以前介紹過的 Twemproxy 是一種Redis代理,但它不支持集羣的動態伸縮,而codis則支持動態的增減Redis節點;另外,官方的redis 3.0開始支持cluster。html
codis和twemproxy最大的區別有兩個:git
codis和redis cluster的區別:github
redis cluster基於smart client和無中心的設計,client必須按key的哈希將請求直接發送到對應的節點。這意味着:使用官方cluster必需要等對應語言的redis driver對cluster支持的開發和不斷成熟;client不能直接像單機同樣使用pipeline來提升效率,想同時執行多個請求來提速必須在client端自行實現異步邏輯。 而codis因其有中心節點、基於proxy的設計,對client來講能夠像對單機redis同樣去操做proxy(除了一些命令不支持),還能夠繼續使用pipeline而且若是後臺redis有多個的話速度會顯著快於單redis的pipeline。同時codis使用zookeeper來做爲輔助,這意味着單純對於redis集羣來講須要額外的機器搭zk,不過對於不少已經在其餘服務上用了zk的公司來講這不是問題:)redis
Codis 是豌豆莢公司開發的一個分佈式 Redis 解決方案,用Go語言開發的。對於上層的應用來講,鏈接到 Codis Proxy 和鏈接原生的 Redis Server 沒有明顯的區別 (不支持的命令列表),Codis 底層會處理請求的轉發,不停機的數據遷移等工做。全部後邊的一切事情,對於前面的客戶端來講是透明的,能夠簡單的認爲後邊鏈接的是一個內存無限大的 Redis 服務。api
Codis 由四部分組成:瀏覽器
Codis 支持按照 Namespace 區分不一樣的產品,擁有不一樣的 product name 的產品,各項配置都不會衝突。安全
Codis 採用 Pre-sharding 的技術來實現數據的分片,默認分紅 1024 個 slots (0-1023),對於每一個key來講,經過如下公式肯定所屬的 Slot Id:服務器
SlotId = crc32(key) % 1024
每個 slot 都會有一個且必須有一個特定的 server group id 來表示這個 slot 的數據由哪一個 server group 來提供。數據的遷移也是以slot爲單位的。多線程
go get -u -d github.com/CodisLabs/codis cd $GOPATH/src/github.com/CodisLabs/codis make
bin/codis-config dashboard
bin/codis-config slot init
bin/codis-config server add 1 localhost:6379 master bin/codis-config server add 1 localhost:6380 slave bin/codis-config server add 2 localhost:6479 master bin/codis-config server add 2 localhost:6480 slave
bin/codis-config slot range-set 0 511 1 online bin/codis-config slot range-set 512 1023 2 online
bin/codis-proxy -c config.ini -L ./log/proxy.log --cpu=8 --addr=0.0.0.0:19000 --http-addr=0.0.0.0:11000
剛啓動的 codis-proxy 默認是處於 offline狀態的, 而後設置 proxy 爲 online 狀態, 只有處於 online 狀態的 proxy 纔會對外提供服務負載均衡
bin/codis-config -c config.ini proxy online <proxy_name> <---- proxy的id, 如 proxy_1
安全和透明的數據遷移是 Codis 提供的一個重要的功能,也是 Codis 區別於 Twemproxy 等靜態的分佈式 Redis 解決方案的地方。
數據遷移的最小單位是 key,咱們在 codis redis 中添加了一些指令,實現基於key的遷移,如 SLOTSMGRT等 (命令列表),每次會將特定 slot 一個隨機的 key 發送給另一個 codis redis 實例,這個命令會確認對方已經接收,同時刪除本地的這個 k-v 鍵值,返回這個 slot 的剩餘 key 的數量,整個操做是原子的。
在 codis-config 管理工具中,每次遷移任務的最小單位是 slot。如: 將slot id 爲 [0-511] 的slot的數據,遷移到 server group 2上,--delay 參數表示每遷移一個 key 後 sleep 的毫秒數,默認是 0,用於限速。
bin/codis-config slot migrate 0 511 2 --delay=10
遷移的過程對於上層業務來講是安全且透明的,數據不會丟失,上層不會停止服務。
注意,遷移的過程當中打斷是能夠的,可是若是中斷了一個正在遷移某個slot的任務,下次須要先遷移掉正處於遷移狀態的 slot,不然沒法繼續 (即遷移程序會檢查同一時刻只能有一個 slot 處於遷移狀態)。
Codis 支持動態的根據實例內存,自動對slot進行遷移,以均衡數據分佈
bin/codis-config slot rebalance
要求:
由於codis的proxy是無狀態的,能夠比較容易的搭多個proxy來實現高可用性並橫向擴容。
對Java用戶來講,可使用通過咱們修改過的Jedis,Jodis ,來實現proxy層的HA。它會經過監控zk上的註冊信息來實時得到當前可用的proxy列表,既能夠保證高可用性,也能夠經過輪流請求全部的proxy實現負載均衡。若是須要異步請求,可使用咱們基於Netty開發的Nedis。
對下層的redis實例來講,當一個group的master掛掉的時候,應該讓管理員清楚,並手動的操做,由於這涉及到了數據一致性等問題(redis的主從同步是最終一致性的)。所以codis不會自動的將某個slave升級成master。 不過咱們也提供一種解決方案:codis-ha。這是一個經過codis開放的api實現自動切換主從的工具。該工具會在檢測到master掛掉的時候將其下線並選擇其中一個slave提高爲master繼續提供服務。
須要注意,codis將其中一個slave升級爲master時,該組內其餘slave實例是不會自動改變狀態的,這些slave仍將試圖從舊的master上同步數據,於是會致使組內新的master和其餘slave之間的數據不一致。由於redis的slave of命令切換master時會丟棄slave上的所有數據,重新master完整同步,會消耗master資源。所以建議在知情的狀況下手動操做。使用 codis-config server add <group_id> <redis_addr> slave
命令刷新這些節點的狀態便可。codis-ha不會自動刷新其餘slave的狀態。