codis,codis3.0和其他
如不少人所看到的,Codis 發布了3.0的alpha版 。這個版本本來叫2.1的,但是因為改動比較大,直接改名叫3.0了。Codis發布至今一年有余,我參與Codis項目也有大半年,在這個繼往開來的好日子里,有必要講講很多想法——只代表我個人的想法。
Codis是Redis的集群解決方案,這意味著他基于Redis,繼承了Redis的部分優點,也繼承了部分缺點。換句話說,讓Redis得到了水平擴展的能力,但依舊無法突破Redis自身的諸多局限性。以及在Github中的提問中發現,其實不少人并沒有嚴格區分Redis和Codis,會覺得這是一種東西,所以很多時候問的問題其實是Redis的問題。
在Codis之前、之后,除了在client自行實現分片邏輯之外,無外乎還有兩種方案,twemproxy和官方的redis cluster,我在《 離職系列文章之redis cluster使用經驗 》中提到過redis cluster的一些問題,不過現在回頭來看并沒有完全解釋清楚。前不久在Codis的 README 中我添加了一個表格,如下:
Codis | Twemproxy | Redis Cluster | |
---|---|---|---|
resharding without restarting cluster | Yes | No | Yes |
pipeline | Yes | Yes | No |
hash tags for multi-key operations | Yes | Yes | Yes |
multi-key operations while resharding | Yes | – | No( details ) |
Redis clients supporting | Any clients | Any clients | Clients have to support cluster protocol |
這個對比就比較容易看出,Codis和Twemproxy是一類,限制更少,但是Twemproxy不支持動態增減節點,而Codis和Twemproxy的主要區別就是加了這個功能——也就是遷移數據。Codis的遷移的核心就是一個二階段提交,因而從分布式系統的角度上講,或者說對于懂分布式系統的人來說,Codis不復雜,更不“牛逼”。但他就是解決了人們的需求,同時又開源(估計不少公司會有類似的內部輪子),所以火了起來。
說實話,很多搞分布式系統的人,很容易覺得別人做的東西不牛逼(沒技術含量),也很容易覺得自己做的東西不牛逼(俗稱天天打雜),因為牛逼的事情確實不多,更多的是邊邊角角的雜事,但是不做又不行,或者說不做就丟飯碗了。一個牛逼的東西從把需求轉化成系統設計(或者抄現成設計)到寫代碼再到根據線上情況各種優化/bugfix,看上去只有第一步是牛逼的,但是實際上實現的過程是最復雜也最需要堆人力的,后續優化也很苦,可能跟一個bug跟了幾天最后改代碼就幾行(換成個不太懂技術的老板直接就無法衡量工作量了是不是)。而且同樣的設計不同的人實現結果也可能有很大不同,比如把GFS實現成HDFS就各種屎……所以作為一個比較實用主義、既無潔癖也無各種邪教心思的人,我更看重一個東西的利弊是如何取舍的、一個東西的利是不是我想要的、一個東西的弊是不是我不那么在乎的。
那目前的Codis(2.0)有啥弊端呢?dashboard與proxy的通信通過zk,導致一些小公司不得不單獨為了Codis而搭一套zk,也導致一旦與zk的連接出了問題,整個Codis會非常脆弱。后者經常會導致Proxy掛掉,雖然可以通過各種優化細節防止他掛掉又避免導致數據出問題,但是最終還是顯得比較繞。于是@斯賓洛克 重新設計和實現了這套邏輯,直接讓dashboard和proxy互相通過http協議通信,不需要zk了——當然依然允許proxy注冊在zk上從而實現服務發現的功能,動態增加新的可用的proxy、剔除不響應的proxy。
于是Codis3.0應運而生。
簡單的一句“互相通過http協議通信,不需要zk了”,自然是需要很多工作量的。而且之前zk除了負責通信之外還負責持久化存儲集群的節點信息,這個無論怎么改永遠是要有的。因此3.0需要在配置中指定如何做持久化的存儲,理論上只要實現了對應的CRUD接口就可以存儲在任何地方,比如zk、mysql等等。這樣哪怕依然把集群狀態數據存儲在zk,對zk的依賴也減輕了很多。當然,因為zk一般至少三臺所以相當于互相備份并且高可用,如果存儲在mysql就要自行考慮可用性和備份的問題了,否則mysql成了單點的話,mysql掛了甚至數據丟了對Codis會造成比較大的影響。
而“很多工作量”意味著其邏輯比之前復雜,潛在的bug可能也比較多,因而alpha里正式版發布還有一點距離。當然,一般來說正式版發布只意味著作者認為它是生產環境可用,不代表真的一定可用……現在無論數據庫還是編程語言,用戶的測試總是會比團隊內部的測試發現更多的問題,而用戶是基本上不會主動地用beta/rc來幫忙測試的,只會等真靠譜的了再升級。所以一個大版本的第一個正式小版本基本上都會有各種bug,因此大多數人都在等第二個小版本,比如x.y.1,這樣x.y.0的問題可能就更難發現,從而x.y.1改了一些bug還會有另一些bug,最終導致惡性循環,大家先等.1,過幾個大版本發現不靠譜就都等.2……Go現在就是類似的情況,Cassandra之前是這個情況而且大家是直接去等.5……為了避免這種情況Cassandra現在引入了個人覺得更坑爹的tick-tock機制……Codis2.0的第一個正式版是2.0.2,目前也更新到了2.0.11,其中有不少版本對于一些特定場合是比較嚴重的bug,也說明我們很難保證在一開始就十分完美。總之,3.0還有一些工作要做,也很難定義一個發布的時間表。并且即使3.0發布正式版之后,可能也不會馬上取代目前的master分支(對應2.0版本)作為用戶的默認選擇,2.0也不會很快EOL因為3.0的改動比較大導致一些用戶可能不會很快升級。
那3.0之后呢?目前來說還沒看到明確的改進方向。總體來說應該會進入一種比較穩定的狀態——回復問題、改bug,不加新feature。Codis作為豌豆莢內部的服務,開源之后各種用戶累計在生產環境搭的集群數量遠超豌豆莢內部搭的數量。但維護Codis的人畢竟是拿豌豆莢的工資的,在Codis比較成熟之后依然拿著公司的工資全職搞Codis的話對公司是一種浪費(畢竟俺們是創業公司),對個人也是一種摧殘(所謂的進入打雜階段),更可能導致因為時間充裕為了改進而改進去做各種偽需求。最近幾個月實際上Codis的開發人力只有“1.1個人”,斯賓洛克把全部精力投入3.0的設計與實現,而我做公司內的其他項目用少部分工作+業余時間(我凌晨回復issue是因為我在家睡得晚,不是因為加班……)回復用戶的問題、改可能出現的2.0的bug。等3.0徹底搞完估計會從1.1降格到0.2-0.3左右,除非我和他都跑路了不然Codis是一定會一直維護的。當然假設以后真跑路了而且內部沒有其他人接手的話,遇到bug我們也不會見死不救的……
當然在此有必要強調一下,希望各位理解: Github的issue 是Codis官方唯一指定的討論問題的場所。建議所有用戶仔細閱讀文檔( Doc目錄的全部內容 )后再提問,并適當搜索老的問題,以節省大家的時間。在其他社區、社交網站提問,我們無法保證第三方的回答是正確、及時、有時效性的。之所以沒有開設任何國內部分程序員很喜歡的QQ群主要是因為QQ群并不是一個很好的討論問題的場所,要么容易出現日經月經重復問題,要么容易水。此外不接受任何微博私信/email點對點提問,因為這些內容無法被搜索引擎收入也無法讓其他人看到,更容易導致每天見到重復的問題以降低我們的效率。理論上似乎Codis可以試水類似“付費VIP服務”,也就是“企業版”,不過這事情沒那么簡單……
最后,長期來看我依然覺得Redis并不是一個“好的數據庫”,因為他的數據容量只取決于內存大小,持久化功能有一定局限性,同時又是單線程。并且我也依然覺得,內存數據庫作為緩存存熱數據、磁盤數據庫存全部數據的方案,在長期來看是會被“帶緩存功能的磁盤數據庫”取代的。因為只有兩者合體才真正解決一致性的問題,同時業務上用著也更簡單。當然另一個方向是“帶冷數據持久化到磁盤功能的內存數據庫”,這個方向我不看好,因為目前的內存數據庫各方面還是和各種磁盤數據庫差太多,而磁盤數據庫其實已經普遍帶各種程度的緩存功能,只不過單機的性能(緩存命中的話)和用C寫的內存數據庫有差距,并且redis的數據結構比較豐富。但是一旦性能差距逐漸縮小(比如很多新的數據庫或者云服務廠商自己提供的數據庫都是用C/C++寫的),并且支持更多的數據結構,最終就可以徹底替換掉內存數據庫了。
來自: http://yangzhe1991.org/blog/2015/12/codis3-0/