Codis 運維D4 - Codis3詳解

Codis 3介紹

對於Redis集羣方案有好多種,基本經常使用的就是twemproxy,codis、redis cluster這三種解決方案,本人有幸工做中都大量使用過,各有利有弊,下面這篇文章詳解講解一下豌豆尖的Codis 3。因爲業務中還使用有Codis 2,因此對於Codis 2也寫了一篇文章Codis 2集羣搭建。Codis整體來講還算不錯,僅供你們學習和參考。html

Codis是一個分佈式Redis解決方案, 對於上層的應用來講, 鏈接到Codis Proxy和鏈接原生的Redis Server沒有顯著區別 (不支持的命令列表), 上層應用能夠像使用單機的Redis同樣使用, Codis 底層會處理請求的轉發, 不停機的數據遷移等工做, 全部後邊的一切事情, 對於前面的客戶端來講是透明的, 能夠簡單的認爲後邊鏈接的是一個內存無限大的Redis服務。前端

Codis 3集羣搭建詳解

Codis 3.x由如下組件組成:java

 Codis Server:基於 redis-2.8.21 分支開發。增長了額外的數據結構,以支持 slot 有關的操做以及數據遷移指令。具體的修改能夠參考文檔 redis 的修改。node

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

    對於同一個業務集羣而言,能夠同時部署多個codis-proxy實例;nginx

    不一樣codis-proxy之間由codis-dashboard保證狀態同步。c++

• Codis Dashboard:集羣管理工具,支持codis-proxy、codis-serve的添加、刪除,以及據遷移等操做。在集羣狀態發生改變時,codis-dashboard 維護集羣下全部 codis-proxy的狀態的一致性。git

    對於同一個業務集羣而言,同一個時刻 codis-dashboard 只能有 0個或者1個;github

    全部對集羣的修改都必須經過 codis-dashboard 完成。golang

• Codis Admin:集羣管理的命令行工具。

    可用於控制codis-proxy、codis-dashboard狀態以及訪問外部存儲。

• Codis FE:集羣管理界面。

    多個集羣實例共享能夠共享同一個前端展現頁面;

    經過配置文件管理後端codis-dashboard列表,配置文件可自動更新。

• Codis HA:爲集羣提供高可用。

    依賴codis-dashboard實例,自動抓取集羣各個組件的狀態;

    會根據當前集羣狀態自動生成主從切換策略,並在須要時經過codis-dashboard完成主從切換。

• Storage:爲集羣狀態提供外部存儲。

    提供Namespace概念,不一樣集羣的會按照不一樣product name進行組織;

    目前僅提供了Zookeeper和Etcd兩種實現,可是提供了抽象的interface可自行擴展。

 

安裝配置Codis 3集羣

這次試驗服務部署架構方式以下:

10.0.60.152 zk、fe、dashboard、proxy、codis
10.0.60.153 zk、proxy、codis
10.0.60.154 zk、proxy、codis

system:CentOS 7版本這次試驗用到的軟件及版本以下:

Jdk:1.8版本

Zookeeper:3.4版本(http://zookeeper.apache.org/releases.html

Go:go1.5.2.Linux-amd64.tar.gz版本(https://golang.org/doc/install?download=go1.5.2.linux-amd64.tar.gz

Codis:3.0.3版本(https://github.com/CodisLabs/codis/archive/3.0.3.zip

安裝參考文檔:https://github.com/CodisLabs/codis/blob/release3.0/doc/tutorial_zh.md

 

一、安裝配置zookeeper

Zookeeper分佈式服務框架,是Apache Hadoop的一個子項目,它主要是用來解決分佈式應用中常常遇到的一些數據管理問題,如:統一命名服務、狀態同步服務、集羣管理、分佈式應用配置項的管理等。Codis依賴zookeeper才能協同工做。

首先安裝開發工具及openjdk,zookeeper是由Java語言開發的,因此須要openjdk環境。

$ yum groupinstall "Development tools" "Compatibility libraries" -y
$ yum install openssl-devel openssl -y
$ yum install java-1.8.0-openjdk-devel java-1.8.0-openjdk -y
$ yum install -y gcc make gcc-c++ automake lrzsz openssl-devel zlib-* bzip2-* readline* zlib-* bzip2-* git
$ yum install -y nmap unzip wget lsof xz net-tools mercurial

肯定Java運行環境正常

$ java -version

openjdk version "1.8.0_101"

OpenJDK Runtime Environment (build 1.8.0_101-b13)

OpenJDK 64-Bit Server VM (build 25.101-b13, mixed mode)

安裝二進制版本的zookeeper

$ tar xvf zookeeper-3.4.9.tar.gz -C /usr/local/

$ ln -s /usr/localzookeeper-3.4.9/ /usr/local/zookeeper

$ cd /usr/local/zookeeper/conf

$ cp zoo_sample.cfg zoo.cfg

編譯zookeeper配置文件/usr/local/zookeeper/conf/zoo.cfg

maxClientCnxns=60

tickTime=2000

initLimit=10

syncLimit=5

dataDir=/data/zookeeper/db

dataLogDir=/data/zookeeper/log

clientPort=2181

# cluster configure

server.1=10.0.60.152:2888:3888

server.2=10.0.60.153:2888:3888

server.3=10.0.60.154:2888:3888

 

$ mkdir /data/zookeeper/{db,log} -p

下面須要生成ID,這裏須要注意,myid對應的zoo.cfg的server.ID,好比第二臺zookeeper主機對應的myid應該是2,以此類推,三個主機分別爲:其中2888表示zookeeper程序監聽端口,3888表示zookeeper選舉通訊端口。

10.0.60.152$ echo 1 > /data/zookeeper/db/myid

10.0.60.153$ echo 2 > /data/zookeeper/db/myid

10.0.60.154$ echo 3 > /data/zookeeper/db/myid

而後輸出環境變量。

$ export PATH=$PATH:/usr/local/zookeeper/bin/
$ source /etc/profile

而後就能夠啓動zookeeper了。

$ zkServer.sh start

查看各個zookeeper節點的狀態(會有一個leader節點,兩個follower節點)。

[root@node1 ~]# zkServer.sh status
Mode: follower
[root@node2 ~]# zkServer.sh status
Mode: leader
[root@node3 ~]# zkServer.sh status
Mode: follower

客戶端鏈接,能夠查看相關信息。

$ zkCli.sh -server 127.0.0.1:2181

至此,zookeeper已經搞定了。


二、go安裝(codis是go語言寫的,因此這些機器須要安裝go環境)

首先下載go二進制安裝包

https://golang.org/doc/install?download=go1.5.2.linux-amd64.tar.gz

官方界面介紹瞭如何安裝GO運環境,對於GO運行環境來講,有一些特定的GOROOT和GOPATH環境變量須要設置,這是必須的,否則沒法運行go程序。這裏最好安裝go1.5.2版本,否則後面編譯Codis有些小問題。

$ tar xvf go1.5.2.linux-amd64.tar.gz -C /usr/local

解壓完成後,GO就安裝完了,下面設置一個GOPATH目錄,其實就是go程序運行目錄。

$ mkdir /usr/local/codis

而後就能夠設置GO須要的環境變量,路徑看好,千萬別搞錯了。

$ cat /etc/profile.d/go.sh

#!/bin/bash

#

export GOROOT=/usr/local/go

export GOPATH=/usr/local/codis/

export PATH=$PATH:$GOROOT/bin

應用一下go.sh

$ chmod a+x /etc/profile.d/go.sh

$ source /etc/profile.d/go.sh

查看GO版本

$ go version

go version go1.5.2 linux/amd64

 

三、安裝godep

Codis的編譯使用了godep,若是沒有安裝的話就會報godep command not found的錯誤,godep是golang的一個包管理工具,相似於Python的pip。

$ mkdir -p $GOPATH/src/github.com/tools

$ cd $GOPATH/src/github.com/tools

$ go get -u github.com/tools/godep

$ cd godep

$ go install ./

其中go install ./命令會將godep執行程序生成到$GOPATH/bin下。

$ ll $GOPATH/bin

-rwxr-xr-x. 1 root root 10329080 Oct 11 11:00 godep

而後將$GOPATH/bin加到/etc/profile.d/go.sh中,主要是引用godep命令:

$ cat /etc/profile.d/go.sh

#!/bin/bash

#

export GOROOT=/usr/local/go

export GOPATH=/usr/local/codis/

export PATH=$PATH:$GOROOT/bin

export PATH=$GOROOT/bin:$GOPATH/bin:$PATH
$ source /etc/profile.d/go.sh

查看godep效果

$ which godep

/usr/local/codis/bin/godep

$ godep version

godep v74 (linux/amd64/go1.5.2)


四、下載並編譯安裝codis 3

$ cd /root

$ wget https://github.com/CodisLabs/codis/archive/3.0.3.zip

$ unzip 3.0.3.zip

$ mkdir /usr/local/codis/src/github.com/CodisLabs

$ cp -fr ./codis-3.0.3/ /usr/local/codis/src/github.com/CodisLabs/codis

$ cd /usr/local/codis/src/github.com/CodisLabs/codis

$ make

編譯完成後,查看一下Codis產生的文件。

$ ll

total 52

drwxr-xr-x. 3 root root 4096 Oct 11 11:08 bin

drwxr-xr-x. 7 root root 4096 Oct 11 11:05 cmd

drwxr-xr-x. 5 root root 4096 Oct 11 11:05 doc

-rw-r--r--. 1 root root 338 Oct 11 11:05 Dockerfile

drwxr-xr-x. 5 root root 4096 Oct 11 11:05 extern

drwxr-xr-x. 3 root root 4096 Oct 11 11:06 Godeps

-rw-r--r--. 1 root root 1352 Oct 11 11:05 Makefile

-rw-r--r--. 1 root root 1076 Oct 11 11:05 MIT-LICENSE.txt

drwxr-xr-x. 6 root root 4096 Oct 11 11:05 pkg

-rw-r--r--. 1 root root 2966 Oct 11 11:05 README.md

drwxr-xr-x. 2 root root 4096 Oct 11 11:05 scripts

-rwxr-xr-x. 1 root root 418 Oct 11 11:05 version

-rw-r--r--. 1 root root 1081 Oct 11 11:05 wandoujia_license.txt

輸出Codis執行文件,添加最後一行PATH變量。在bin文件夾內生成codis-admin、codis-dashboard、codis-fe、codis-ha、codis-proxy、codis-server六個可執行文件。另外, bin/assets文件夾是codis-dashboard http服務須要的前端資源, 須要和codis-dashboard放置在同一文件夾下。

$ cat /etc/profile.d/go.sh

#!/bin/bash

#

export GOROOT=/usr/local/go

export GOPATH=/usr/local/codis/

export PATH=$PATH:$GOROOT/bin

export PATH=$GOROOT/bin:$GOPATH/bin:$PATH

export PATH=$PATH:/usr/local/codis/src/github.com/CodisLabs/codis/bin/
$ source /etc/profile.d/go.sh

至此,Codis安裝完成。但須要注意的是,若是你是用golang 1.5 beta3以上的版本進行編譯,還有可能出現的一個問題是:

GOPATH=godep path godep restore

Error: GO15VENDOREXPERIMENT is enabled and the vendor/ directory is not a valid Go workspace.

godep: Error restore requires GOPATH but it is empty.

make: *** [godep] Error 1

這是由於golang 1.5 beta3以後go添加了GO15VENDOREXPERIMENT這個特性,並在1.6版本就默認開啓,你能夠參照Codis issue715裏面的方案解決。最簡單就是在編譯前

export GO15VENDOREXPERIMENT=0

Codis安裝完成後,就能夠爲Codis建立一些標準的目錄,用來存儲Codis的腳本目錄、配置文件目錄、日誌目錄、PID目錄、Redis配置目錄等。

 

五、爲Codis建立標準目錄

$ mkdir -p /data/codis/sh

$ mkdir -p /data/codis/conf

$ mkdir -p /data/codis/log

$ mkdir -p /data/codis/run

$ mkdir -p /data/codis/redis/bin

$ mkdir -p /data/codis/redis/redis-6379

$ mkdir -p /data/codis/redis/redis-6380

複製Codis自帶的redis-2.8.21相關工具到標準目錄中。

$ cd /usr/local/codis/src/github.com/CodisLabs/codis/extern/redis-2.8.21/src/

$ cp ./{redis-benchmark,redis-cli,redis-sentinel,redis-server} /data/codis/redis/bin/

添加環境變量

$ cat /etc/profile.d/go.sh

#!/bin/bash

#

export GOROOT=/usr/local/go

export GOPATH=/usr/local/codis/

export PATH=$PATH:$GOROOT/bin

export PATH=$GOROOT/bin:$GOPATH/bin:$PATH

export PATH=$PATH:/usr/local/codis/src/github.com/CodisLabs/codis/bin/

export PATH=$PATH:/data/codis/redis/bin
$ source /etc/profile.d/go.sh

 

六、配置啓動Codis各組件—-啓動Redis

考慮到性能,主庫關閉aof和rdp,從庫只開啓aof便可。下面這份配置就是生產環境中的配置,具體的含義能夠看本博客的Redis生產環境配置文件詳解章節。

主庫:/data/codis/redis/redis-6379/redis.conf

###基本參數###

daemonize yes

pidfile /data/codis/run/redis-6379.pid

port 6379

tcp-backlog 65535

bind 0.0.0.0

timeout 0

tcp-keepalive 0

loglevel notice

logfile "/data/codis/log/redis-6379.log"

databases 16

lua-time-limit 5000

maxclients 10000



###慢日誌參數###

slowlog-log-slower-than 10000

slowlog-max-len 128



###內存參數###

maxmemory 3G

maxmemory-policy noeviction



###RDB持久化參數###

#save 3600 1

#stop-writes-on-bgsave-error yes

#rdbcompression yes

#rdbchecksum yes

#dbfilename dump.rdb



###AOF持久化參數###

#no-appendfsync-on-rewrite yes

#appendonly yes

#appendfilename "appendonly.aof"

#appendfsync no

#auto-aof-rewrite-min-size 512mb

#auto-aof-rewrite-percentage 100

#aof-load-truncated yes

#aof-rewrite-incremental-fsync yes



###客戶端Buffer參數###

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60



###其餘參數###

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

hll-sparse-max-bytes 3000

activerehashing yes

latency-monitor-threshold 0



###安全參數###

#requirepass  123456789

從庫:/data/codis/redis/redis-6380/redis.conf

###基本參數###

daemonize yes

pidfile /data/codis/run/redis-6380.pid

port 6380

tcp-backlog 65535

bind 0.0.0.0

timeout 0

tcp-keepalive 0

loglevel notice

logfile "/data/codis/log/redis-6380.log"

databases 16

lua-time-limit 5000

maxclients 10000



###慢日誌參數###

slowlog-log-slower-than 10000

slowlog-max-len 128



###內存參數###

maxmemory 3G

maxmemory-policy noeviction



###RDB持久化參數###

#save 3600 1

#stop-writes-on-bgsave-error yes

#rdbcompression yes

#rdbchecksum yes

#dbfilename dump.rdb



###AOF持久化參數###

no-appendfsync-on-rewrite yes

appendonly yes

appendfilename "appendonly.aof"

appendfsync no

auto-aof-rewrite-min-size 512mb

auto-aof-rewrite-percentage 100

aof-load-truncated yes

aof-rewrite-incremental-fsync yes



###客戶端Buffer參數###

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60



###其餘參數###

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

hll-sparse-max-bytes 3000

activerehashing yes

latency-monitor-threshold 0



###安全參數###

#requirepass  123456789

可使用codis-server啓動redis了。

$ codis-server /data/codis/redis/redis-6379/redis.conf

$ codis-server /data/codis/redis/redis-6380/redis.conf

 

七、配置啓動Codis各組件—-啓動dashboard(集羣中某一個節點)

首先生成默認的配置文件:

$ codis-dashboard --default-config | tee /data/codis/conf/dashboard.toml

修改配置文件參數以下:

# Set Coordinator, only accept "zookeeper" & "etcd"

coordinator_name = "zookeeper"

coordinator_addr = "10.0.60.152:2181,10.0.60.153:2181,10.0.60.154: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"

配置文件參數說明:
coordinator_name:外部存儲類型,接受zookeeper/etcd,這裏咱們使用的zookeeper集羣。

coordinator_addr:外部存儲地址。

product_name:集羣名稱,知足正則\w[\w\.\-]*。

product_auth:集羣密碼,默認爲空。

admin_addr:RESTful API端口。

啓動dashboard

$ nohup codis-dashboard --ncpu=2 --config=/data/codis/conf/dashboard.toml --log=/data/codis/log/dashboard.log --log-level=WARN &

參數解釋:

–ncpu=N:最大使用CPU個數。

-c CONF, –config=CONF:指定啓動配置文件。

-l FILE, –log=FILE:設置log輸出文件。

–log-level=LEVEL:設置log輸出等級:INFO,WARN,DEBUG,ERROR,默認INFO,推薦WARN。

PS:dashboard只須要在一個節點啓動便可,啓動時會向zookeeper註冊信息(topom),若是有其餘節點也啓動dashboard時,向zookeeper註冊信息發現裏面有信息時,就會沒法啓動的。另外,若是dashboard異常退出,請看後面的異常處理案例。

 

八、配置啓動Codis各組件—-啓動codis-proxy(集羣中全部節點)

首先生成默認的配置文件:

$ codis-proxy --default-config | tee /data/codis/conf/proxy.toml

修改配置文件參數以下:

product_name = "codis-demo"

product_auth = ""

admin_addr = "0.0.0.0:11080"

proto_type = "tcp4"

proxy_addr = "0.0.0.0:19000"

#jodis_addr = "10.0.60.152:2181,10.0.60.153:2181,10.0.60.154:2181"

jodis_addr = ""

jodis_timeout = 10

backend_ping_period = 5

session_max_timeout = 1800

session_max_bufsize = 131072

session_max_pipeline = 1024

session_keepalive_period = 60

配置文件參數介紹:
product_name:產品名稱, 這個codis集羣的名字, 能夠認爲是命名空間, 不一樣命名空間的codis沒有交集。

product_auth:集羣密碼,默認爲空。Codis 3.x支持AUTH,可是要求全部組件使用的AUTH必須徹底相同。

admin_addr:RESTful API端口。

proto_type:Redis端口類型,接受tcp/tcp4/tcp6/unix/unixpacket。

proxy_addr:Redis端口地址或者路徑。

jodis_addr:Jodis註冊zookeeper地址。

jodis_timeout:Jodis註冊session timeout時間,單位second。

backend_ping_period:與codis-server探活週期,單位second,0表示禁止。

session_max_timeout:與client鏈接最大讀超時,單位second,0表示禁止。

session_max_bufsize:與client鏈接讀寫緩衝區大小,單位byte。

session_max_pipeline:與client鏈接最大的pipeline大小。

session_keepalive_period:與client的tcp keepalive週期,僅tcp有效,0表示禁止。

啓動codis-proxy

$ nohup codis-proxy --ncpu=2 --config=/data/codis/conf/proxy.toml --log=/data/codis/log/proxy.log --log-level=WARN &

-c CONF, –config=CONF:指定啓動配置文件。

–ncpu=N:最大使用CPU個數。

-l FILE, –log=FILE:設置log輸出文件。

–log-level=LEVEL:設置log輸出等級:INFO,WARN,DEBUG,ERROR;默認INFO,推薦WARN。

–ulimit=NLIMIT:檢查ulimit -n的結果,確保運行時最大文件描述很多於NLIMIT。

 

codis-proxy啓動後,處於waiting狀態,監聽proxy_addr地址,可是不會accept鏈接,添加到集羣並完成集羣狀態的同步,才能改變狀態爲online。添加的方法有如下兩種:

第一種:經過codis-fe添加,經過Add Proxy按鈕,將admin_addr加入到集羣中,以下圖(具體操做要等到後面codis-fe啓動後才能夠):

Codis 3集羣搭建詳解

第二種:經過codis-admin命令行工具添加,方法以下(添加3個proxy):

$ codis-admin --dashboard=10.0.60.152:18080 --create-proxy -x 10.0.60.152:11080

$ codis-admin --dashboard=10.0.60.152:18080 --create-proxy -x 10.0.60.153:11080

$ codis-admin --dashboard=10.0.60.152:18080 --create-proxy -x 10.0.60.154:11080

1)獲取proxy信息,對集羣name以及auth進行驗證,並將其信息寫入到外部存儲中;其中–dashboard須要指定codis-dashboard的管理地址,–create-proxy指定爲和codis-proxy的admin_addr地址,。添加過程當中,codis-dashboard會完成以下一系列動做:

2)同步slots狀態;

3)標記proxy狀態爲online,此後proxy開始accept鏈接並開始提供服務;

PS:在添加codis-proxy的時候須要特別注意,這個地方容易出現各類問題,最好能一次性添加成功,否則就須要刪除zookeeper數據了,而後從新開始。還有一點須要注意的是,測試中發現一旦刪除掉某個proxy後,再次添加就會報錯。

 

九、配置啓動Codis各組件—-啓動codis-fe(可選組件)

首先生成默認的配置文件,配置文件codis.json能夠手動編輯,也能夠經過codis-admin從外部存儲(這裏是zookeeper)中拉取,以下操做:

$ codis-admin --dashboard-list --zookeeper=127.0.0.1:2181 | tee /data/codis/conf/codis.json

拉去的配置文件信息:

$ cat /data/codis/conf/codis.json

[

    {

        "name": "codis-demo",

        "dashboard": "10.0.60.152:18080"

    }

]

啓動codis-fe,注意啓動codis-fe的時候,必需要使用codis-fe的全路徑進行啓動,由於codis-fe須要找到前端靜態文件,也就是要找到/usr/local/codis/src/github.com/CodisLabs/codis/bin/assets目錄。

$ nohup `which codis-fe` --ncpu=2 --log=/data/codis/log/fe.log --log-level=WARN --dashboard-list=/data/codis/conf/codis.json \

--listen=0.0.0.0:8080 &


十、添加Redis Server Group(在集羣中一臺服務器上操做便可,也能夠在面板圖形界面操做)

web監控端口是801端口,咱們能夠在瀏覽器打開http://10.0.60.152:8080看看圖形化界面。

首先使用codis-admin工具建立組,按照上面的規劃的,咱們建立2個組便可:

$ codis-admin --dashboard=10.0.60.152:18080 --create-group --gid=1

$ codis-admin --dashboard=10.0.60.152:18080 --create-group --gid=2

而後使用codis-admin工具給組添加Redis主機(2個主機爲一個組):

$ codis-admin --dashboard=10.0.60.152:18080 --group-add --gid=1 --addr=10.0.60.152:6379

$ codis-admin --dashboard=10.0.60.152:18080 --group-add --gid=1 --addr=10.0.60.154:6379
$ codis-admin --dashboard=10.0.60.152:18080 --group-add --gid=2 --addr=10.0.60.153:6380

$ codis-admin --dashboard=10.0.60.152:18080 --group-add --gid=2 --addr=10.0.60.154:6380

把從庫跟主庫同步:

$ codis-admin --dashboard=10.0.60.152:18080 --sync-action --create --addr=10.0.60.154:6379

$ codis-admin --dashboard=10.0.60.152:18080 --sync-action --create --addr=10.0.60.154:6380

若slave須要提高爲master,操做以下:須要注意的是若是當從庫運行一段時間後掛掉了,那麼從新啓動後須要人爲手動地將主從進行同步,執行上面的命令便可,或者圖形界面操做(反之,若是主庫掛了,立刻又好了,這時候從庫會自動從新鏈接上的,不須要人爲干預)。

$ codis-admin --dashboard=10.0.60.152:18080 --promote-server --gid=1 --addr=10.0.60.154:6379

 

十一、初始化slots並設置server group服務的slot 範圍(在集羣中一臺服務器上操做便可,也能夠在面板圖形界面操做)

注意的是,當從庫提高爲主庫後,那麼原來的主庫就會掉線,若是想把它做爲如今主庫的從庫,仍是須要人爲干預的,由於這個涉及到數據安全性的問題。

Codis採用Pre-sharding的技術來實現數據的分片, 默認分紅1024個slots (0-1023),對於每一個key來講,經過如下公式肯定所屬的Slot Id : SlotId = crc32(key) %1024。每個slot都會有一個且必須有一個特定的server group id來表示這個slot的數據由哪一個server group來提供。

$ codis-admin --dashboard=10.0.60.152:18080 --slot-action --create-range --beg=0 --end=511 --gid=1

$ codis-admin --dashboard=10.0.60.152:18080 --slot-action --create-range --beg=512 --end=1023 --gid=2

至此,一個簡單的集羣就搭建完成了。可是此時redis雖然可以很好地進行切換了。可是是須要人爲切換,若是想作到自動切換,那麼還須要Codis的另外一個組件codis-ha。

 

十二、配置啓動Codis各組件—-啓動codis-ha(可選組件)

codis-ha --log=/data/codis/log/ha.log --log-level=WARN --interval=3 --dashboard=127.0.0.1:18080 &

注意:Codis HA工具僅僅是Codis集羣HA的一部分,單獨工做能力有限。工做原理:

默認以5s(–interval是調整時間間隔的)爲週期,codis-ha會從codis-dashboard中拉取集羣狀態,並進行主從切換;

codis-ha在如下狀態下會退出:

一、從codis-dashboard獲取集羣狀態失敗時;

二、向codis-dashboard發送主從切換指令失敗時;

codis-ha在如下狀態下不會進行主從切換:

一、存在proxy狀態異常:

由於提高主從須要獲得全部proxy的確認,所以必須確保操做時全部proxy都能正常響應操做指令;

二、網絡緣由形成的master異常:

若存在slave知足slave.master_link_status == up,一般能夠認爲master並無真的退出,而是因爲網絡緣由或者響應延遲形成的master狀態獲取失敗,此時codis-ha不會對該group進行操做;

三、沒有知足條件的slave時:

提高過程會選擇知足slave.master_link_status == down,而且slave.master_link_down_since_seconds最小的進行操做。這就要求被選擇的slave至少在過去一段時間內與master是成功同步狀態,這個時間間隔是2d+5,其中d是codis-ha檢查週期默認5秒。

注意:所以,應用codis-ha時還須要結合對codis-proxy和codis-server的可用性監控,不然codis-ha沒法保證可靠性。

PS:當codis-ha啓動後,你能夠測試關掉redis master,看看redis slave是否立刻會成爲主節點。

最後來看一下配置完成後的web界面是什麼樣子?

Codis 3集羣搭建詳解

在此界面中也能夠進行,組建立、將redis加入到組、刪除redis主機、設置主從同步、將從節點提高爲主節點、初始化slot等等。而且還能夠看見OPS、內存、key等性能狀況。另外能夠在web界面進行slot遷移的操做,具體能夠自行多試驗試驗。

 

1三、測試Codis

鏈接codis-proxy代理端口便可,而後操做redis命令。

$ redis-cli -h 10.0.60.152 -p 19000

127.0.0.1:19000> set k1 v1

OK


Zookeeper相關操做

查看zk中codis產品:

$ zkCli.sh -server 127.0.0.1:2181

[zk: 127.0.0.1:2181(CONNECTED) 1] ls /codis3/codis-demo/

proxy   slots   topom   group

查看zk中的dashboard信息:

[zk: 127.0.0.1:2181(CONNECTED) 2] get /codis3/codis-demo/topom

{

    "start_time": "2016-10-13 18:09:21.802793218 +0800 CST",

    "admin_addr": "10.0.60.152:18080",

    "product_name": "codis-demo",

    "pid": 3386,

    "pwd": "/usr/local/codis/src/github.com/CodisLabs/codis/extern/redis-2.8.21/src",

    "sys": "Linux"

}

查看zk中的slot狀態:

[zk: 127.0.0.1:2181(CONNECTED) 3] ls /codis3/codis-demo/slots

前面initslots初始化的全部Slot都保存在slots路徑下,每一個Slot是一個結點。隨便選取一個Slot結點,用get命令可以查看結點上附着的數據:

[zk: 127.0.0.1:2181(CONNECTED) 4] get /codis3/codis-demo/slots/slot-0334

{

    "id": 334,

    "group_id": 1,

    "action": {}

}

查詢zk中的server狀態:

[zk: 127.0.0.1:2181(CONNECTED) 5] get /codis3/codis-demo/group/group-0001

{

"id": 1,

"servers": [

{

"server": "10.0.60.152:6379",

"action": {}

},

{

"server": "10.0.60.154:6379",

"action": {

"state": "synced"

}

}

],

"promoting": {}

}

查詢zk中的proxy狀態:

[zk: 127.0.0.1:2181(CONNECTED) 6] ls /codis3/codis-demo/proxy/proxy-

proxy-919ce168362a7286e4081b600a00ca67 proxy-cdcec3cebe703a67688bb0fc3de21f76

proxy-b87c96f0bc6d8e62f196369c66cea7c2
[zk: 127.0.0.1:2181(CONNECTED) 7] get /codis3/codis-demo/proxy/proxy-919ce168362a7286e4081b600a00ca67

{

"id": 1,

"token": "919ce168362a7286e4081b600a00ca67",

"start_time": "2016-10-13 19:55:09.532570818 +0800 CST",

"admin_addr": "10.0.60.152:11080",

"proto_type": "tcp4",

"proxy_addr": "10.0.60.152:19000",

"product_name": "codis-demo",

"pid": 4532,

"pwd": "/usr/local/codis/src/github.com/CodisLabs/codis/extern/redis-2.8.21/src",

"sys": "Linux"

}

要是想系統重作,刪除此產品便可:rmr /codis3/codis_demo。
 

Codis常見問題修復

使用codis-admin命令行管理工具進行修復。

1)codis-dashboard異常退出的修復

當codis-dashboard啓動時,會在外部存儲上存放一條數據,用於存儲 dashboard 信息,同時做爲LOCK存在。當codis-dashboard安全退出時,會主動刪除該數據。

當codis-dashboard異常退出時(大多數狀況zookeeper鏈接異常時會異常退出),因爲以前LOCK未安全刪除,重啓每每會失敗。所以codis-admin提供了強制刪除工具:

一、確認codis-dashboard進程已經退出(很重要);

二、而後運行codis-admin刪除LOCK:

codis-admin --remove-lock --product=codis_demo --zookeeper=127.0.0.1:2181

或者刪除topom

[zk: 127.0.0.1:2181(CONNECTED) 13] rmr /codis3/codis-demo/topom

正常關閉codis-dashboard:

codis-admin --dashboard=10.0.60.152:18080 --shutdown

 

2)codis-proxy異常退出的修復

一般codis-proxy都是經過codis-dashboard進行移除,移除過程當中codis-dashboard爲了安全會向codis-proxy發送offline指令,成功後纔會將proxy 信息從外部存儲中移除。若是codis-proxy異常退出,該操做會失敗。此時可使用codis-admin工具進行移除:

一、確認codis-proxy進程已經退出(很重要);

二、運行codis-admin刪除proxy,首先查看proxy狀態:

codis-admin --dashboard=10.0.60.152:18080 --proxy-status

或用

codis-admin --dashboard=10.0.60.152:18080 --list-proxy

根據查看到的信息,強制刪除報錯的codis-proxy。

codis-admin --dashboard=10.0.60.152:18080 --remove-proxy --token=6a2db3c9ac07ba8857d4bc79ca6d191c  --force
codis-admin --dashboard=10.0.60.152:18080 --remove-proxy --addr=127.0.0.1:11080 --force

選項–force表示,不管offline操做是否成功,都從外部存儲中將該節點刪除。因此操做前,必定要確認該codis-proxy進程已經退出。

codis-proxy正常關閉

codis-admin --proxy=10.0.60.152:11080 --auth="xxxxx" --shutdown

 

3)jodis鏈接proxy顯示Proxy list is empty問題處理

參考:https://github.com/CodisLabs/jodis/issues/10

 

codis數據遷移

安全和透明的數據遷移是Codis提供的一個重要的功能,也是Codis區別於Twemproxy等靜態的分佈式Redis解決方案的地方。

數據遷移的最小單位是key,咱們在codis redis中添加了一些指令,實現基於key的遷移,如SLOTSMGRT等 (命令列表),每次會將特定slot一個隨機的key 發送給另一個codis redis實例,這個命令會確認對方已經接收,同時刪除本地的這個k-v 鍵值,返回這個slot的剩餘key的數量,整個操做是原子的。

遷移的過程對於上層業務來講是安全且透明的,數據不會丟失,上層不會停止服務。

注意,遷移的過程當中打斷是能夠的,可是若是中斷了一個正在遷移某個slot的任務,下次須要先遷移掉正處於遷移狀態的slot,不然沒法繼續 (即遷移程序會檢查同一時刻只能有一個slot處於遷移狀態)。

 

codis-proxy高可用問題?

由於codis-proxy是無狀態的,能夠比較容易的搭多個實例,達到高可用性和橫向擴展。對Java用戶來講,可使用基於Jedis的實現Jodis,來實現proxy層的HA:

  • 它會經過監控zookeeper上的註冊信息來實時得到當前可用的proxy列表,既能夠保證高可用性;
  • 也能夠經過輪流請求全部的proxy實現負載均衡。

對於其餘語言,可使用haproxy代理到後端的多個codis-proxy,達到負載均衡的做用。而haproxy的單點問題可使用keepalive作HA,這樣就能夠實現一個高可用高併發的codis-proxy了。

 

codis-dashboard高可用問題?

Codis Dashboard:集羣管理工具,支持codis-proxy、codis-serve的添加、刪除,以及數據遷移等操做。在集羣狀態發生改變時,codis-dashboard 維護集羣下全部codis-proxy的狀態的一致性。

但須要注意的是對於同一個業務集羣而言,同一個時刻codis-dashboard只能有0個或者1個。另外全部對集羣的修改都必須經過codis-dashboard完成。因爲自己的限制,codis-dashboard沒法作到高可用。也就是說若是你集羣中的codis-dashboard掛掉了,那麼你將沒法對集羣作出更改操做,另外你的codis-fe界面也會異常(獲取不到數據),但值得慶幸的是此時你的codis-集羣對外服務不會出現任何問題。你須要作的就是去集羣中的其餘節點開啓codis-dashboard便可,此時會從新去zookeeper中註冊信息,集羣操做不會有任何問題,因此也沒必要太擔憂codis-dashboard掛掉了,只須要作好監控及時報警便可。

另外,此時的codis-fe須要更改一下配置文件,也就是把codis-dashboard的地址更換爲新的codis-dashboard主機便可;而後從新啓動codis-fe,此時整個codis集羣又恢復了最初的完整性,期間不會對客戶端鏈接形成任何影響。

 

Redis高可用問題?

對下層的redis實例來講,當一個group的master掛掉的時候,應該讓管理員清楚,並手動的操做,由於這涉及到了數據一致性等問題(redis的主從同步是最終一致性的)。所以codis不會自動的將某個slave升級成master。關於外部codis-ha工具(具體能夠參考以前的章節),這是一個經過codis-dashboard開放的RESTful API實現自動切換主從的工具。該工具會在檢測到master掛掉的時候主動應用主從切換策略,提高單個slave成爲新的master。

須要注意,codis將其中一個slave升級爲master時,該組內其餘slave實例是不會自動改變狀態的,這些slave仍將試圖從舊的master上同步數據,於是會致使組內新的master和其餘slave之間的數據不一致。所以當出現主從切換時,須要管理員手動建立新的sync action來完成新master與slave之間的數據同步(codis-ha不提供自動操做的工具,由於這樣太不安全了)。

 

codis-fe安全問題?

默認狀況下,codis-fe圖形化界面沒有任何安全措施,任何人只要知道地址均可以登陸操做codis集羣。此時你能夠藉助nginx/Apache的訪問控制來進行codis-fe訪問控制。提升codis-fe安全性。

 

Codis相關腳本

標準多codis實例目錄

# proxy_19000;

$ mkdir -p /data/codis/proxy_19000/bash

$ mkdir -p /data/codis/proxy_19000/conf

$ mkdir -p /data/codis/proxy_19000/log

$ mkdir -p /data/codis/proxy_19000/run



# proxy_19001;

$ mkdir -p /data/codis/proxy_19001/bash

$ mkdir -p /data/codis/proxy_19001/conf

$ mkdir -p /data/codis/proxy_19001/log

$ mkdir -p /data/codis/proxy_19001/run

而後在各自的實例的/data/codis/proxy_19001/bash/目錄下添加如下腳本便可。
一、start_dashboard.sh

#!/bin/bash

#

nohup codis-dashboard --ncpu=2 --config=../conf/dashboard.toml --log=../log/dashboard.log --log-level=WARN &

二、add_group.sh

#!/bin/bash

#

# create group;

codis-admin --dashboard=10.0.60.152:18080 --create-group --gid=1

codis-admin --dashboard=10.0.60.152:18080 --create-group --gid=2



# add host;

codis-admin --dashboard=10.0.60.152:18080 --group-add --gid=1 --addr=10.0.60.152:6379

codis-admin --dashboard=10.0.60.152:18080 --group-add --gid=1 --addr=10.0.60.154:6379

codis-admin --dashboard=10.0.60.152:18080 --group-add --gid=2 --addr=10.0.60.153:6380

codis-admin --dashboard=10.0.60.152:18080 --group-add --gid=2 --addr=10.0.60.154:6380



# configuration maser/slave;

codis-admin --dashboard=10.0.60.152:18080 --sync-action --create --addr=10.0.60.154:6379

codis-admin --dashboard=10.0.60.152:18080 --sync-action --create --addr=10.0.60.154:6380

三、start_proxy.sh

#!/bin/bash

#

nohup codis-proxy --ncpu=2 --config=../conf/proxy.toml --log=../log/proxy.log --log-level=WARN &

四、start_fe.sh

#!/bin/bash

#

nohup `which codis-fe` --ncpu=2 --log=../log/fe.log --log-level=WARN --dashboard-list=../conf/codis.json --listen=0.0.0.0:8080 &

五、initslot.sh

codis-admin --dashboard=10.0.60.152:18080 --slot-action --create-range --beg=0 --end=511 --gid=1

codis-admin --dashboard=10.0.60.152:18080 --slot-action --create-range --beg=512 --end=1023 --gid=2

注意按照順序依次啓動便可。因爲codis一旦跟zookeeper鏈接出現異常後codis-proxy就會異常退出,因此須要寫一個計劃任務監控腳本當codis_proxy異常退出時就報警而且自動拉起來。

#!/bin/bash

IP=10.0.60.152

PORT="19000 190001"

TIME=`date +%Y-%m-%d-%H-%M`

for port in $PORT;do

ps aux | grep -v grep | grep $port | grep codis-proxy &> /dev/null

ret=$?

if [ $ret -eq 0 ]; then

    echo "$TIME codis ${IP}:${port} is exist !" >> /data/codis/proxy_${port}/log/codis.log

else

    msg="$TIME codis ${IP}:${port} is down!"

            /usr/bin/curl    http://10.0.8.51:8888/sms/send  -d  "from=1000&to=15210491149&msg=$msg"

    echo "$TIME codis ${IP}:${port} is not exist !" >> /data/codis/proxy_${port}/log/codis.log

            cd /data/codis/proxy_${port}/bash

            sh start_proxy.sh > /dev/null 2>&1

    sleep 2

            sh set_proxy_online.sh > /dev/null 2>&1

    sleep 2

fi

done

完結。

爲了方便你們交流,本人開通了微信公衆號(關注看更多精彩)和QQ羣,QQ羣1(291519319)和QQ羣2(659336691)。喜歡技術的一塊兒來交流吧

相關文章
相關標籤/搜索