1. 程式人生 > >利用Docker安裝執行Codis

利用Docker安裝執行Codis

最近打算對快取中間進行專題性學習,之前使用過Redis Sentinal,後來認識到Codis,對Codis產生感興趣,於是便有了下面的安裝執行總結。

什麼是Codis

目前基於Redis叢集的方案有三種,第一種是Redis Sentinal,第二種是Redis Cluster,第三種是豌豆莢的Codis。
Redis Sentinal搭建簡單,不過受Redis容量限制,普通應用個人覺得已經足夠了;本來想分析一下Redis Cluster,不過由於個人沒用過,不好說;至於Codis,第一次聽說是大概一年前去唯品會面試的時候(原諒我當時的孤陋寡聞),後來就一直留意這個東西,對Codis的動態擴容縮容以及監控頁面很甘興趣,最後狠下心來搭一套起來玩玩。

Twemproxy與Codis

說到Codis不得不提Twemproxy,Twemproxy是twitter開發的redis代理,能夠實現資料分片,通過keeplived來實現高可用。不過Twemproxy也有自己的一些痛點:

  • 無法平滑地擴容或縮容
    由於Twemproxy是靜態sharding,當業務需要對redis進行擴容或縮容時會導致大量資料不能命中,需要resharding,這對快取強依賴的應用來說比較致命。
  • 修改配置需要重啟
    這個就不用多解釋了…
  • 不可運維,沒有Dashboard
    這點對運維人員比較痛苦,不能通過控制檯對叢集進行監控配置

相比而言,Codis比較好地克服了上面的缺點。

Codis概覽

首先看看官網上Codis的架構圖

這裡寫圖片描述

下面是官方解釋:
Codis 3.x 由以下元件組成:

Codis Server:基於 redis-2.8.21 分支開發。增加了額外的資料結構,以支援 slot 有關的操作以及資料遷移指令。具體的修改可以參考文件 redis 的修改。

Codis Proxy:客戶端連線的 Redis 代理服務, 實現了 Redis 協議。 除部分命令不支援以外(不支援的命令列表),表現的和原生的 Redis 沒有區別(就像 Twemproxy)。

對於同一個業務叢集而言,可以同時部署多個 codis-proxy 例項;
不同 codis-proxy 之間由 codis-dashboard 保證狀態同步。
Codis Dashboard

:叢集管理工具,支援 codis-proxy、codis-server 的新增、刪除,以及據遷移等操作。在叢集狀態發生改變時,codis-dashboard 維護叢集下所有 codis-proxy 的狀態的一致性。

對於同一個業務叢集而言,同一個時刻 codis-dashboard 只能有 0個或者1個;
所有對叢集的修改都必須通過 codis-dashboard 完成。
Codis Admin:叢集管理的命令列工具。

可用於控制 codis-proxy、codis-dashboard 狀態以及訪問外部儲存。
Codis FE:叢集管理介面。

多個叢集例項共享可以共享同一個前端展示頁面;
通過配置檔案管理後端 codis-dashboard 列表,配置檔案可自動更新。
Codis HA:為叢集提供高可用。

依賴 codis-dashboard 例項,自動抓取叢集各個元件的狀態;
會根據當前叢集狀態自動生成主從切換策略,並在需要時通過 codis-dashboard 完成主從切換。
Storage:為叢集狀態提供外部儲存。

對Codis架構有大概瞭解之後,下面我們就開始利用Docker來搭建Codis

利用Docker搭建Codis

首先上一幅描述各個元件之間連線關係的圖
這裡寫圖片描述
利用docker釋出服務的時候,需要新增--host-admin來指定服務對外的訪問地址。
如果不這樣做的話,dashboard將不能正確獲取到proxy對外的代理和管理埠。例如容器內proxy的管理埠是19000,不新增–host-admin情況下,dashboard會以為proxy的管理埠就是19000,此時是訪問不通的(docker真正對外的地址是29000)。

1.準備Dockerfile

FROM golang:1.4

RUN apt-get update
RUN apt-get install -y vim bash golang
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/*

ENV GOPATH /gopath
ENV CODISLABS ${GOPATH}/src/github.com/CodisLabs  #存放Codis原始碼目錄
ENV CODIS  ${CODISLABS}/codis
ENV GOX    ${GOPATH}/src/golang.org/x
ENV PATH   ${GOPATH}/bin:${PATH}:${CODIS}/bin

WORKDIR ${GOX}
RUN git clone https://github.com/golang/net.git  #獲取gonet原始碼

WORKDIR ${CODISLABS}
RUN git clone https://github.com/CodisLabs/codis.git #獲取codis原始碼

WORKDIR ${CODIS}
RUN git checkout release3.0  #基於codis3.0release版本構建

WORKDIR ${CODIS}
RUN make

WORKDIR /codis

2.在Dockerfile所在目錄下構建docker image

docker build -t lzw2006/codis .

長時間的耐心等待… done!

#!/bin/bash
#獲取宿主機ip地址
hostip=`ifconfig enp0s3 | grep "inet " | awk -F " " '{print $2}'`

if [ "x$hostip" == "x" ]; then
    echo "cann't resolve host ip address"
    exit 1
fi

mkdir -p log

case "$1" in
dashboard) #啟動dashboard
    docker rm -f      "Codis-D28080" &> /dev/null
    docker run --name "Codis-D28080" -d \
         -v `realpath config/dashboard.toml`:/codis/dashboard.toml \
                    -v `realpath log`:/codis/log \
        -p 28080:18080 \
         --privileged=true \
        lzw2006/codis \
        codis-dashboard -l /codis/log/dashboard.log -c /codis/dashboard.toml --host-admin ${hostip}:28080
    ;;

proxy)  #啟動proxy
    docker rm -f      "Codis-P29000" &> /dev/null
    docker run --name "Codis-P29000" -d \
        --read-only -v `realpath config/proxy.toml`:/codis/proxy.toml \
                    -v `realpath log`:/codis/log \
        -p 29000:19000 -p 21080:11080 \
    --privileged=true \
        lzw2006/codis \
        codis-proxy -l /codis/log/proxy.log -c /codis/proxy.toml --host-admin ${hostip}:29000 --host-proxy ${hostip}:21080
    ;;

server) #啟動4個redis例項
    for ((i=0;i<4;i++)); do
        let port="26379 + i"
        docker rm -f      "Codis-S${port}" &> /dev/null
        docker run --name "Codis-S${port}" -d \
            -v `realpath log`:/codis/log \
            -p $port:6379 \
        --privileged=true \
            lzw2006/codis \
            codis-server --logfile /codis/log/${port}.log
    done
    ;;

fe) #啟動監控頁面
    docker rm -f      "Codis-F8080" &> /dev/null
    docker run --name "Codis-F8080" -d \
         -v `realpath log`:/codis/log \
         -v `realpath config/codis.json`:/codis/codis.json \
         -p 8080:8080 \
     -privileged=true \
     lzw2006/codis \
      /gopath/src/github.com/CodisLabs/codis/bin/codis-fe -l /codis/log/fe.log --dashboard-list=/codis/codis.json --listen=0.0.0.0:8080
    ;;


cleanup)
    docker rm -f      "Codis-D28080" &> /dev/null
    docker rm -f      "Codis-P29000" &> /dev/null
    for ((i=0;i<4;i++)); do
        let port="26379 + i"
        docker rm -f      "Codis-S${port}" &> /dev/null
    done
    ;;

*)
    echo "wrong argument(s)"
    ;;

esac

利用這指令碼能啟動dashboard、 proxy、fe以及redis-server。

4.準備配置檔案
建立config資料夾,把dashboard.toml、codis.json和proxy.toml複製到config資料夾下。
配置檔案都是可以通過Codis自帶的命令生成,例如dashboard.toml可以通過
./bin/codis-dashboard –default-config | tee dashboard.toml
生成

dashboard.toml

##################################################
#                                                #
#                  Codis-Dashboard               #
#                                                #
##################################################

# Set Coordinator, only accept "zookeeper" & "etcd"
coordinator_name = "zookeeper"
coordinator_addr = "10.100.5.74:2181"

# Set Codis Product {Name/Auth}.
product_name = "codis-demo"
product_auth = ""

# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:18080"

proxy.toml

##################################################
#                                                #
#                  Codis-Proxy                   #
#                                                #
##################################################

# Set Codis Product {Name/Auth}.
product_name = "codis-demo"
product_auth = ""

# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:19000"

# Set bind address for proxy, proto_type can be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
proto_type = "tcp4"
proxy_addr = "0.0.0.0:11080"

# Set jodis address & session timeout.
jodis_addr = ""
jodis_timeout = 10

# Proxy will ping-pong backend redis periodly to keep-alive
backend_ping_period = 5

# If there is no request from client for a long time, the connection will be droped. Set 0 to disable.
session_max_timeout = 1800

# Buffer size for each client connection.
session_max_bufsize = 131072

# Number of buffered requests for each client connection.
# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.
session_max_pipeline = 1024

# Set period between keep alives. Set 0 to disable.
session_keepalive_period = 60

codis.json

[
    {
        "name": "codis-demo",
        "dashboard": "10.100.5.74:28080"
    }
]

5.啟動zookeeper
怎樣安裝和啟動zookeeper請自行百度

6.啟動dashboard

./docker.sh dashboard

7.啟動proxy

./docker.sh proxy

8.啟動redis

./docker.sh server

指令碼會在本地啟動4個redis例項
這裡寫圖片描述

9.啟動codis-fe

./docker.sh fe

10.在FE上配置proxy,redis server和slot

  • 新增伺服器組,並往裡面新增redis例項
    這裡寫圖片描述

  • 配置slot(初始化slot)
    這裡寫圖片描述

  • 新增proxy
    這裡寫圖片描述

到這裡Codis已經啟動起來
接下來就可以使用redis-cli連線codis的proxy,就跟直連redis一樣
以上只是展示了一個大概的過程,可能你在安裝的時候遇到各種問題,耐心一點就能解決!

另外,Codis是用3.0release版本,請留意!