Codis——分佈式Redis服務的解決方案

 Codis——分佈式Redis服務的解決方案

 

以前介紹過的 Twemproxy 是一種Redis代理,但它不支持集羣的動態伸縮,而codis則支持動態的增減Redis節點;另外,官方的redis 3.0開始支持cluster。html

  

codis和twemproxy最大的區別有兩個:git

  • codis支持動態水平擴展,對client徹底透明不影響服務的狀況下能夠完成增減redis實例的操做;
  • codis是用go語言寫的並支持多線程,twemproxy用C並只用單線程。 後者又意味着:codis在多核機器上的性能會好於twemproxy;codis的最壞響應時間可能會由於GC的STW而變大,不過go1.5發佈後會顯著下降STW的時間;若是隻用一個CPU的話go語言的性能不如C,所以在一些短鏈接而非長鏈接的場景中,整個系統的瓶頸可能變成accept新tcp鏈接的速度,這時codis的性能可能會差於twemproxy。

 

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 Proxy (codis-proxy),處理客戶端請求,支持Redis協議,所以客戶端訪問Codis Proxy跟訪問原生Redis沒有什麼區別;
  • Codis Dashboard (codis-config),Codis 的管理工具,支持添加/刪除 Redis 節點、添加/刪除 Proxy 節點,發起數據遷移等操做。codis-config 自己還自帶了一個 http server,會啓動一個 dashboard,用戶能夠直接在瀏覽器上觀察 Codis 集羣的運行狀態;
  • Codis Redis (codis-server),Codis 項目維護的一個 Redis 分支,基於 2.8.21 開發,加入了 slot 的支持和原子的數據遷移指令;
  • ZooKeeper/Etcd,Codis 依賴 ZooKeeper 來存放數據路由表和 codis-proxy 節點的元信息,codis-config 發起的命令都會經過 ZooKeeper 同步到各個存活的 codis-proxy;

 

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爲單位的。多線程

 

 

 


 

安裝與部署

  1. 安裝go;
  2. 安裝codis
    go get -u -d github.com/CodisLabs/codis
    cd $GOPATH/src/github.com/CodisLabs/codis
    make

     

  3. 安裝zookeeper;
  4. 啓動dashboard
    bin/codis-config dashboard

     

  5. 初始化slots,在zk上建立slot相關信息
    bin/codis-config slot init

     

  6. 啓動codis-redis,跟官方redis server方法同樣;
  7. 添加redis server group,每一個 Group 做爲一個 Redis 服務器組存在,只容許有一個 master, 能夠有多個 slave,group id 僅支持大於等於1的整數。如: 添加兩個 server group, 每一個 group 有兩個 redis 實例,group的id分別爲1和2, redis實例爲一主一從。
  8. 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

     

  9. 設置server group 服務的 slot 範圍,如設置編號爲[0, 511]的 slot 由 server group 1 提供服務, 編號 [512, 1023] 的 slot 由 server group 2 提供服務
    bin/codis-config slot range-set 0 511 1 online
    bin/codis-config slot range-set 512 1023 2 online

     

  10. 啓動codis-proxy,
    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

     

 

 

 

 

 


 

數據遷移(migrate)

安全和透明的數據遷移是 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 處於遷移狀態)。

 

 

自動再平衡(auto rebalance)

Codis 支持動態的根據實例內存,自動對slot進行遷移,以均衡數據分佈

bin/codis-config slot rebalance

要求:

  • 全部的codis-server都必須設置了maxmemory參數;
  • 全部的 slots 都應該處於 online 狀態, 即沒有遷移任務正在執行;
  • 全部 server group 都必須有 Master;

 

 

高可用(HA)

由於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的狀態。

相關文章
相關標籤/搜索