可靠构建服务几原则
前两天写了一篇「也谈DID与过度设计」,主观原因是当时的确有感,还有一个原因是突然想起了之前的一本书「高扩展网站性能的50条原则」。 这本书在很久之前我就看过,但是并没有什么意思,最近温习了一遍,颇有感触。正所禅宗大师青原行思提出的参禅三境界:
参禅之初,看山是山,看水是水;禅有悟时,看山不是山,看水不是水;禅中彻悟,看山仍然山,看水仍然是水。
原则一:简单到不能再简单
这个可见之前写的也谈DID与过度设计。
原则二:拆分与隔离
拆分之前要清楚的两件事:
- 抑制拆分的冲动。拆分固然好,但是过细或者不合理起到的反作用远远大于你期望的正作用。
- 谁的数据谁做主。不要试图在「组织结构」上将共享一份数据的团队拆分。
拆分与扩展
进行拆分无非是为了扩展与隔离。
拆分或者扩展的思路通常是在三个方面:
- 横向。通过克隆方式进行扩展。通过冗余的方式增加服务能力。如对于存储系统的加从操作,对于服务的加机器扩容操作。横向拆分通常可以解决如数据库写流量相对小,读流浪很大的情景。
- 纵向。通过拆分不同的东西进行扩展。通过类别的划分来降低服务复杂度,数据一篮子的风险。关于这方面有一个按照「动词」与「名词」进行拆分的实践。以订单服务为例,按照动词「交易」与「退款」拆分为「正向交易」「反向退款」服务;按照名词「交易数据」「退款数据」拆分为交易库与退款库。
- Z轴方向。通过拆分相近的东西进行扩展。如数据按时间分片。
大白话的讲,如果单以数据为例。上面的三原则可以声情并茂的概括为「一拉二切」,拉就是冗余副本,切分两刀,一刀分表分库,一刀按时间等维度进行分片,这两刀主要解决流量和数据量的问题。
原则三:Do not repeat yourself
拓展视野
工具定律(锤子定律):如果你只有一把锤子,你会把每个问题都看成钉子。
不要为了 0.01% 的错误做 100%的冗余
原则四:敬畏线上
放弃QA
尽可能的降低对QA的依赖。在技术层面,这就相当多了一层依赖,如果不能做到完全放弃,那么至少把强依赖变为弱依赖。
用以下的方案来做这件事:
- 完善的单元测试,在这个过程中,将所有的外部依赖mock掉,不要试图让你的下游提供环境与数据。Mockito可以帮助你。
- 有效的灰度与验证方案。
- 留条后路给自己。
给自己留条后路
这件事可以用最简单的方式(如统一配置服务)来实现,做到优雅的回退。
容错与降级
用至少可用代替完全可用。
单点故障
两个维度避免单点问题:
- 服务部署,多机房多机器
- 服务设计,避免出现被过多服务依赖的中心节点,与多个系统串联。
这种串联问题的避免可以用一句话来概况,串联变并联,同步变异步,尽量容错。
异步通信
异步是为了解耦,避免故障传播。以下几点可作为是否采用异步通信的标准:
- 不稳定的依赖,经常不可用。避免让对方的故障传染到自己的服务。
- 依赖的接口耗时较长。避免让IO过多占用线程资源。
万能的空间分析原则
利用在任务管理上,如任务的四象限管理法:X轴是重要程度,Y轴是紧急程度。
利用在风险收益分析上,X轴是风险,Y轴是收益。
利用在服务拆分上的三轴原则。
利用在如RMF(recency/frequency/monetization)分析上,如数据归档的判断上,针对于「低价值、从不访问」的数据「清除」处理,针对于「高价值、总是访问」的数据提供更好的「硬件资源」。