跳到主要内容

再窥iOS架构模式

· 阅读需 4 分钟

我们为什么要在架构上费心思?

答案是:为了减少在每做一个功能的时候所耗费的人力资源

移动开发人员会在以下三个层面上评估一个架构的好坏:

  1. 各个功能分区的职责分配是否均衡
  2. 是否具有易测试性
  3. 是否易于使用和维护
职责分配的均衡性易测试性易用性
紧耦合MVC
Cocoa MVC❌ V和C是耦合的✅⭐
MVP✅ 独立的视图生命周期一般:代码较多
MVVM一般:视图(View)存在对UIKit的依赖一般
VIPER✅⭐️✅⭐️

紧耦合MVC

传统 MVC

举一个例子,在一个多页面的网页Web应用程序中,当你点击一个链接导航至其他页面的时候,该页面就会被全部重新加载。该架构的问题在于视图(View)与控制器(Controller)和模型(Model)是紧密耦合的。

Cocoa MVC

Cocoa MVC 是苹果公司建议iOS开发者使用的架构。理论上来说,该架构可以通过控制器(Controller)将模型(Model)与视图(View)剥离开。

Cocoa MVC

然而,在实际操作过程中,Cocoa MVC 鼓励大规模视图控制器的使用,最终使得视图控制器完成所有操作。

实际的 Cocoa MVC

尽管测试这样的耦合大规模视图控制器是十分困难的,然而在开发速度方面,Cocoa MVC是现有的这些选择里面表现最好的。

MVP

在MVP中,Presenter与视图控制器(view controller)的生命周期没有任何关系,视图可以很轻易地被取代。我们可以认为UIViewController实际上就是视图(View)。

MVC 的变体

还有另外一种类型的MVP:带有数据绑定的MVP。如下图所示,视图(View)与模型(Model)和控制器(Controller)是紧密耦合的。

MVP

MVVM

MVVM与MVP相似不过MVVM绑定的是视图(View)与视图模型(View Model)。

MVVM

VIPER

不同于MV(X)的三层结构,VIPER具有五层结构(VIPER View, Interactor, Presenter, Entity, 和 Routing)。这样的结构可以很好地进行职责分配但是其维护性较差。

VIPER

相较于MV(X),VIPER有下列不同点:

  1. Model 的逻辑处理转移到了 Interactor 上,这样一来,Entities 没有逻辑,只是纯粹的保存数据的结构。
  2. ==UI相关的业务逻辑分在Presenter中,数据修改功能分在Interactor中==。
  3. VIPER为实现模块间的跳转功能引入了路由模块 Router 。

如何使用HTTP协议向移动设备传输视频? HTTP Live Streaming (HLS)

· 阅读需 2 分钟

为什么需要这样一个协议?

使用HTTP直播流的移动视频播放服务有以下问题:

  1. ==手机的内存和外存有限==。
  2. 受制于不稳定的网络连接以及不同的带宽,需要==在传输过程中动态调整传输视频的质量==。

解决方法

  1. 服务器层面:在典型的设置中,编码硬件接受音视频输入,将其编码为H.264格式的视频和ACC格式的音频,然后将他们以MPEG-2格式流输出。
    1. 其后通过一个软件分流器将原始输出流分割为一系列短媒体文件(长度可能为10s的.ts文件)。
    2. 分流器同时也会维护一个包含所有媒体文件列表的索引文件(.m3u8格式)。
    3. 将以上步骤生成的媒体文件和索引文件发布在网络服务器上。
  2. 客户端层面:客户端读取索引,然后向服务器顺序请求所需要的媒体文件,并且流畅地将各个短媒体文件的内容播放出来。

架构

HLS Architecture

设计Facebook图片存储系统

· 阅读需 3 分钟

为什么 Facebook 要自己做图片存储?

  • PB级别的Blob数据量
  • 传统的基于NFS的设计(每个图像存储为文件)都存在元数据瓶颈:庞大的元数据严重限制了元数据命中率。
    • 以下是细节解释:

对于图片应用程序,图片的权限等大多数元数据是无用的,从而浪费了存储空间。然而,更大的开销在于,必须将文件的元数据从磁盘读入内存中才能找到文件本身。虽然对于小规模存储来说这微不足道,但当乘以数十亿的照片和数PB的数据时,那么访问元数据将是吞吐量的瓶颈。

解决方案

通过把数以十万计的图像聚集到单个Haystack存储文件中,从而消除了元数据负荷。

结构

Facebook Photo Storage Architecture

数据布局

索引文件(用于快速加载内存)+ 包含很多图片的haystack存储文件。

索引文件布局

index file layout 1

index file layout 2

储存文件

haystack store file

CRUD操作

  • 增: 写入存储文件,然后==异步==写入索引文件,因为建立索引并不是关键的步骤。
  • 删: 通过在标志字段中标记已删除的位来进行软删除。通过紧凑操作执行硬删除。
  • 改: 在更新时,只能追加 (append-only),如果遇到了重复的键,应用程序可以选择具有最大偏移量的键去改和读。
  • 查: 读取操作(偏移量,健,备用键,Cookie 以及数据大小)

用例

上传

Photo Storage Upload

下载

Photo Storage Download

学会被信任——教唆杀人只需要72分钟

· 阅读需 10 分钟

传统智慧告诉我们:失去信任很快,获得信任很慢。但实际上并非如此。英国的著名心理魔术师达伦·布朗在真人秀《达伦·布朗:就范 Derren Brown: The Push》中,利用了种种心理学的技巧,在 72 分钟内,就令一个善良的普通人走向极端,犯下可怕的谋杀案,把老人推下大楼。

故事的主人公是一位性格温和的阳光男孩克里斯。他虽然看上去普普通通,但实际上他是通过实验精心挑选出来的,社会屈从行比较强。克里斯自己其实并不知道实验和节目的目的,而且节目组告诉他落选了,让他放松警惕。节目组找人扮演位高权重的慈善项目的高管,联系到克里斯的公司商量合作计划,并邀请他帮助举办活动。为了尽快树立权威感,这个活动还找来了大量名人的背书,并且让克里斯端酒、拎包、拿衣服训练他的服从感。

然后案件开始了,在只有高管和克里斯的情况下,一位大财主老头突然“暴毙”,高管劝说克里斯顾全大局,让克里斯帮忙藏尸,他照做了。后来,活动主持人"误"以为克里斯是那位大财主,让他上台演讲,他照做了。高管让克里斯转移尸体,他照做了。再后来,财主的妻子说财主有昏睡症,一犯病就像死了一样,于是高管和克里斯松了一口气。不料节目组安排老头“醒来”用自己口袋里的录音器“知道了”他”死“后发生的一切,囔囔着要告发二人,不给慈善机构捐一分钱。最后的最后,害怕失去工作和坐牢的高管让克里斯把老头干掉,把正好坐在高台边缘的老头推下去,他……并没有照做。实际上,节目总共测试了4个人,而克里斯是唯一没有服从“杀人”决定的人。

另外三个“杀人”的受试者会如此之快的就范,说明了信任的建立可以如此之快,让人竟然能够听从他人的命令去“杀人”。

那么,信任是如何建立起来的呢?心理学家早就有了答案:==信任等于能干加亲和==。比如在上面撺掇杀人的真人秀里面,高管就是表现得高端大气上档次,整个慈善活动也是得到了社会名流的加持。

这其中,==“能干”并不是要求人真的能干,而是只要表现得能干就可以了==。比如,说话的时候使用大量的专业名词,就会让人听上去像个专家。还有更肤浅的方法是外表,开豪车戴袖扣,让人记住你。其中的关键在于得体,不要穿着西装领带去修理厂给别人修车,不要穿着拖鞋短裤去慈善晚宴给别人演讲。

还有一个增强“能干程度”的好方法是言行一致,没有人会相信言行不一的伪君子(hypocrite)。要是活在《笑傲江湖》里,我当然也会信任一言九鼎的真小人田伯光,不会信任道貌岸然的伪君子岳不群。

能干程度,或者说是“可置信度”(credibility),在人与人之间、在组织与组织之间,是可以交互促进的。人和组织都可以通过加入一些排他性的协会来增加置信度,而高置信度的人和组织加入这个协会,这个协会的置信度就会更高。我感觉,中国有句古话,叫做“花花轿子人抬人”,讲的可能就是这个道理吧。交互产生可信度的最最直接的产物,就是钱;交互产生可信度的过程越是容易,人们越是互相信任,产生的交易就越多,整个社会的经济水平就越高。

很多国家领导人给人以“能干”的印象,但是很冷酷,所以为了增强民众的信任感,每一任的美国总统都会养狗。比如奥巴马,他在搬进白宫之前从未养过狗,他的女儿玛丽亚甚至对狗过敏,但他还是不得不养狗,毕竟,很少有什么东西能够像毛茸茸的、摇着尾巴的、眼睛水汪汪的狗狗们更能够让人感到亲和的了。

这就是“亲和”的力量。哈佛大学的一位教授做了一个实验发现,雨天的时候在车站躲雨,向陌生人借电话,只要在接电话之前先说了,“我对雨感到抱歉”,借到的概率就会高四倍。研究发现,==甭管这种道歉有多浮夸,这一方法在生活中对于促进合作屡试不爽==。

实际上,==想要表现亲和力,通常而言,说话的方式比说话的内容更重要,肢体语言比口头语言更重要==。坐得更近、身体前倾、握手、拍肩膀、碰到手肘,都能够有力地表达合作的意向。==就信任而言,面对面地交流是非常非常重要的==。我有一位耶鲁的同学,在拿到优步的 Offer 之后直接找老板面谈薪水,一路谈到总监,竟然就多拿到了几千股的股票!

除了这两个维度之外还有什么方法增强信任感呢?答案是暴露无关紧要的弱点。比如“不小心”把笔掉在地上,“不小心”说了一个冷笑话,“不小心”泼了咖啡。

能人能够通过有意识地犯一些小错误或者暴露一些小秘密让自己更合群。哥伦比亚大学MBA项目就曾经有一位高管学生,她有意识地往自己写的邮件里面加错别字,让她显得更平易近人,而她跟同事之间的关系就真的变得更好了。这就解释了为什么日本的职员喜欢下班后一起喝醉酒然后去五音不全地唱卡拉OK。因为你表现得越烂,你与朋友的羁绊就越深。

当然,暴露弱点要小心。==在暴露弱点之前,人们得认可你真的能干==。其次,==弱点必须是无关紧要的==。外科医生手抖,橄榄球四分卫黄油手,这些都不是弱点,是硬伤。

所以,总的来说,==信任=能干+亲和+暴露无关紧要的弱点==。要想被人信任,首先你得值得被信任,你得是能干的人;你不仅要能干,还得得跟对方建立连接,所以你需要表现得亲和。而建立信任之后,如果表现得太过于能干了、太过于面面俱到了,会给人造成距离感和威胁感,所以你还得暴露无关紧要的弱点,拉近和对方的距离。

iOS 架构模式再探

· 阅读需 3 分钟

为什么要关注架构?

答案:为了降低每个功能的人力资源成本

移动开发者从三个维度评估架构。

  1. 功能参与者之间责任的平衡分配。
  2. 可测试性
  3. 易用性和可维护性
责任分配可测试性易用性
紧耦合 MVC
Cocoa MVC❌ VC 耦合✅⭐
MVP✅ 分离的视图生命周期一般:代码较多
MVVM一般:由于视图依赖 UIKit一般
VIPER✅⭐️✅⭐️

紧耦合 MVC

传统 MVC

例如,在一个多页面的 web 应用中,一旦点击链接导航到其他地方,页面会完全重新加载。问题在于视图与控制器和模型紧密耦合。

Cocoa MVC

苹果的 MVC 理论上通过控制器将视图与模型解耦。

Cocoa MVC

实际上,苹果的 MVC 鼓励 ==庞大的视图控制器==。而视图控制器最终负责所有事情。

现实中的 Cocoa MVC

测试耦合的庞大视图控制器是困难的。然而,Cocoa MVC 在开发速度方面是最佳的架构模式。

MVP

在 MVP 中,呈现者与视图控制器的生命周期无关,视图可以轻松模拟。我们可以说 UIViewController 实际上就是视图。

MVC 变体

还有另一种 MVP:带有数据绑定的 MVP。正如你所看到的,视图与其他两个之间存在紧密耦合。

MVP

MVVM

它类似于 MVP,但绑定是在视图和视图模型之间。

MVVM

VIPER

与 MV(X) 相比,VIPER 有五个层次(VIPER 视图、交互器、呈现者、实体和路由)。这很好地分配了责任,但可维护性较差。

VIPER

与 MV(X) 相比,VIPER

  1. 模型逻辑转移到交互器,实体作为简单的数据结构保留。
  2. ==与 UI 相关的业务逻辑放入呈现者,而数据修改能力放入交互器==。
  3. 引入路由器负责导航。

键值缓存

· 阅读需 4 分钟

KV 缓存就像一个巨大的哈希映射,用于减少数据访问的延迟,通常通过

  1. 将来自慢速且便宜介质的数据转移到快速且昂贵的介质上。
  2. 从基于树的数据结构的 O(log n) 索引转为基于哈希的数据结构的 O(1) 进行读写。

有各种缓存策略,如读穿/写穿(或写回)和旁路缓存。总体而言,互联网服务的读写比为 100:1 到 1000:1,因此我们通常会优化读取。

在分布式系统中,我们根据业务需求和上下文选择这些策略,并在 CAP 定理 的指导下进行选择。

常规模式

  • 读取
    • 读穿:客户端通过缓存层从数据库读取数据。当读取命中缓存时,缓存返回;否则,它从数据库获取数据,缓存后再返回值。
  • 写入
    • 写穿:客户端写入缓存,缓存更新数据库。缓存在完成数据库写入后返回。
    • 写后 / 写回:客户端写入缓存,缓存立即返回。在缓存写入的背后,缓存异步写入数据库。
    • 绕过写入:客户端直接写入数据库,绕过缓存。

旁路缓存模式

当缓存不支持原生的读穿和写穿操作,并且资源需求不可预测时,我们使用这种旁路缓存模式。

==在这种模式下仍然存在缓存变脏的可能性。== 当满足以下两个条件时,会发生这种情况:

  1. 读取数据库并更新缓存
  2. 更新数据库并删除缓存

缓存放在哪里?

  • 客户端
  • 独立层
  • 服务器端

如果数据量达到缓存容量怎么办?使用缓存替换策略

  • LRU(最近最少使用):检查时间,驱逐最近使用的条目,保留最近使用的条目。
  • LFU(最不常用):检查频率,驱逐最常用的条目,保留最常用的条目。
  • ARC(自适应替换缓存):其性能优于 LRU。通过同时保留最常用和频繁使用的条目,以及驱逐历史来实现。(保留 MRU + MFU + 驱逐历史。)

谁是缓存使用的王者?

Facebook TAO

设计 Facebook 照片存储

· 阅读需 2 分钟

动机与假设

  • PB 级 Blob 存储
  • 传统的基于 NFS 的设计(每张图像存储为一个文件)存在元数据瓶颈:大的元数据大小严重限制了元数据命中率。
    • 进一步解释元数据开销

对于照片应用,大部分元数据(如权限)未被使用,从而浪费了存储容量。然而,更重要的成本在于,文件的元数据必须从磁盘读取到内存中,以便找到文件本身。在小规模上这并不显著,但在数十亿张照片和 PB 级数据的情况下,访问元数据成为了吞吐量瓶颈。

解决方案

通过将数十万张图像聚合在一个单一的 haystack 存储文件中,消除了元数据开销。

架构

Facebook 照片存储架构

数据布局

索引文件(用于快速内存加载)+ 包含针的 haystack 存储文件。

索引文件布局 索引文件布局 1

索引文件布局 2

haystack 存储文件

haystack 存储文件

CRUD 操作

  • 创建:写入存储文件,然后 ==异步== 写入索引文件,因为索引不是关键的
  • 读取:read(offset, key, alternate_key, cookie, data_size)
  • 更新:仅追加。如果应用程序遇到重复键,则可以选择具有最大偏移量的一个进行更新。
  • 删除:通过在标志字段中标记删除位进行软删除。硬删除通过压缩操作执行。

用例

上传

照片存储上传

下载

照片存储下载

设计 Uber

· 阅读需 3 分钟

免责声明:以下所有内容均来自公共来源或纯原创。这里没有 Uber 机密信息。

需求

  • 针对全球交通市场的打车服务
  • 大规模实时调度
  • 后端设计

架构

uber architecture

为什么选择微服务?

==康威定律== 表示软件系统的结构是组织结构的复制。

单体 ==服务==微服务
小团队和代码库时的生产力✅ 高❌ 低
==大团队和代码库时的生产力==❌ 低✅ 高 (康威定律)
==对工程质量的要求==❌ 高 (不合格的开发人员容易导致系统崩溃)✅ 低 (运行时被隔离)
依赖性提升✅ 快 (集中管理)❌ 慢
多租户支持 / 生产-预发布隔离✅ 简单❌ 难 (每个独立服务必须 1) 构建连接到其他服务的预发布环境 2) 在请求上下文和数据存储中支持多租户)
可调试性,假设相同模块、指标、日志❌ 低✅ 高 (使用分布式追踪)
延迟✅ 低 (本地)❌ 高 (远程)
DevOps 成本✅ 低 (构建工具成本高)❌ 高 (容量规划困难)

结合单体 ==代码库== 和微服务可以带来双方的好处。

调度服务

  • 一致性哈希按地理哈希分片
  • 数据是瞬态的,存在内存中,因此无需复制。(CAP: AP 优于 CP)
  • 在分片中使用单线程或锁定匹配以防止双重调度

支付服务

==关键是采用异步设计==,因为支付系统通常在多个系统之间的 ACID 事务中具有非常长的延迟。

用户资料服务和行程服务

  • 低延迟与缓存
  • 用户资料服务面临为越来越多类型的用户(司机、乘客、餐厅老板、吃货等)和不同地区和国家的用户架构提供服务的挑战。

推送通知服务

  • 苹果推送通知服务(可靠性不高)
  • 谷歌云消息服务 GCM (可以检测可送达性)或
  • 短信服务通常更可靠

名称很重要——绰号狂魔的启示

· 阅读需 5 分钟

我们都知道唐纳德·特朗普是一位非常特立独行的美国总统,不论他政绩如何,我们都不可否认,他的演讲极具感染力。他的说服力在斯科特·亚当斯《以大取胜》一书中有详细论述,而我感觉他演讲中非常有趣的地方在于,他特别喜欢给他的竞争对手取绰号,简直就是绰号狂魔。

比如,他会称希拉里为“骗子希拉里”(crooked Hillary),其他的还有“小马可”(little Marco),“撒谎的泰德”(lying Ted),”低能量杰布”(low-energy Jeb)。结合以下图片,也就是杰布·布什的演讲现场,看到观众们昏昏欲睡的样子,我觉得特朗普说得还是挺在理的。

Low Energy Jeb

名称之重要,它甚至可以决定人的生死,明尼苏达州的13岁女孩瑞秋·爱慕基(Rachel Ehmke),就是因为被霸凌、被称为“荡妇”,而上吊自杀。这不是个案,雪城大学的研究者发现,当人们用蔑称称呼某一类社会群体,这群人的自杀率就会偏高。

人言可畏,在被人恶语相向地时候,我们要学会保护自己。对待蔑称,无外乎有三种应对方法:第一是忽视它。当然如果真的那么容易忽视,就不需要我们额外的重视了。第二是消灭它。比如,Facebook 的首席运营官雪莉·桑德伯格认为应该禁用“bossy”这个词。==广泛而全面地禁用一个词未免太过困难,所以还有第三种选择,就是改变它,这种策略在商业上很常见,比如,“瓦卢杰航空”在一系列的空难发生后,更名为“穿越航空”==。

除了上面三种方式,还有一种更加高级的方式,而其中的关键在于,==名称的含义不是一成不变的,你可以骄傲地夺回蔑称的使用权==。而这种夺回,一方面会令组织内部的成员更加团结,另一方面甚至会形成一种排外的禁区,比如“黑鬼” (negro) 一词,黑人自己可以用,白人不能用;林书豪自己可以用ID ChiNkBaLLa88,ESPN 不能用 chink in the armor (盔甲里的中国佬)。

名称是一件非常重要的武器,它可以伤害人,也可以团结人。以色列的研究者做过这样一个实验,同样的一款游戏,当它叫做“社区游戏”的时候,有72%的人选择合作,而叫做“华尔街游戏”的时候,只有33%的人选择合作。

这一==名称控制感受==的技巧可以应用到实际工作中。哈佛大学的研究者发现,当人们面对公开演讲、唱歌比赛、数学竞赛这类让人有压力的活动的时候,如果能够自己给自己打气,大声说:“我很兴奋!”往往能够达到最佳状态。

这里的洞见在于,==给自己的内在感受取一个合适的名称,去疏导情绪,而不是回避情绪,是处理并利用情绪的最佳方式==。如果我们能够正确地理解坏情绪的来源,比如“我今天回家感到很生气,其实是因为今天的工作实在太糟心”,我们就不会把坏脾气撒在亲友身上,做出亲者痛仇者快的事情了。

区块链技术评审

· 阅读需 8 分钟

什么是区块链?

区块链是一种不可篡改的分布式账本,它是…

  1. 由多个参与方托管
  2. 通过加密算法确保安全
  3. 仅可附加/不可变,因此在数据存储中可验证

它是如何工作的?

区块链是如何工作的

分类:公有链 vs. 私有链 vs. 混合链

  • 公有链:加入网络无需许可。
  • 私有链:加入的权限由中心控制。
  • 混合链:多个参与方控制加入的权限。

你需要区块链吗?

你需要区块链吗?

架构

硬件

硬件

基本工具

基本工具

账本

账本

共识

共识

智能合约

智能合约

APIs

APIs

去中心化应用

去中心化应用

开发


运维


[不支持的查看器]

  1. 硬件:计算资源 = 计算 + 网络 + 存储

  2. 基本工具:P2P 网络 + 加密 + 数据存储(使用数据库或文件系统)

  3. 账本:数据块链 + 特定领域数据模型

  4. 共识:先写共识,后写(工作量证明/权益证明/委托权益证明)/先共识,后写(实用拜占庭容错)

  5. 智能合约:在区块链上运行的有限程序

  6. API:远程过程调用 + 软件开发工具包

  7. 去中心化应用:1)价值转移 2)数据认证 3)数据访问控制

  8. 开发运维:部署、操作、指标、日志

行业

  1. 金融服务

    • 加密货币交易所:币安、Coinbase 等
    • 国际支付:Ripple、Stellar 等
    • 了解你的客户(KYC)/ 反洗钱(AML):Civic
  2. 医疗保健

    • 在提供者、保险公司、供应商、审计员等之间共享数据
  3. 公共部门

    • 资产代币化
    • 公共选举中的透明投票
  4. 能源和资源

    • 交易
    • 在供应商、运输商、承包商和当局之间共享数据
  5. 技术、媒体和电信

    • 数字版权管理和激励内容创作者
    • 确保物联网设备的操作和数据存储安全
  6. 消费品和工业产品

    • 旅行中的忠诚积分计划
    • 文档签署
    • 供应链管理

案例研究:Ripple 用于跨境支付

  • 与 200 多家银行合作
  • 47 万亿美元的跨境支付市场
  • 巨大的麻烦和成本。许多企业无法承担传统跨境支付的高交易费用。
    • 如果没有 Ripple,在某些非洲国家,完成交易可能需要几天时间
      1. 报价汇率
      2. 找到这些跳数的路径
      3. 锁定报价
      4. 验证,KYC,AML 等…
    • 使用 Ripple,A 国的用户购买 Ripple 代币,用 Ripple 支付,然后另一个国家的用户只需提取。只需几分钟,并且在此期间代币价格不会波动太大。

杀手级应用

  • Graphite Docs: 类似于 Google Docs,但数据离开计算机时会加密。
  • Textile Photos: 类似于私人 Instagram 的手机应用。照片被加密并存储在 IPFS 上,这是一个由社区运行的去中心化存储网络。
  • Augur: 网络应用,人们可以对 许多事情的预测进行投注。
  • Blockstack: 开发者构建去中心化应用的工具。
  • D.Tube: 无广告的视频流媒体服务,但内容创作者通过代币获得奖励。类似于 ThetaNetwork 的电子竞技视频。
  • OpenBazaar: 无平台费用的在线市场,由加密货币驱动。

挑战

  • 网络效应。说服用户离开现有的成熟中心化服务是困难的。
  • 隐私与免费服务。人们愿意用加密货币购买服务吗?还是人们愿意为了免费服务而牺牲隐私?
  • 去中心化系统的效率。复杂的去中心化系统与简单的中心化系统之间的对比。