一個分布式 Redis 替代解決方案

gww3 9年前發布 | 29K 次閱讀 Redis NoSQL數據庫

Codis 是一個分布式 Redis 解決方案, 對于上層的應用來說, 連接到 Codis Proxy 和連接原生的 Redis Server 沒有明顯的區別 (不支持的命令列表), 上層應用可以像使用單機的 Redis 一樣使用, Codis 底層會處理請求的轉發, 不停機的數據遷移等工作, 所有后邊的一切事情, 對于前面的客戶端來說是透明的, 可以簡單的認為后邊連接的是一個內存無限大的 Redis 服務.

Codis 由四部分組成:

  • Codis Proxy (codis-proxy)
  • Codis Manager (codis-config)
  • Codis Redis (codis-server)
  • ZooKeeper

codis-proxy 是客戶端連接的 Redis 代理服務, codis-proxy 本身實現了 Redis 協議, 表現得和一個原生的 Redis 沒什么區別 (就像 Twemproxy), 對于一個業務來說, 可以部署多個 codis-proxy, codis-proxy 本身是無狀態的.

codis-config 是 Codis 的管理工具, 支持包括, 添加/刪除 Redis 節點, 添加/刪除 Proxy 節點, 發起數據遷移等操作. codis-config 本身還自帶了一個 http server, 會啟動一個 dashboard, 用戶可以直接在瀏覽器上觀察 Codis 集群的運行狀態.

codis-server 是 Codis 項目維護的一個 Redis 分支, 基于 2.8.13 開發, 加入了 slot 的支持和原子的數據遷移指令. Codis 上層的 codis-proxy 和 codis-config 只能和這個版本的 Redis 交互才能正常運行.

Codis 依賴 ZooKeeper 來存放數據路由表和 codis-proxy 節點的元信息, codis-config 發起的命令都會通過 ZooKeeper 同步到各個存活的 codis-proxy.

Codis 支持按照 Namespace 區分不同的產品, 擁有不同的 product name 的產品, 各項配置都不會沖突.

Build codis-proxy & codis-config


安裝go參考這里,建議使用Go源碼安裝,然后參考下的流程

go get github.com/wandoulabs/codis
cd path/to/codis
./bootstrap.sh
make gotest

會在 codis/bin 文件夾生成 codis-config, codis-proxy 兩個可執行文件, (另外, bin/assets 文件夾是 codis-config 的 dashboard http 服務需要的前端資源, 需要和 codis-config 放置在同一文件夾下)

cd sample

$ ../bin/codis-config -h                                                                                                                                                                                                                           (master)
usage: codis-config  [-c <config_file>] [-L <log_file>] [--log-level=<loglevel>]
        <command> [<args>...]
options:
   -c   配置文件地址
   -L   日志輸出文件地址
   --log-level=<loglevel>   輸出日志級別 (debug < info (default) < warn < error < fatal)

commands:
    server            redis 服務器組管理
    slot              slot 管理
    dashboard         啟動 dashboard 服務
    action            事件管理 (目前只有刪除歷史事件的日志)
    proxy             proxy 管理
$ ../bin/codis-proxy -h

usage: codis-proxy [-c <config_file>] [-L <log_file>] [--log-level=<loglevel>] [--cpu=<cpu_num>] [--addr=<proxy_listen_addr>] [--http-addr=<debug_http_server_addr>]

options:
   -c   配置文件地址
   -L   日志輸出文件地址
   --log-level=<loglevel>   輸出日志級別 (debug < info (default) < warn < error < fatal)
   --cpu=<cpu_num>      proxy占用的 cpu 核數, 默認1, 最好設置為機器的物理cpu數的一半到2/3左右
   --addr=<proxy_listen_addr>       proxy 的 redis server 監聽的地址, 格式 <ip or hostname>:<port>, 如: localhost:9000, :9001
   --http-addr=<debug_http_server_addr>   proxy 的調試信息啟動的http server, 可以訪問 http://debug_http_server_addr/debug/vars

部署


配置文件

codis-config 和 codis-proxy 在不加 -c 參數的時候, 默認會讀取當前目錄下的 config.ini 文件

config.ini:

zk=localhost:2181   <- zookeeper的地址, 如果是zookeeper集群,可以這么寫: zk=hostname1:2181,hostname2:2181,hostname3:2181,hostname4:2181,hostname5:2181
product=test        <- 產品名稱, 這個codis集群的名字, 可以認為是命名空間, 不同命名空間的codis沒有交集
proxy_id=proxy_1    <- proxy會讀取, 用于標記proxy的名字, 針對多個proxy的情況, 可以使用不同的config.ini, 只需要更改 proxy_id 即可

流程

1. 初始化 slots , 執行../bin/codis-config slot init,該命令會在zookeeper上創建slot相關信息

2. 啟動 Codis Redis , 和官方的Redis Server參數一樣

3. 添加 Redis Server Group , 每一個 Server Group 作為一個 Redis 服務器組存在, 只允許有一個 master, 可以有多個 slave, group id 僅支持大于等于1的整數

$ ../bin/codis-config server -h                                                                                                                                                                                                                   usage:
    codis-config server list
    codis-config server add <group_id> <redis_addr> <role>
    codis-config server remove <group_id> <redis_addr>
    codis-config server promote <group_id> <redis_addr>
    codis-config server add-group <group_id>
    codis-config server remove-group <group_id>

如: 添加兩個 server group, 每個 group 有兩個 redis 實例,group的id分別為1和2, redis實例為一主一從。

添加一個group,group的id為1, 并添加一個redis master到該group

$ ../bin/codis-config server add 1 localhost:6379 master

添加一個redis slave到該group

$ ../bin/codis-config server add 1 localhost:6380 slave

類似的,再添加group,group的id為2

$ ../bin/codis-config server add 2 localhost:6479 master
$ ../bin/codis-config server add 2 localhost:6479 slave

4. 設置 server group 服務的 slot 范圍 Codis 采用 Pre-sharding 的技術來實現數據的分片, 默認分成 1024 個 slots (0-1023), 對于每個key來說, 通過以下公式確定所屬的 Slot Id : SlotId = crc32(key) % 1024 每一個 slot 都會有一個特定的 server group id 來表示這個 slot 的數據由哪個 server group 來提供.

$ ../bin/codis-config slot -h                                                                                                                                                                                                                     
usage:
    codis-config slot init
    codis-config slot info <slot_id>
    codis-config slot set <slot_id> <group_id> <status>
    codis-config slot range-set <slot_from> <slot_to> <group_id> <status>
    codis-config slot migrate <slot_from> <slot_to> <group_id> [--delay=<delay_time_in_ms>]

如:

設置編號為[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

5. 啟動 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

6. 啟動 dashboard 服務 (可選, 但是建議啟動)

../bin/codis-config -c config.ini -L ./log/dashboard.log dashboard --addr=:18087 --http-log=./log/requests.log

7. 打開瀏覽器 http://localhost:18087/admin

現在可以在瀏覽器里面完成各種操作了, 玩得開心

數據遷移


安全和透明的數據遷移是 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
 本文由用戶 gww3 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!