消除架構(gòu)中的單點(diǎn),這一篇就夠用了
系統(tǒng)架構(gòu)中,為什么會存在單點(diǎn)?
- 存在設(shè)計缺陷,出現(xiàn)了單點(diǎn);
- 能大大簡化系統(tǒng)設(shè)計,有意為之;
哪些地方可能存在潛在單點(diǎn)?

典型互聯(lián)網(wǎng)高可用架構(gòu):
- 端,通過DNS,由域名拿到nginx的外網(wǎng)IP;
- 反向代理,nginx是后端入口;
- 站點(diǎn)應(yīng)用,典型的是tomcat或者apache;
- 服務(wù),典型的是dubbo提供RPC服務(wù)調(diào)用;
- 數(shù)據(jù)層,典型的是讀寫分離的db架構(gòu);
在這個互聯(lián)網(wǎng)架構(gòu)中,站點(diǎn)、服務(wù)、數(shù)據(jù)庫的從庫都容易通過冗余的方式來保證高可用,但:
- nginx是一個潛在的單點(diǎn);
- 數(shù)據(jù)庫寫庫也是一個潛在的單點(diǎn);
哪些例子,因?yàn)樵O(shè)計需要,有意設(shè)置的單點(diǎn)?
先看GFS(Google File System)架構(gòu)的例子:

GFS的系統(tǒng)架構(gòu)里主要有這么幾種角色:
- client,就是發(fā)起文件讀寫的調(diào)用端;
- master,這是一個單點(diǎn)服務(wù),它有全局視野,掌握文件元信息;
- chunk-server,實(shí)際存儲文件的服務(wù)器;
在GFS系統(tǒng)里,master是一個單點(diǎn)服務(wù)。
Map-reduce系統(tǒng)里也有類似的角色,協(xié)調(diào)全局的master就是單點(diǎn),它的存在,能夠大大的簡化系統(tǒng)架構(gòu)設(shè)計。
不管是設(shè)計缺陷,還是有意為之,像nginx,db-master,GFS-master這樣的單點(diǎn)服務(wù),會存在什么問題呢?
兩個大問題:
- 高可用問題:單點(diǎn)一旦發(fā)生故障,服務(wù)就會受到影響;
- 性能瓶頸:單點(diǎn)不具備良好的擴(kuò)展性,單點(diǎn)的性能上限往往就是整個系統(tǒng)的性能上限;
第一大問題:“高可用”問題通常怎么優(yōu)化?
shadow-master是一種很常見的解決單點(diǎn)高可用問題的技術(shù)方案。
shadow-master,顧名思義,它只是單點(diǎn)master的一個shadow(影子):
- master工作時,shadow-master只備份;
- master出現(xiàn)故障時,shadow-master會自動變成master,繼續(xù)提供服務(wù);
shadow-master它能夠解決高可用的問題,并且故障的轉(zhuǎn)移是自動的,不需要人工介入,但不足是它使資源的利用率降為了50%,業(yè)內(nèi)經(jīng)常使用keepalived+vip的方式實(shí)現(xiàn)這類單點(diǎn)的高可用。

以GFS的master為例,master正常時:
- client會連接正常的master,shadow-master不對外提供服務(wù);
- master與shadow-master之間有一種存活探測機(jī)制;
- master與shadow-master有相同的虛IP;

當(dāng)發(fā)現(xiàn)master異常時:
shadow-master會自動頂上成為master,虛IP機(jī)制可以保證這個過程對調(diào)用方是透明的。
除了GFS與MapReduce系統(tǒng)中的主控master,nginx和數(shù)據(jù)庫的主庫master亦可用類似的方式來保證高可用:

- 兩個主庫設(shè)置相互同步的雙主模式;
- 平時只有一個主庫提供服務(wù);
- 異常時,虛IP漂移到另一個主庫,shadow-master變成主庫繼續(xù)提供服務(wù);
第二大問題:“性能瓶頸”問題通常怎么優(yōu)化?
有時候,單點(diǎn)設(shè)計是有意為之,此時單點(diǎn)的性能(例如GFS中的master)有可能成為系統(tǒng)的瓶頸,那么,減少與單點(diǎn)的交互,便成了存在單點(diǎn)的系統(tǒng)優(yōu)化的核心方向。
如何來減少與單點(diǎn)的交互,有兩種常見的方法:
- 批量寫;
- 客戶端緩存;
如何利用“批量寫”減少與單點(diǎn)的交互,提升整體性能?
舉一個單點(diǎn)“ID生成器”的例子,很多公司會利用數(shù)據(jù)庫的auto-inc-id,來作為一個嚴(yán)格遞增的ID生成工具。

其交互流程是:
- 調(diào)用方需要ID;
- 插入記錄,利用auto-inc-id來生成和返回ID;
此時,ID生成的并發(fā)上限,取決于單點(diǎn)數(shù)據(jù)庫的插入性能上限。
如何利用“批量寫”提升性能呢?

優(yōu)化如下:
- 增加一個服務(wù),每次從DB拿出100個id;
- 調(diào)用方需要ID;
- 服務(wù)直接返回100個id中的1個,100個分配完,再訪問DB;
這樣一來,每分配100個才會寫數(shù)據(jù)庫一次,分配id的性能提升了100倍。
如何利用“客戶端緩存”減少與單點(diǎn)的交互,提升整體性能?
還是舉GFS文件系統(tǒng)的栗子。

GFS文件讀取的流程如下:
- GFS的調(diào)用客戶端client要訪問shenjian.txt,先查詢本地緩存,miss了;
- client訪問master問說文件在哪里,master告訴client在chunk3上;
- client把shenjian.txt存放在chunk3上記錄到本地的緩存,然后進(jìn)行文件的讀寫操作;
- 未來client要訪問文件,從本地緩存中查找到對應(yīng)的記錄,就不用再請求master了,可以直接訪問chunk-server;
這類緩存的命中非常非常高,在99%以上(因?yàn)槲募淖詣舆w移是小概率事件),這樣與master的交互次數(shù)就降低了100倍。
批量寫,客戶端緩存,對性能的提升也有極限,單點(diǎn)性能優(yōu)化還有沒有其他方法?
無論怎么批量寫,客戶端緩存,單點(diǎn)畢竟是單機(jī),還是有性能上限的。
水平擴(kuò)展,才能夠無限的提升系統(tǒng)性能。
以nginx為例,如何來進(jìn)行水平擴(kuò)展呢?

第一步的DNS解析,只能返回一個nginx外網(wǎng)IP么?

通過DNS輪詢,在DNS-server,一個域名可以配置多個IP,每次DNS解析請求,輪詢返回不同的IP,就能實(shí)現(xiàn)nginx的水平擴(kuò)展,擴(kuò)充負(fù)載均衡層的整體性能。
數(shù)據(jù)庫單點(diǎn)寫庫也是同樣的道理,在數(shù)據(jù)量很大的情況下,可以通過水平拆分,來提升寫入性能。
內(nèi)容較多,簡單總結(jié):
- 單點(diǎn)系統(tǒng)存在的問題:可用性問題,性能瓶頸問題;
- shadow-master是一種常見高可用方案;
- 減少與單點(diǎn)的交互,是單點(diǎn)系統(tǒng)優(yōu)化的核心方向,常見方法有:批量寫,客戶端緩存;
- 水平擴(kuò)展,才能做到理論上的無限性能;
知其然,知其所以然。
思路比結(jié)論更重要。





























