數據庫(七),讀寫分離到CQRS
讀寫分離
當一個公司業務不斷擴展,用戶量大量增加,原來使用的數據庫很可能就撐不住了。那麽可以
Scale-in,擴充硬件的性能,但是很可能用戶量繼續增長,增加的性能很快就吃光了。
讀寫分離:數據庫撐不住了,無非就是讀寫量過大,特別是有一些復雜的查詢比如最近24小時最熱門的產品等。需要很復雜的SQL語句,運行起來當然是慢。
但是為了讀寫分離,需要把數據庫拆分為master庫和Slave庫,
市面上主要的關系數據庫都支持數據復制功能,所以可以把一個數據庫拆分為Master和Slave兩種角色,寫操作在主上,由Master服務器向其他Slave服務器進行同步。
而讀操作以及數據分析等離線操作都在Slave服務器上進行。
我們知道互聯網的很多應用都是讀的,這樣有多個Slave可以負載分擔一下,又可以保證數據的可用性和正確性。
但是相應的原有的應用代碼也需要修改,必須改為寫數據用master庫,讀數據的時候使用slave庫,就相當於重寫了。
復雜查詢
但是就算重寫了代碼,發現性能還是無法得到明顯的提升,原因仍然是使用了太多復雜的查詢,比如說有很多表在聯接,在數據庫(四),數據庫組成部分裏面我們都說過,聯接非常消耗性能。
那麽我們可不可以單獨用一張表來存放過去24小時的熱門產品啊,這樣只需要使用簡單的SQL就能搞定。
也就是說,一套單一的數據庫表對報表、搜索、事務等不同的行為是不適當的。
現在的表是為了新增、修改數據
但是我們還需要考慮這個查詢庫如何更新的問題,還就是可能不是實時更新,我們能否忍受這種延遲的問題。
CQRS
能否忍受延遲的問題需要從業務上來看,比如過去24小時熱門的極品,一點點過時的信息沒有太大的影響,只要求最終一致即可。
我們可以使用CQRS(Command Query Responsibility Segregation),也就是增刪改的命令與查詢責任分離。
在CQRS中,強調的是讀(Query)寫(Command)分離,因為用戶讀到的數據通常是過時的,那麽為什麽還需要從數據庫讀一遍呢,可以直接建立一個讀數據源。可以是Cache,可以是XML、JSON等。
那之前提到的怎麽更新的問題怎麽解決?可以使用Event,也就是事件,比如某個產品賣出去了,可以發布一個事件,修改原有的Read Model。
這樣就通過事件機制把同步變成了異步。
最後,這種方法最好只在復雜查詢中用,原來的簡單查詢依然在關系型數據庫裏面取。為什麽呢?因為引入一種新的技術需要付出代價,比如同步變異步了,還需要事件機制,我們不能只看到新技術的優點,而看不到缺點了。
主要參考
從讀寫分離到CQRS,張大胖是如何解決性能問題的?
數據庫(七),讀寫分離到CQRS