Redis 遷移 Codis 集羣方案

Redis集羣主要有五種方案:

官方cluster方案、twemproxy代理方案、哨兵模式、Codis、客戶端分片。

其中以豌豆莢的Codis使用最多,本文主要介紹Codis。

 

一、Codis 安裝

1. 安裝最新版 3.2

1) java 環境

yum -y  install java-1.8.0

2)go環境

tar zxvf /root/go1.8.3.linux-amd64.tar.gz -C /usr/local/

/usr/local/go/bin/go version

mkdir -p /data/go

echo 'export PATH=$PATH:/usr/local/go/bin:/usr/local/codis/bin'  >>/etc/profile

echo 'export GOPATH=/data/go'  >>/etc/profile

source /etc/profile

go env GOPATH

3) 安裝codis

4)安裝zookeeper

zookeeper 至少部署 3臺

 

二、集羣配置

1. 角色劃分

192.168.180.120 codis120 codis-server  zookeeper

192.168.180.121 codis121 codis-server  zookeeper

192.168.180.122 codis122 codis-server  zookeeper

192.168.180.123 codis123 codis-server  codis-proxy  nginx-tcp  lvs

192.168.180.124 codis124 codis-server  codis-proxy  nginx-tcp  lvs

192.168.180.125 codis125  codis-server  codis-dashboard codis-fe

 

2. 啓動codis-dashobard(codis125上操作)

修改dashboard.toml配置文件:

coordinator_name = "zookeeper"

coordinator_addr = "192.168.180.120:2181,192.168.180.121:2181,192.168.180.122:2181"

product_name = "codis-product1"

product_auth = ""

admin_addr = "0.0.0.0:18080"

啓動命令:

./admin/codis-dashboard-admin.sh start

 

3. 啓動codis-proxy(codis123與codis124上操作)

修改codis-proxy啓動腳本:

cat admin/codis-proxy-admin.sh | grep DASH

CODIS_DASHBOARD_ADDR="192.168.180.125:18080"

修改proxy.toml配置:

cat config/proxy.toml|grep -Ev "^#|^$"

product_name = "codis-product1"

product_auth = ""

session_auth = ""

admin_addr = "0.0.0.0:11080"

proto_type = "tcp4"

proxy_addr = "0.0.0.0:19000"

啓動codis-proxy腳本:

./admin/codis-proxy-admin.sh start

檢查日誌和端口:

cat log/codis-proxy.log

netstat -tulpn | grep codis-proxy

 

4. 啓動codis-server(需要在所有上操作)

1)修改啓動腳本

vim /usr/local/codis/admin/codis-server-admin-6379.sh start

vim /usr/local/codis/admin/codis-server-admin-6380.sh start

主要注意以下幾點

[root@codis125 codis]# cat /usr/local/codis/admin/codis-server-admin-6379.sh |grep -Ev "^#|^$"|grep 6379

CODIS_SERVER_PID_FILE=/data/codis/6379/redis_6379.pid

CODIS_SERVER_LOG_FILE=/data/codis/6379/redis_6379.log

CODIS_SERVER_CONF_FILE=$CODIS_CONF_DIR/redis-6379.conf

2)修改服務配置

[root@codis120 codis]# mkdir -p /data/redis/6379

[root@codis120 codis]# mkdir -p /data/redis/6380

[root@codis120 codis]# vim /usr/local/codis/config/redis-6379.conf

[root@codis120 codis]# vim /usr/local/codis/config/redis-6380.conf

主要是注意以下幾點

[root@codis120 codis]# cat /usr/local/codis/config/redis-6379.conf |grep -Ev "^#|^$"|grep 6379

port 6379

pidfile /data/redis/6379/redis_6379.pid

logfile "/data/redis/6379/redis_6379.log"

dir /data/redis/6379

3)啓動codis-server服務

[root@codis120 codis]# ./admin/codis-server-admin-6379.sh start

/usr/local/codis/admin/../config/redis-6379.conf

starting codis-server ...

[root@codis120 codis]# ./admin/codis-server-admin-6380.sh start

/usr/local/codis/admin/../config/redis-6380.conf

starting codis-server ...

 

5. 啓動codis-fe(codis125上操作)

1)修改codis-fe啓動腳本

[root@codis125 codis]# cat admin/codis-fe-admin.sh

主要修改這幾行

#!/usr/bin/env bash

#COORDINATOR_NAME="filesystem"

#COORDINATOR_ADDR="/tmp/codis"

COORDINATOR_NAME="zookeeper"

COORDINATOR_ADDR="192.168.180.120:2181,192.168.180.121:2181,192.168.180.122:2181"

2)啓動codis-fe腳本

[root@codis125 codis]#  ./admin/codis-fe-admin.sh start

3)訪問面板

http://192.168.188.125:9090/#codis-product1

 

6. codis-fe面板操作

1)通過codis-fe添加group

通過web瀏覽器訪問集羣管理頁面(fe地址:http://192.168.188.125:9090/#codis-product1) 選擇我們剛搭建的集羣 codis-product1,在 Proxy 欄可看到我們已經啓動的 Proxy, 但是

Group 欄爲空,因爲我們啓動的 codis-server 並未加入到集羣 添加 NEW GROUP,NEW GROUP 行輸入 1,再點擊 NEW GROUP 即可 添加 Codis Server,Add Server 行輸入我們剛剛啓動的

codis-server 地址,添加到我們剛新建的 Group,然後再點擊 Add Server 按鈕即可。

如上依次添加6個group,12個codis-server,默認每組裏面第一個添加的爲主,第二個添加的設置爲從,同一個節點2個實例不能設置爲同一group。

2)通過codis-fe初始化solt

新增的集羣 slot 狀態是 offline,因此我們需要對它進行初始化(將 1024 個 slot 分配到各個 group),而初始化最快的方法可通過 fe 提供的 rebalance all slots 按鈕來做,如下圖

所示,點擊此按鈕,我們即快速完成了一個集羣的搭建。

自動分配1024個solt到6個group,reblance all solts會自動分配完所以solt到6個group。

 

7. 代理HA

1)在codis123與codis124上安裝lvs與nginx-tcp

2)配置好VIP+19000端口爲第一個codis-dashboard業務線使用,其他類推

 

三、數據遷移

做好平滑的數據同步遷移,不影響業務正常使用。

redis-port 工具做數據遷移

參考:https://www.cnblogs.com/yotone/p/6556480.html

使用redis-port:

 [www@m180p10 redis-port]$  nohup ./bin/redis-port sync --ncpu=1 --from=192.168.180.10:6001 --password=whyredis --target=192.168.180.12:19002 --auth=codiswyt >> /opt/codis/redis-port/log/redis-to-codis.log  2>&1 &

 

1. 如何做到不停機,數據遷移?

數據遷移過程中,如果不停機,新集羣 和 舊集羣 數據只能是趨近於相等,但不可能絕對相等。

我們需要考慮的是,切流量那一會新打入舊集羣的緩存信息,在新集羣不存在,是否會影響業務?是否可以接受?

2. 如果有影響,那麼就需要考慮影響範圍最小化,如何最小化?

因爲緩存一旦沒有信息,勢必會穿透到DB, 這樣DB壓力會上升。

我們可以通過流量控制,開始只切5% 的流量(甚至更小 1%) 到 Codis, 觀察情況,沒問題逐步切流量到新集羣。

3. 梳理舊集羣 redis key, 分析哪些key 是必不可少的。檢查遷移是否有遺漏。

4. 故障回滾方式:灰度 和線上 兩份,連接新舊集羣,進行切換。

 

四、Codis 客戶端高可用

使用jodis做codis的連接,在項目中封裝多代理ip 輪詢負載均衡,實現高可用。

pom.xml配置:

<dependency>

       <groupId>io.codis.jodis</groupId>

      <artifactId>jodis</artifactId>

      <version>0.5.1</version>

</dependency>

properties 文件:

codis.zkAddr=127.0.0.1:2181,127.0.0.1:2181,127.0.0.1:2181

codis.zk.proxy.dir=/jodis/codis

codis.password=

 

1. 代碼實現

@Bean

public JedisResourcePool getPool() {

JedisPoolConfig poolConfig = new JedisPoolConfig();

poolConfig.setMaxIdle(max_idle);

poolConfig.setMaxTotal(max_active);

poolConfig.setTestOnBorrow(true); //在borrow一個jedis實例的時候,是否要進行驗證操作,如果賦值true。則得到的jedis實例肯定是可以用的。

poolConfig.setTestOnReturn(true); //在return一個jedis實例的時候,是否要進行驗證操作,如果賦值true。則放回jedispool的jedis實例肯定是可以用的。

poolConfig.setMaxWaitMillis(max_wait);

poolConfig.setBlockWhenExhausted(false); //連接耗盡的時候,是否阻塞,false 會拋出異常,true 阻塞直到超時。默認爲true。

JedisResourcePool pool = RoundRobinJedisPool.create().poolConfig(poolConfig)

.curatorClient(zkAddr, timeout)

.password(password).zkProxyDir(zkProxyDir).build();

return pool;

}

注意:如果沒有設置密碼,以上代碼去掉password。

封裝以上jedisPool爲啓動時加載,注入bean,其他服務使用時,注入即可。

線上環境使用時,將127.0.0.1 換成自己的真實ip即可,這裏只是範例。

 

2. Spring 配置方式接入

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">

<!--最大分配的對象樹 -->

<property name="maxTotal" value="1024"></property>

<!--最大能夠保持idle狀態的對象數 -->

<property name="maxIdle" value="0"></property>

<!--當緩存池內沒有返回數據時,最大等待時間 -->

<property name="maxWaitMillis" value="1000"></property>

<!-- 當調用borrow Object方法時,是否進行有效性檢查 -->

<property name="testOnBorrow" value="false"></property>

<!--當調用return Object方法時,是否進行有效性檢查 -->

<property name="testOnReturn" value="false"></property>

</bean>

<bean id="jedisPool" class="com.deppon.cache.store.RedisClient">

<property name="host" value="127.0.0.1:2181,127.0.0.1:2181,127.0.0.1:2181"></property>

<property name="timeout" value="30000"></property>

<property name="zkProxyDir" value="/jodis/codis"></property>

<property name="poolConfig" ref="poolConfig"></property>

</bean>

 

五、踩坑

報錯: JedisException- Proxy list empty

解決:

1. 檢查proxy是否已經成功的添加到集羣中,在zk中就可以查看。/jodis/productName路徑下,看是否有對應的proxy。

如:

 

 

2. 修改codis3的proxy.toml文件

# Set jodis address & session timeout.

jodis_addr = "127.0.0.1:2181,127.0.0.1:2181,127.0.0.1:2181" 

jodis_addr必須設置

 

報錯: Could not get a resource from the pool

查詢異常詳情,發現 cause by ERR Client sent AUTH, but no password is set

這裏意思是服務端沒有設置password,客戶端鏈接是確使用了password ,就會報這個錯誤。去掉password 即可。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章