# 讀寫分離
當一個公司業務不斷擴展,用戶量大量增加,原來使用的數據庫很可能就撐不住了。那么可以
- Scale-in,擴充硬件的性能,但是很可能用戶量繼續增長,增加的性能很快就吃光了。
- 讀寫分離:數據庫撐不住了,無非就是讀寫量過大,特別是有一些復雜的查詢比如最近24小時最熱門的產品等。需要很復雜的SQL語句,運行起來當然是慢。
但是為了讀寫分離,需要把數據庫拆分為master庫和Slave庫,
市面上主要的關系數據庫都支持**數據復制功能**,所以可以把一個數據庫拆分為Master和Slave兩種角色,**寫操作**在主上,由Master服務器向其他Slave服務器進行同步。
而**讀操作**以及數據分析等離線操作都在Slave服務器上進行。
我們知道互聯網的很多應用都是讀的,這樣有多個Slave可以**負載分擔**一下,又可以保證數據的可用性和正確性。

但是相應的原有的**應用代碼**也需要修改,必須改為寫數據用master庫,讀數據的時候使用slave庫,就相當于重寫了。
# 復雜查詢
但是就算重寫了代碼,發現性能還是無法得到明顯的提升,原因仍然是使用了太多復雜的查詢,比如說有很多表在聯接,在[數據庫(四),數據庫組成部分](http://www.cnblogs.com/dy2903/p/8438206.html)里面我們都說過,聯接非常消耗性能。
那么我們可不可以**單獨用一張表**來存放過去24小時的熱門產品啊,這樣只需要使用簡單的SQL就能搞定。
也就是說,一套單一的數據庫表對報表、搜索、事務等不同的行為是不適當的。
現在的表是為了**新增、修改數據**而設計的,對復雜查詢不適合。
但是我們還需要考慮這個查詢庫如何更新的問題,還就是可能不是實時更新,我們能否忍受這種延遲的問題。
# CQRS
能否忍受延遲的問題需要從業務上來看,比如過去24小時熱門的極品,一點點過時的信息沒有太大的影響,只要求最終一致即可。
我們可以使用CQRS(Command Query Responsibility Segregation),也就是增刪改的**命令與查詢責任分離**。

在CQRS中,強調的是讀(Query)寫(Command)分離,因為用戶讀到的數據通常是過時的,那么為什么還需要從數據庫讀一遍呢,可以直接建立一個讀數據源。可以是Cache,可以是XML、JSON等。
那之前提到的怎么**更新**的問題怎么解決?可以使用Event,也就是事件,比如某個產品賣出去了,可以發布一個事件,修改原有的Read Model。
這樣就通過事件機制把同步變成了異步。
最后,這種方法最好只在**復雜查詢**中用,原來的簡單查詢依然在關系型數據庫里面取。為什么呢?因為引入一種新的技術需要付出代價,比如同步變異步了,還需要事件機制,我們不能只看到新技術的優點,而看不到缺點了。

# 主要參考
[從讀寫分離到CQRS,張大胖是如何解決性能問題的?](http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513844&idx=1&sn=82a70f987fdf56a47debffc995addfec&chksm=80d67b37b7a1f221187a97af92ec7fed5b31d1fae3831d7b59b28c34935afb7765cb1b7a4fb0&scene=21#wechat_redirect)