架構-1:高性能架構之讀寫分離和分表分庫
架構-2:高性能架構之NoSQL和緩存
架構-3:高性能架構之單機高性能和負載均衡
架構-4:高可用架構之存儲高可用
架構-5:高可用架構之Paxos和Raft
架構-6:高可用架構之一緻性雜湊演算法和資料分片
架構-7.高可用架構之接口級故障
關系型資料庫的局限
NoSQL不是指No SQL而是指No only SQL,關系型資料庫非常成熟于強大,但是依然存在一些問題,是以NoSQL時關系型資料庫的一種補充而不是替代。
- 1.隻能存儲行結構而不能存儲更複雜的資料結構,比如某個屬性是數組,關系型資料庫隻能把數組存放到另外一個表或者解析成字元串存儲。
- 2.表結構不易修改。由于強制每一行資料個列都是一樣的,對于資料量很大的表來說,修改一個字段都是非常耗時的,而且容易出現錯誤。
- 3.大資料量下的I/O,可能導緻鎖住表很久,即使隻是針對某一列進行操作。
- 4.全文搜尋效率低。使用like關鍵字搜尋文本時,效率非常低,一般不推薦使用。
NoSQL解決方案
針對關系型資料庫的問題,NoSQL提供了一些解決方案。
- Redis:提供Key-Value存儲,而且提供了string,hash,list,set.sorted set,bitmap等複雜的存儲資料結構。而且Redis性能非常高,提供了過期功能,經常被作為緩存使用。但是由于Redis時基于記憶體操作的,盡管提供了持久化的操作,但是依然不能完全保證資料不丢失。
- MongoDB:文檔型資料庫。MongoDB以Json的格式存放資料,并不強制要求每一行資料的格式是一緻的,可以存放複雜的資料結構。适用于電商遊戲等屬性複雜的産品。
- HBase:列式資料庫,差別于關系型資料庫的行資料庫,HBase是以列存儲的資料庫。這樣在大資料量僅操作某一列的情況下,I/O效率非常高。
- Elasticsearch:全文搜尋引擎,針對關系型資料庫全文搜尋困難的問題,Elasticsearch使用反向索引,提供了高效的全文搜尋。
高性能緩存
緩存幾乎是高性能首先想到的方案,對于以下的情況,緩存能夠極大的提升整體的性能。
- 讀多寫少的業務:絕大多數線上業務都是都是寫少,如微網誌,淘寶,微信,讀業務占據了90%的業務量,幾十萬條的select對于mysql會産生極大的I/O壓力。而諸如Redis和Memcache等基于記憶體的高性能的緩存能夠解決這一難點。
- 經過複雜計算後的資料:比如淘寶的搜尋,大部分的搜尋都落在搜尋條件的前10頁,而擷取這些資料需要進行很多運算。把前10頁的結果緩存下來,能夠極大的提升搜尋的效率。
緩存帶來的問題
緩存穿透
緩存穿透是指大量的查詢命中緩存中不存在的值,導緻大量的查詢都落在資料庫上,造成資料庫崩潰。産生這種情況的原因有兩種:一種是惡意查詢,如黑客故意大量的查詢某個不存在的ID。一種是生成耗時較長,導緻在緩存沒有更新好之前,發生大量的更新緩存的請求直接落在了資料庫上。
針對第一種情況,解決方案是針對不存在的值,緩存一個null值或者預設值,過期時長可以設定短一些,比如5分鐘,這樣可以防止對應的值被更新為存在的值而導緻資料無法查詢。
針對第二種情況,可以使用解決緩存雪崩的解決方案。
緩存雪崩
緩存雪崩是指高通路量的緩存過期,導緻大量的更新緩存的請求直接落在了資料庫上。針對這種情況和生成耗時長的緩存,解決方案是不要通過通路直接更新緩存而是通過中介去更新緩存。
解決方案:
- 1.使用隊列更新,而不是直接更新。當發現緩存失效後,并不直接去通路資料庫更新緩存,而是發生一個請求到隊列,由隊列去更新,然後循環判斷資料是否被更新,如果已經更新了則直接傳回資料。隊列可以過濾重複的請求,不用大量的通路資料庫。缺點是,如果緩存更新速度比較慢(比如需要大量運算的結果),會導緻通路響應時間變長。
- 2.使用背景更新。背景運作一個定時任務去更新失效的緩存,這樣防止在請求到來時才去更新緩存導緻響應時間變長。但是有可能存在已經失效的緩存但是定時任務還未啟動的情況,是以要配合方案1一起使用。
- 3.雙Key政策。儲存兩個key1和key2,當key1失效時,發送一個更新請求到隊列,然後直接傳回key2的值。然後隊列把key1和key2同時更新。優點是沒有通路延遲,缺點是占用了兩倍的緩存。
緩存熱點
比如某明星發了一個戀愛的微網誌,這個微網誌會被大量的通路,如果隻有一個緩存,會導緻大量的請求都落在該緩存上,導緻這個緩存伺服器崩潰。解決方案是針對可能是熱點的緩存,複制副本到多個緩存伺服器上,通過Nginx之類的進行負載均衡。比如微網誌超過100W粉絲的使用者的每條微網誌都會有100份副本緩存。
其中一個細節是:副本不要設定相同的過期時間,會導緻緩存雪崩。即使已經做了緩存雪崩的處理,這種超高的通路量也會對更新緩存的服務造成極大的壓力。