標籤:twemproxy redis cluster twitter open source
在大量使用者大規模使用大型Redis節點的時候,目前從項目本身來看Redis基本上可以說是一個單例的業務。關於這個項目的分布式我有一個很大的想法,在這個想法下,我不需要去對多線程版本的Redis做任何評估:在這個角度上對我來說,一個核就像是一台電腦,所以在多核上擴充就相當於分布在電腦之間的叢集。多執行個體是一個無共用的架構。如果我們找到一個可用的方式來分區,那麼所有事情就合理了。 :-)這也是為什麼叢集會成為Redis在2013年的焦點,並且,最終Redis 2.6的發行資料表現出了很好的穩定性和成熟度等級,現在正是時候來關注Redis Cluster, Redis Sentinel, 以及一些其它期待已久的改進。然而現實狀況是,Redis Cluster目前仍然沒有發布,正式版還需要幾個月的工作。但是我們的使用者已經需要將資料分區到不同的執行個體上來做負載平衡,更重要的是為資料獲得更大的記憶體儲存。目前保底的結局方案是用戶端分區。用戶端分區有很多好處,例如:在用戶端和節點之間沒有中介層,這就意味著它是一個擴充性很好的設定(主要是線性擴充)。然而要穩定的實現(用戶端分區)需要進行一些最佳化,需要一個同步用戶端配置的方式,也需要用戶端支援一致性雜湊或其它分區演算法。有一個重大訊息來自Twitter,世界最大的Redis叢集之一部署在Twitter用於為使用者提供時間軸資料。所以毫不奇怪這篇文章討論的項目來自Twitter Open Source部門。Twemproxy---Twemproxy是一個快速的單線程代理程式,支援Memcached ASCII協議和更新的Redis協議: 它全部用C寫成,使用Apache 2.0 License授權。 項目在Linux上可以工作,而在OSX上無法編譯,因為它依賴了epoll API.我的測試環境為Ubuntu 12.04案頭版。 好吧,閑話少敘。twemproxy到底做了什嗎?(註:我將關注Redis到部分,但是該項目也可以對memcached做相同到事情) 1) 在用戶端和眾多Redis執行個體間作為代理。 2) 在配置的Redis執行個體之間進行自動到資料分區。 3) 支援一致性雜湊,支援不同到策略和雜湊方法。 Twemproxy最了不起的地方就在於它能在節點失敗的時候卸載它,然後可以在一段時間以後重新嘗試(隨即)串連,又或者可以嚴格按照設定檔中寫的鍵與伺服器之間對應關係進行串連。這意味著Twemproxy能勝任把Redis當做資料存放區(不能容忍節點未命中)的情境,也能夠勝任當做緩衝來使用,那些允許(它意味著少量,不是說低品質)未命中且高可用的情境。總結來說就是:如果你能容忍未命中,那麼當有節點失敗你的資料也許會儲存到其他節點,所以它會是弱一致性的。另一方面,如果你不能容忍未命中,那麼你需要一個擁有高可用的執行個體的方案,例如使用Redis監控的失敗自動切換功能。安裝 --- 在深入項目的更多特性之前,有一個好訊息,它在Linux上非常容易構建。好吧,沒有Redis那麼簡單,但是……你僅僅需要簡單按照下面的幾步操作:apt-get install automake apt-get install libtool git clone git://github.com/twitter/twemproxy.git cd twemproxy autoreconf -fvi ./configure --enable-debug=log make src/nutcracker -h 它的配置也非常簡單,在項目的github頁面上有足夠的文檔可以讓你有一個平滑的初體驗。我使用了如下的配置:redis1: listen: 0.0.0.0:9999 redis: true hash: fnv1a_64 distribution: ketama auto_eject_hosts: true timeout: 400 server_retry_timeout: 2000 server_failure_limit: 1 servers: - 127.0.0.1:6379:1 - 127.0.0.1:6380:1 - 127.0.0.1:6381:1 - 127.0.0.1:6382:1 redis2: listen: 0.0.0.0:10000 redis: true hash: fnv1a_64 distribution: ketama auto_eject_hosts: false timeout: 400 servers: - 127.0.0.1:6379:1 - 127.0.0.1:6380:1 - 127.0.0.1:6381:1 - 127.0.0.1:6382:1 第一個叢集配置為(故障時)節點自動排除,第二個叢集則在所有執行個體上配置了靜態映射。 有趣的是,針對同一組伺服器你能同時有多個部署。然而在生產環境更適合使用多個樣本以利用多核的能力。單點失效? --- 還有另一件有趣的事情,使用這個部署並不意味著有單點失效問題,你可以通過運行多套twemproxy,讓你的用戶端串連到第一個可用的執行個體。 通過使用twemproxy你基本上把分區邏輯和用戶端進行了分離。在這種情況下,一個基本的用戶端就可以實現目的,分區將完全由代理來處理。這是一個直接而安全的方法,個人觀點。現在Redis Cluster還不成熟,twemproxy是大多數希望利用Redis叢集的使用者的好方法。也不要太激動,先看看這種方法的限制 ;)不足---我認為Twemproxy沒有支援大量操作的命令和事物是對的。當然,AFAIK甚至比Redis cluster更嚴格,反而它對於相同的鍵允許大量操作。但是恕我直言按照這種方式,分散的叢集帶來分散的效率,並且將這個挑戰帶給了早期的使用者,而且花費了大量的資源,從大量的執行個體中摘要資料,得到僅僅是“能用”的結果,而且你將很快開始有嚴重的負載問題,因為你有太多的時間花費在資料的傳輸上。可是有一些大量操作命令還是支援了的。MGET和DEL是處理的非常好的。有趣的是MGET命令在不同的伺服器之間切分請求並且返回一個結果。這一點相當酷,也許我以後不能有更好的效能(看以後的吧)。無論如何,大量操作和事物的不支援的現狀意味著Twemproxy不適用於每個人,特別像Redis cluster本身。特別是它顯然不支援EVAL(我認為他們應該支援它!它是多通用的,EVAL被設計可以在代理中工作,是因為鍵的名字已經明確了)。有待改進的地方---錯誤報表機制並不穩定,發送一個Redis不支援的命令會導致串連被關閉。比如從redis-cli只發送一個‘GET‘並不會報"參數個數不正確”的錯誤,只會導致串連被掛起。總體看來,伺服器返回的其它錯誤都可以準確的傳給用戶端:redis metal: 10000 > get list(錯誤)類型操作錯誤,鍵匹配了錯誤的值類型另外一個我想要看到的特性是對自動故障恢複的支援。有很多種替代方案:1) twemproxy已經能夠監控執行個體錯誤資訊、錯誤的數量、在檢測出足夠多的錯誤的情況下斷開節點。但是很遺憾twemproxy不能夠拿從節點作為替代方案,這樣就可以發送一個SLAVE OFNOONE命令來棄用備用節點,而不用只是斷開錯誤節點。這種情況下twemproxy才是一個具有高可用性的解決方案。2) 或者,我希望twemproxy能夠與Redis Sentinel一起協同工作,定期檢查Sentinel配置,如果出現故障則更新服務端配置3) 另外一種替代方案是提供一種熱配置twemproxy的方式,一旦節點出故障,Redis Sentinel就能夠切換ASAP代理配置有很多種替代方案,總體來說,如果能夠提供對HA(高可用性)的底層支援就非常棒了。效能 ---Twemproxy很快,真的很快,接近直接與Redis通訊的速度。我敢說你用的話最多損失20%的效能。我對效能唯一的意見是可以有更高效的方法把IMHO MGET命令分發到執行個體之間如果twemproxy與所有Redis執行個體的延遲很相似的話(很有可能),在MGETs命令在同一時間發出的情況下,twemproxy很有可能會在同一時間接收到所有節點的命令,所以我希望看到的是當我在所有執行個體上運行MGET命令的時候,發送的數量和twemproxy接收到的數量是一致的,但是實際上twemproxy在一秒內只接收到了50%的MGET命令。也許是時候重構twemproxy的應答模組了。結論---這是個偉大的項目,鑒於Redis Cluster還未發布,我強烈建議有需求的Redis使用者試一下Twemproxy我正打算將它連結到Redis專案網站上,因為我認為Twitter的夥計已經用他們的項目為Redis做了不小的貢獻,所以...這是Twitter贏得榮譽!
Twemproxy來自Twitter的Redis代理