接上文。html
Cache Money雖然解決了數據的讀取性能瓶頸;但開發大網站數據庫面臨的問題遠不至讀壓力。mysql
首先是容量。算法
上千萬/億的數據量並不罕見,單一物理數據庫服務器即使單純承擔寫壓力也會是瓶頸。更況且Cache Money僅僅是在理想情況下才能夠作到數據庫0讀。緩存服務器更新,新增查詢,複雜查詢等等都還會形成讀壓力。sql
比較常見的作法是採用分表,也就是所謂的Sharding,把數據按照必定的規則,分別存儲至多臺數據庫服務器上去。數據庫
其次是變更。緩存
業務需求是不可預測的;不管一開始數據庫表結構定義得如何完備,總會有新需求出來,須要對錶結構作調整才能夠實現。服務器
數據量過了百萬以後,每次對生產服務器作alter table/create index等調整都是痛苦的經歷。數據結構
針對容量與變更這兩個問題,FriendFeed提出的schema-less database design給出了一個至關漂亮的解決方案。app
強烈推薦閱讀FriendFeed的原文。less
FriendFeed的方案大體是這樣:
FriendFeed的方案至關聰明,數據自己結構及其簡單,sharding很容易作。寫/讀壓力一會兒就分佈出去。
blob列用於序列化(數據甚至是先zip過再存,CPU強勁,磁盤IO是瓶頸),因此結構能夠隨時變化;只須要保證序列化算法能夠兼容不一樣版本便可。
而靈活的序列化,偏偏是Facebook Thrift所解決的!
(還記得一開始使用Memcached作object cache時採用了Thrift作序列化麼?)
先不考慮Sharding分佈方案,在MoSonic中將各個類定義爲相似下面的結構:
之後要修改數據結構,直接改Thrift的定義文件,而後從新生成代碼就成。properties列中存的數據可能跟最新的結構不一直,但Thrift並不要求嚴格的匹配(BinaryFormatter則否則),它會自動忽略那些不符合的列;而一但Object被從新存入,數據就又會被從新序列化完整。
======================
FriendFeed的分佈式方案要求表主建是uuid,而cache money卻要求全部表必需要有自增的ID主健。
這其實不是衝突,把database_name + table_name + id當作一個uuid便可。
而FriendFeed的分佈式索引,跟cache money中Vector Cache有殊途同歸之妙。
都是根據查詢條件作處理/sharding。
以前爲MoSonic添加Vector Cache,已經須要判斷查詢的表名/查詢條件;符合即查詢緩存;這裏套用FriendFeed的方案則變成,符合即查詢分佈式索引!
執行select id from users where age=18 limit order by id desc 0,10時
邏輯變成這樣:
插入數據時,以前僅是更新Vector Cache,如今則需多一步去插入索引表。
實際運行中,由於是先插入數據表,同步更新Vector Cache,後續的插敘已經會命中緩存;索引表的更新實質變成是備份,能夠異步插入。
Thrift / Cache Money / Schema-less Database Design其實是三個不一樣團隊爲了解決不一樣方面的技術問題而作出的方案,但糅合進MoSonic中時,我感到的不是衝突,而更多的是一種不謀而合的美妙。
下篇會繼續講更多一些細節。