這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
效能,HA (高可用),營運等等
「對於一個設計良好的分布式系統來說,單機效能從來不是一個問題 」—— 我
第一篇文章就說了,Codis 採用了 Proxy 的方案,所以必然會帶來單機效能的損失,經測試,在不開 pipeline 的情況下,大概會損失 40% 左右的效能,但是 Redis 本身是一個快得嚇人的東西,即使單機損失了 40% 仍然是一個很大的數字。
另外一個比較好的地方是,Codis 本身是可以充分的利用多核的(Thanks to golang),在多線程用戶端的環境下,不會像 Twemproxy 那樣,撐死就跑滿一個 CPU(當然你可以部署 Twemproxy 的多執行個體,但不就又增加營運成本了嘛。。。)。而且不要忘了,
Codis 可以通過平行擴充多個 Proxy 實現效能成倍的提升,一台機器 CPU 滿了?沒事,再另一台機器起一個 proxy 就是了。某個 Redis 跑滿了?沒事,把一部分資料移轉到另外一個 Redis 執行個體好了。所以,我們從來不認為單機效能能說明什麼。使用 Codis 帶來的最大的好處,是為你的緩衝提供了彈性擴縮容的能力, 而不是追求榨乾底下 Redis 的效能。。。這也是我們選擇了 go 而不是 c 來開發的原因。
我們進行了一個詳細的效能測試,測試的結果如下:Benchmark , 2 proxy 的情況下,單機可以到達 20w 的 QPS.
HA (Redis HA, Proxy HA)
對於Redis HA, 我個人是蠻糾結的,仔細用過的 Codis 的同學會發現,在某個 server group 的 master 死掉的時候,雖然 server group 裡可以有多個 slave,但是這些 slave 並不會自動的提升為 master。
當然實現這個功能並不困難,但是我認為這種情況應該讓管理員清楚,並手動的操作,因為如果自動的切到 slave 上,這段時間原 master 還沒同步到 slave 上的資料有可能就會衝突,如果 master 又複活了,解決資料的衝突是一個麻煩的問題,與其自動的操作,不如給用戶端返回失敗 (也只是這個機器負責的slots 會失敗,如果執行個體足夠多,不會出現致命的單點故障), 交給管理員去處理。
Proxy HA, 在決定使用無狀態的 proxy 的方案時,就自動帶來了高可用性的保證,這個不多說,有很多種做法,比如智能DNS,HAProxy,用戶端串連 ZooKeeper 做 Proxy 的串連池等。
說到可營運性,Codis 幾乎一切的操作都是通過 codis-config 發起的,codis-config 在做任何操作的時候,都會到 ZooKeeper 拿一個鎖,以保證是唯一的操作執行個體,這也是防止路由表被改壞的一個措施,尤其是設定遷移這樣比較敏感的操作,必須保證不能同時有多個 slots 處於遷移狀態,所以,在整個遷移的過程中,是不釋放鎖的。
那麼如果在遷移一個 slot 的過程中,我強行殺死 (kill -9) codis-config 不讓它釋放遷移的鎖會怎麼樣?會死結嗎?
答案是:不會的。
為什嗎?首先,在遷移過程中的任意階段打斷,都是沒有問題的,因為對底層的 redis 來說,遷移的只是一個個原子的 key,我殺掉了 codis-config ,只是停止了髮指令的人,導致這個 slot 沒有全部遷移乾淨而已, 在 Zk 上看到的也只是一個長期處於遷移狀態的 slot (由於 codis-config 被殺了,沒人去發遷移命令,也不會在遷移完成的時候修改slot狀態了). 此時如果用戶端有請求,proxy 也會主動的發一個 migratekey 先強行的把這個key遷移過來,所以對用戶端也是沒有影響的。
而且 codis-config 還有一個特性,每次啟動的時候,都會在 Zk 上註冊一個臨時節點, 記錄自己的 pid 和機器名,而且上的所有的鎖,都會帶上機器名和pid的簽名,每次啟動的時候,會掃描一下所有未釋放的鎖,如果這個鎖的所屬進程的臨時節點已經不存在了,就會直接把這個鎖釋放掉,於是避免了死結的狀態。
只不過在下次開始新的遷移任務之前,需要先將這個未遷移完成的slot遷移掉,方法是發起一個遷移任務,from slot 和 to slot 都寫成這個slot id, new group id設成之前未完成的那個任務的group id, 這個是為了保證系統能重新回到一個乾淨的狀態,再進行下一個新的遷移任務。這是一個人為加的限制。
在實際使用 Codis 的過程中,我們為一些特別懶的業務 (懶得重建緩衝),開發了叫做redis-port的工具,它的作用是,作為一個假的 slave,掛在一個redis後面,然後將master的資料同步回來,sync 到 codis 叢集上,所以,業務方根本無需重建緩衝,直接同步處理完後,換個地址重啟服務就OK了, 這也是問哦們在公司內部推動項目特別輕鬆的一個殺手鐧。 :P
除此之外,Codis 還有一個和其他後端中介軟體不太一樣的地方:它不僅提供了完整的 Unix CLI interface, 居然有一個炫酷的 dashboard 和完整的 RESTful API ! 恩,沒錯,而且在實際的生產環境中,我們發現使用 dashboard 更安全,更少誤操作,更方便,而且系統的即時狀態都非常清晰。這年頭,要沒有一個好看的 dashboard 都不好意思開源了。。。(嘛,其實是我剛學 AngularJS,技癢了。。。不過最終效果還不錯)。
三篇文章差不多寫完了,有什麼問題可以在 github 上 post issue, 也可以在微博上聯絡我 @Dongxu_Huang 或 @goroutine, 當然,郵件也可以,同時如果你對豌豆莢基礎架構組有興趣,也歡迎你把簡曆發過來,我們是 Golang 的重度使用者 :) 也是開源的狂熱分子,有機會希望和你一起工作, email: huangdongxu1987@gmail.com
announce一下 Codis 的作者們:
@Dongxu_huang (aka c4pt0r): codis-config, 分布式協議實現,資料移轉及auto rebalancer,Dashboard, unit-test…
@goroutine (aka ngaut): codis-proxy, Redis 協議解析, router,zkhelper, unit-test…
@spinlock9: redis patch, redis-port, benchmark, test …