重写 Facebook.com

25556 2020-05-18 01:22

Facebook 从最初的 PHP 服务端渲染网站发展至今已经 16 个年头,Web 开发的外部环境已经是沧海桑田,在老构架上开发新 Feature 的成本也越来越高。为了得到“App 的体验”以及卓越的性能, 他们用 React 和 Relay 重写了整个主网站,基于两个原则 —— “尽可能少尽可能早”、“提升开发体验以服务用户体验”。

将这两个原则应用到四个主要元素 (CSS,JavaScript,数据,导航) 上,得到如下经验

  1. 改进 CSS
    1. Atomic CSS: 使用 Build 时生成的原子类 CSS 将首页的 CSS 减少 80% - 因为这种 CSS 的条目的数量接近 log N——样式的总量是随着独特的样式增长的,而不是跟着代码里面写的样式和 feature 的数量增长的。我们 Uber 就使用的 Styletron 来做这件事情。
    2. CSS-in-JavaScript: 用类似于 stylex.create({}) 这种方法来为组件生成 Style,跟组件放到一起,以增加可删除性,让样式更容易被维护。
    3. 统一使用 rem 让缩放的时候体验更好, Build 时自动将 px 转化成 rem.
    4. 使用 CSS 变量实现黑暗模式
    5. 使用 HTML 内嵌 SVG 作为图标,解决图标延迟渲染的一闪问题
  2. 分拆 JavaScript 以优化性能
    1. 增量式加载代码,把 500 KB 的总代码,分成 50KB Tier 1,150KB Tier 2, 300KB Tier 3,分别对应骨架内容、首屏内容 、非 UI 内容,然后按需加载。
    2. 只在需要的时候加载实验代码
    3. 根据数据加载相应的代码,比如图片数据加载图片组件、视频数据加载视频组件
    4. 给 JavaScript 的大小做预算,严格监视代码尺寸的变化
  3. 尽早载入数据
    1. 预加载:用 Relay 能够立马知道首屏所需要的数据,在下载代码的同时,也 stream 这些数据
    2. 用 stream 的方式减少 round trips
    3. 延迟加载现在不需要的数据
  4. 定义路由 map 以加速导航
    1. 尽早获得路由的定义
    2. 尽早预先获取资源,在 hover 或者 focus 的时候就开始了,导航变化之后,如果还没有加载完,先用 React Suspense transitions 保留当前页面,只有加载完之后才真正切换。这样就能跟标准的浏览器体验保持一致。
    3. 并行下载代码和数据。通常是先下载代码再下载数据,这样是串行的;FB 让数据和代码在一个 round trip 里面同时下载。

如何吃得好活得久?

25960 2020-05-06 16:19

根据美国医药期刊的研究,在 42000 个百岁病人的解剖实验中发现,大部分人死于疾病而不是单纯的老死。不健康的饮食习惯是生病的最大的原因。似乎人们现在还不够重视饮食对身心健康的影响。而实际上这种影响不容忽视。当你被不同的健康类信息所包围,辨别有效信息变得十分困难。《何以不死》一书提供了八条被科学验证过的健康建议。

采用以植物为基础的饮食

植物性饮食被证实是现代美国社会最健康的饮食方式。1980年代,中国-康奈尔-牛津联合项目在针对中国人民饮食的研究中发现,动物性食品消费比例最低的贵州省,在65岁以下的男性冠心病的死亡率是最低的。不仅如此,植物性的饮食还可以帮助病人恢复疾病。生活医学方面的先驱 Nathan Pritikin 和 Dean Ornish 通过让晚期心脏病的患者食用植物性饮食,发现了这种饮食在减缓症状方面的显著效果 —— 比如,病人们的动脉粥样硬化溶解得比通常更快了。

多吃水果,尤其是莓果类

健康的饮食应该包括每天四份水果,其中之一应该是浆果。每天多吃一份水果,患慢性阻塞性肺病的风险就会降低24%。这其中浆果尤为重要,因为它有改善肝脏功能,抗癌能力和免疫系统的能力。在2014年,一项研究显示,14名病人在食用黑树莓九个月后,遗传性结肠息肉患的息肉数量显著减少。

蔬菜是不可或缺的

蔬菜在预防疾病方面十分重要。羽衣甘蓝又被称作“蔬菜中的女王”,因为它可以降低胆固醇。在2008年的研究中表明,30名高胆固醇病人三个月中每天喝三到四杯甘蓝汁。他们的有益胆固醇水平显著升高,这甚至和跑 300 英里的效果相同。而像花椰菜和卷心菜这样的十字花科蔬菜则可以帮助提高肝脏和肺功能。所以人们的五份蔬菜饮食中,最好有两份是叶类蔬菜(羽衣甘蓝,甜菜,芝麻菜等)。另外两份可以是胡萝卜,甜菜根或者蘑菇类。最后也不能忘记花椰菜和卷心菜这样的十字花科蔬菜。

豆类和全麦类食品对身体健康有益

美国癌症研究所建议每餐吃豆类,因为它富含无动物蛋白还有膳食纤维。对于不喜欢这类的人, 白豆或者斑豆也是个好选择,它们不仅可以减少有害的胆固醇,减缓糖类吸收速度,还可以放松胃。和豆类一样,人们也最好可以三餐都摄入全麦食品。2015年的一项研究证明食用全谷物的人们更加长寿。

摄入更多有营养的坚果和种子类食物

全球疾病负担研究所发现,在全世界范围内,食用过少的种子和坚果已经成为导致死亡和残疾的第三大饮食风险。其实一份巴西坚果就可以达到和汀类药物一样的胆固醇降低水平。坚果和种子类食物可以解除体内过多的铁而产生的毒素,还可以增加骨密度。我们可以在日常饮食中加入奇亚籽、罂粟籽、南瓜籽和葵花籽。将它们加入到日常饮食调味汁中也是一个很好的选择。

在食物中加入草本植物和香料

草本香料不仅会让食物更美味,还可以有效预防癌症等疾病。它们是所有食物品类中含抗氧化成分最高的。2010的一项实验中,服用了藏红花得阿尔茨海默病患者得到了比服用安慰剂更好的效果。不仅如此,丁香和肉桂等香料含有的特殊酶,还可以改善抑郁症。值得注意的是,姜黄是所有香料中效果对抗癌症最好的。但是因为它在体内的时效很短,所以搭配黑胡椒会更好帮助延缓消散和加强吸收。然而富有草酸盐的姜黄并不适用于所有人,患有胆结石和肾结石者应该限制摄入量。

将饮用水作为饮料的第一选择

理论上来说,人们每天应该至少摄入五杯12盎司的饮料。而这其中,纯净水是最好的选择。尽管有许多关于喝八杯水的传言,但这个理论其实并没有科学支持。我们每天摄入的水还可以来自水果蔬菜。除了水之外,咖啡和茶也是不错的选择,因为它们都在不同程度上对身体健康有益处。Tufts University的一项研究发现,茶能够降低高血压早期患者的血压。

四步搞定理性决策

31225 2020-04-30 15:05

普通人在生活和工作中做决策机会并不多,也很难有机会练习和提高自己的决策水平。大多数人的决策靠直觉,而理性的决策靠流程。《决断力》一书提出了理性决策的四步流程 —— 为了提高做出最佳决策的概率,我们需要 1.拓宽选项、2. 用事实检测假设、3. 跳出自己看自己、4. 为错误决定做准备。

1.拓宽选项

人们误以为做选择就好像考试做选择题,从三五个选项里选一个那么简单,然而世界之大,选项又何止三五?例如,一家广告设计公司在工作中会同时开展多个设计方案,并在每一轮的反馈中将有用的元素组合为最终的设计成果。这样不仅使工作效率变得更高,还也节省了决策的耗时成本。除此之外,还可以参考他人面对类似状况时做的选择的基础比率。沃尔玛的创始人 Sam Walton,就在职业生涯中一直密切关注着竞争对手的动向,从而适时调整决策。作为决策者,应要在创造更多选项和参考他人的选择中,找到最佳方案。

2. 用事实检测假设

如果说实践是检验真理的唯一标准,那么做最终决策前的实验,也能相对准确地预估出想法能否奏效。很多公司已经从仅仅通过面试来雇佣员工,发展到要求他们通过短时间的试用期,正是为了避免面试的局限性,从而增加决策的准确性。我朋友买房前去房子里试着住了一个晚上,发现能够听到火车的鸣笛,从而花小的成本避免了大的失误。

3. 跳出自己看自己

当决策者过于沉浸于自己的观点时,往往会忽略外部视角。所以,想要判断决策的可能结果应该去调查决策所基于的客观情况。可以考虑从更远的时间和空间的维度来衡量选项,比如安迪格鲁夫假装自己是新的 CEO 从大门进来然后砍掉内存条业务;李开复假设明天有两份报纸头条报道自己的两个选择——有情但不公正、公正但无情,继而作为领导者选择了要公正。

4. 为错误决定做准备

对于决策的结果,你应该考虑到最好和最坏的两种结果,以便了解自己所处的位置。如果情况接近最糟糕的结果,你也能及时地做出反应。除此之外,还可以建立一种能使你意识到自己行为的信号,从而削弱行为的惯性,及时地纠正决策。值得注意的是,为了提高做决策的速度,贝索斯认为,决策与决策之间生而不平等,绝对不要一碗水端平 —— 可逆的决策用轻量级的决策过程。

需求分析

  • 分布式的区块链记账和智能合约系统
  • 节点之间相互不大信任,但是又需要激励他们互相合作
    • 交易不可逆
    • 不依赖可信的第三方
    • 保护隐私,透露最少信息
    • 不依赖中心化的权威证明一笔钱不能花两次
  • 假设性能不是问题,暂不考虑如何优化性能

构架设计

具体模块和他们之间的交互

基础层(P2P 网络、加密算法、存储)

P2P 网络

分布式系统有两种实现方式:

  • 中心化的 lead / follower 的分布式,比如 Hadoop, Zookeeper 这种系统,结构比较简单,但是对 lead 要求高
  • 去中心化的对等 (P2P) 网络分布式,比如 Chord, CAN, Pastry, Tapestry 算法组织起来的网络,结构比较复杂,但是更加平等

因为前提条件是节点之间不大信任,所以选择 P2P 的形式。具体到如何组织 P2P 的网络呢?一个典型的去中心化的节点和网络是这样保持连接的:

  1. 基于 IP 协议,节点上线占用某个地址 hostname/port,利用初始化的节点列表广播自己的地址,利用这些初始的 hop,试图向全网 flood 自己的信息
  2. 接到广播的初始节点一方面存下这个 neighbor,一方面帮助他 flooding,不相邻的节点收到后 NAT 穿墙加 neigbhor
  3. 节点之间 anti-entropy 随机互相 heartbeat 发出最新的带着类似 vector clock 的信息,保证能够持续更新对方那里自己的最新信息

我们可以利用既有的库,比如 libp2p,来实现网络模块。网络协议的选择见Crack the System Design Interview: Communication.

加密算法

在互相不大信任的分布式系统中,一笔转账如何在不泄漏自己秘密信息的同时证明这个转账是自己发起的呢?非对称加密:一对公钥和私钥对应一个”所有权”。Bitcoin 选择 secp256k1 参数的 ECDSA 椭圆曲线加密算法,为了兼容,其他链也基本选择同样的算法

为什么不直接把公钥作为转账的地址呢?隐私问题,交易的过程应该尽可能少地泄漏信息,用公钥的哈希作为“地址”可以避免接收方泄露公钥。甚至,人们应该避免反复使用同一个地址

具体到账本的账户,有两种实现方式 UTXO vs. Account/Balance

  • UTXO (unspent transaction output) ,例如 Bitcoin,类似于复式记账的 credit 和 debit,每个 transaction 有都有 input 和 output,但是除了 coinbase 每个 input 的前面都连着上一个的 output。尽管没有账户的概念,但是取一个地址对应的所有的未花完的 output,就是这个地址的余额。
    • 优点
      • 精准:类似于复式记账的结构,让流水账非常精准地记录下所有的资产流动。
      • 保护隐私和抗量子攻击:如果用户经常换地址的话。
      • 无状态:为提高并发留下了可能。
      • 避免重放攻击:因为重放会找不到 input 对应的 UTXO
    • 缺点
      • 记录了所有的交易,复杂,消耗存储空间。
      • 遍历 UTXO 花时间。
  • Account/Balance,例如 Ethereum,有三个主要的 map:account map, transaction map, transaction receipts map. 具体在实现上,为了缩减空间、防篡改,使用 merkle patricia trie (MPT)
    • 优点
      • 省空间:不像是 UTXO 那样,一个 transaction 把多个 UTXO 联系起来
      • 简单:把复杂性让给了 script
    • 缺点
      • 需要用 nonce 解决重放问题,因为 transaction 之间没有依赖性

值得一提的是 “区块 + 链” 的数据结构本质上来讲,就是 append-only 的 Merkle tree,也被称为 hash tree.

存储

因为本身 UTXO 或者 MPT 这种结构就充当了索引,加上分布式的时候,为了让每个节点运维更加简单,一般做 data persistence 的时候倾向于选择 in-process database 随着节点的程序能够直接跑,比如 LevelDB, RocksDB。

因为这种索引并不是通用的,所以你并不能像是 SQL 数据库那样查询,这也为数据分析提高了门槛,优化时需要专门做一个 indexer 服务,比如 etherscan。

协议层

现在我们有了可以操作的基础层后,在这层之上,我们需要一个比较通用的逻辑操作的协议层。根据这个区块链的使用需求,可以像是微内核构架那样,插拔具体的逻辑处理模块。

比如最常见的记账:在最新的 block 高度收到了一些 transaction,组织起来建立如上一层构架所说的数据结构。

为每一个业务逻辑写一个原生模块然后更新所有节点的代码不大现实,用虚拟化的方法解耦这一层?答案是能够执行 smart contract 代码的虚拟机。在互不可信的环境中,不能让客户白执行代码,所以这个虚拟机最独特的功能可能是计费。

基于 contract 的 token 比如 ERC20 和 native token 的区别,导致在不同的 token 捣腾的时候很麻烦,于是就出现了 Wrapped Ether 这种 token.

共识层

协议层算出来执行的结果之后,如何跟其他的节点达成一致呢?有如下一些常见的激励大家合作的机制:

  • proof of work (POW): 用 hash 的碰撞挖 token,耗电量大不环保
  • proof of stake (POS): 用质押的 token 挖 token
  • delegated proof-of-stake (DPOS): 选人民代表用质押的 token 挖 token

在激励机制的基础上,节点中谁的链最长听谁的,两群人互不待见就分叉。

同时,有这样一些一致性协议让大家达成共识(也就是大家要么一起都干,要么一起都不干)

  • 2PC:大家都依赖某一个 coordinator:coordinator 问大家:要不要干?只要有人回复不干,那么 coordinator 跟所有人都说“不干”;否则都说干。 这样的依赖会导致,如果 coordinator 在第二个阶段的中间挂了,有些节点会不知道怎么办 block 在那里,需要人工干预重启 coordinator。
  • 3PC:为了解决上述问题,加一个保证大家在干之前都知道所有人要干还是不干的阶段,出了错就重新选 coordinator
  • Paxos:上述的 2PC 和 3PC 都依赖某一个 coordinator,如何干掉这个 coordinator 呢?用“大多数(2f + 1 里至少 f+1)”来取代,在两步中,只要大多数取得一致,最后就能取得一致。
  • PBFT (deterministic 3-step protocol): 上述的做法容错率还是不够高,于是有了 PBFT。用来保证大多数(2 / 3)节点要么都同意,要么都不同意的算法,具体做法是三轮投票,每轮有至少大多数(2 / 3)节点同意,最后一轮才 commit block 。

在具体的应用中,关系数据库大多用 2PC 或者 3PC ;Paxos 的变种有 Zookeeper 的实现,Google Chubby 分布式锁的实现,Spanner 的实现;区块链中,Bitcoin, Ethereum 是 POW,新的 Ethereum 是 POS,IoTeX 和 EOS 是 DPOS。

API 层

Public API choices

研究表明:有导师的人表现更好,在事业上进步更快,甚至连在工作和生活中,获得的满足感也更多。而导师也会从中受益,在教人的同时自己也会有收获。尽管有那么多的好处 —— 76%的职场人士认为导师对成长很重要 —— 但超过54%的人没有这种关系。

这里问题往往是人们不知道如何找到导师,如何建立关系。以下九个步骤可以帮到你。

1. 明确自己的目标和具体需求

拿出笔和纸,写下你的职业目标。确保这些目标是 SMART 的。然后,列出实现这些目标的最大障碍。这些具体的需求将帮助你决定应该寻找什么样的导师。也许你需要发展新的技能,也许你需要扩大在某一特定领域的人脉,也许你需要建立进行艰难谈判的自信心。在了解你想成为什么样的人,以及成为这样的人的差距和机会在哪里之后,你就能确定导师如何才能真正帮助你。

2. 写出你理想中的导师的 “工作要求”

在知道你的目标以及你需要怎么来实现这些目标之后,思考一下导师如何帮助你。描述出能够帮助你抓住最大机会/驾驭挑战的导师类型。具体地说,也许你需要导师帮助你完成一个项目,或者为你介绍特定行业内某一层次的人,或者指导你度过艰难的谈判。在你的工作要求中,一定要包括"为什么"--就像公司希望潜在的应聘者了解他们公司的大方向一样,解释一下为什么指导你将会有更大的收获。当你与潜在的导师联系时,告诉他们你的工作要求,这样他们就会知道你为什么要找导师,从而更愿意提供帮助(第四和第五点中会提到)。

3. 通过你的二度关系寻找导师

导师可以来自任何地方。他们可以是来自你LinkedIn人脉,专业领域的人脉,也可以是你在会议上认识的人。重要的是,虽然人们肯定很忙,但被邀请成为导师是一种巨大的赞美。人们可能会说不,但这依然是一种积极的交流,你要勇于去尝试,去提出请求,即使你认为对方不可能腾出时间给你。答不答应就让他们自己来判断。

4. 提出要求(并保持请求简单)

第一次、第二次,甚至第三次请别人做导师时可能会让你有点尴尬。你很可能也从来没被邀请过做别人的导师,也没有教过别人如何为自己提出这个请求。拥抱这种不舒适的感觉。询问并没有什么坏处,但要慢慢来。邀请别人进行第一次对话来了解他们的工作和兴趣。一旦你们对对方有了更多的了解,如果有一致的意见,那么就可以提出更多的请求,请求对方做你的导师。反之,如果用长长的邮件去请求不一个不认识的人做导师,那就不太容易被接受。

5. 进行第一次谈话

你与潜在导师的第一次谈话有两个目标。首先,你要确定这个人是否是你正确的导师人选。然后,搞清楚他们是否对指导你保持开放态度。你如何进行对话将取决于你自己,但总的来说,你会想做以下几件事:

  • 让对方感到轻松。去一个对他们来说方便的地方,准备好咖啡(或茶),使会议没有压力。

  • 花时间去了解对方。最好让导师多讲话,而你的讲话时间少于30%。

  • 一开始就请求对方给你一些小的帮助也是可以的。事实上,它甚至可能会帮助你建立关系。

  • 提出一个明确的请求:“我很喜欢这次谈话。如果一个月内我在目标上取得一些进展,能不能再跟你跟进?”

  • 表示感谢,然后再次通过邮件跟进,再次表示感谢。

6. 从简开始

对于你的下一次会面,要在上次见面的基础上进行跟进,并保持简单。一旦对方确认会与你再次见面,就发送一封邮件提出议程,并暗示要建立长期关系。一个例子是"在我们下次聊天时,我希望我们能快速回顾一下上次的话题,然后我想进一步扩展这个话题。我会准备好一些具体的问题,我觉得你可以帮我回答。"

7. 确立一个结构化责任的过程,并签订导师协议

在你们进行了一两次简单的谈话之后,试着提出一个更正式的要求:这个人愿意在接下来的六个月里,每月和你一起坐下来谈一次,直到你实现目标或解决问题为止吗?如果愿意,那么可以考虑写一份简单的单页文件,列出你们要在这六个月里完成的任务。虽然这可能看起来有点小题大做,但它将使你和你的导师更加清楚地知道目标是什么。它还将帮助你为每次会议确定明确的会议内容。你可以建议说:“我真的很感谢你的时间和帮助,我很想确保自己能充分利用时间。我在想,我可以准备一份简单的文件,把我的目标、我对你的承诺,以及我希望在未来三个月内实现哪些阶段性的目标分享给你。我想这将有助于让我担起责任,有准备地来参加我们的谈话。你同意吗?”

8. 持续跟进并道谢

每次见面后,你一定要发一封感谢信。除此之外,当你的导师关系结束后,你应该继续说谢谢。我曾经有一个被指导者在我们合作两年后给我发过电子邮件。这让我高兴不已。作为回报,我帮她建立一些新的有趣的联系,而她也是如此。所以请记住,请人帮忙是可以的,但一定要确保表示适当的感谢!

9. 选用合适的工具

为了能够更高效地践行上述步骤,我给自己专门做了一套工具关系io - 端到端加密的个人 CRM,免费开放注册现已开源,欢迎 star

下载 硅谷io App

关注互联网创业,用移动 App ,随时随地收藏和复习好文章


产品coderoma OJ关系io CRMBeancount.io 账本OneFx.JS 框架
社区 系统设计与构架群 系统设计英文电报群 BBS
订阅方式 RSS Github 推特 邮件