一、Codis简介

Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别 (不支持的命令列表), 上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务.

二、Codis组成部分

1、Codis Proxy   (codis-proxy)

codis-proxy 是客户端连接的 Redis 代理服务, codis-proxy 本身实现了 Redis 协议, 表现得和一个原生的 Redis 没什么区别 (就像Twemproxy), 对于一个业务来说, 可以部署多个 codis-proxy, codis-proxy 本身是无状态的.

2、Codis Manager (codis-config)

codis-config 是 Codis 的管理工具, 支持包括, 添加/删除 Redis 节点, 添加/删除 Proxy 节点, 发起数据迁移等操作. codis-config 本身还自带了一个 http server, 会启动一个 dashboard, 用户可以直接在浏览器上观察 Codis 集群的运行状态.

3、Codis Redis   (codis-server)

codis-server 是 Codis 项目维护的一个 Redis 分支, 基于 2.8.13 开发, 加入了 slot 的支持和原子的数据迁移指令. Codis 上层的 codis-proxy 和 codis-config 只能和这个版本的 Redis 交互才能正常运行.

4、ZooKeeper

Codis 依赖 ZooKeeper 来存放数据路由表和 codis-proxy 节点的元信息, codis-config 发起的命令都会通过 ZooKeeper 同步到各个存活的 codis-proxy.

三、Codis常用架构

Codis 支持按照 Namespace 区分不同的产品, 拥有不同的 productname 的产品, 各项配置都不会冲突.目前 Codis 已经是稳定阶段,目前豌豆荚已经在使用该系统。常用架构图如下图所示:


四、Codis实验项目

1、实现拓扑图


2、准备工作

下载安装包:可到官网下载最新版
  • jdk1.8.0_45

  • Zookeeper-3.4.6

  • Go1.6.2

创建目录
Mkdir /data/packages

3、部署zookeeper

每个zookeeper节点上安装java环境

[root@localhost ~]# cd /data/packages/
[root@localhost packages]# tar xf jdk-8u91-linux-x64.tar.gz -C /usr/local/
[root@localhost packages]# cd /usr/local/
[root@localhost local]# ln -s jdk1.8.0_91 java

安装zookeeper

[root@localhost packages]# tar xf zookeeper-3.4.6.tar.gz -C /usr/local/
[root@localhost packages]# cd /usr/local/
[root@localhost local]# ln -s zookeeper-3.4.6 zookeeper

设置java环境变量并生效

[root@localhost local]# cat /etc/profile.d/java.sh
JAVA_HOME=/usr/local/java
JRE_HOME=$JAVA_HOME/jre
ZOOKEEPER_HOME=/usr/local/zookeeper
JAVA_FONTS=/usr/local/java/jre/lib/fonts 
CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$ZOOKEEPER_HOME/bin 
export JAVA_HOME PATH CLASSPATH JRE_HOME ZOOKEEPER_HOME

[root@localhost local]# source /etc/profile.d/java.sh

修改zookeeper配置文件

[root@localhostlocal]#cp /usr/local/zookeeper/conf/zoo_sample.cfg /usr/local/zookeeper/conf/zoo.cfg
[root@localhost local]# vim /usr/local/zookeeper/conf/zoo.cfg
[root@localhost local]# cat /usr/local/zookeeper/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
clientPort=2181
autopurge.snapRetainCount=500 
autopurge.purgeInterval=24
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/logs
server.1=192.168.0.152:2888:3888
server.2=192.168.0.154:2888:3888
server.3=192.168.0.155:2888:3888

按上面配置文件中设置创建数据目录和日志目录

Mkdir –p /data/zookeeper/data
Mkdir –p /data/zookeeper/logs

在每台zookeeper节点上创建myid,节点对应id

在第一台机上创建myid,对应配置文件中server.1
Echo 1 > /data/zookeeper/data/myid
在第二台机上创建myid,对应配置文件中server.2
Echo 2 > /data/zookeeper/data/myid
在第三台机上创建myid,对应配置文件中server.3
Echo 3 > /data/zookeeper/data/myid

每台机器上面启动zookeeper

[root@node1 ~]# zkServer.sh start
JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

每台机上zookeeper启动后状态

[root@node1 ~]# zkServer.sh status
JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower

[root@localhost local]# zkServer.sh status
JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: leader

[root@localhost local]# zkServer.sh status
JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Mode: follower

4、部署codis集群

所有codis机器上安装go语言环境

Cd /data/packages
[root@node1 packages]# tar xf go1.6.2.linux-amd64.tar.gz -C /usr/local/

添加go环境变量并使用source读入使其生效

[root@node1 packages]# cat /etc/profile.d/go.sh
GOROOT=/usr/local/go
GOPATH=/usr/local/codis
PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$ZOOKEEPER_HOME/bin:$GOROOT/bin:$GOPATH/bin
export JAVA_HOME PATH CLASSPATH JRE_HOME ZOOKEEPER_HOME GOROOT GOPATH
[root@node1 packages]# source /etc/profile.d/go.sh

所有codis节点安装codis

这里是使用go命令从git上下载然后执行make、make install操作,make时有点慢

使用rpm –ql git来查看本机是否已安装git,如没有安装则使用yum命令自行安装即可

[root@node1 packages]# go get github.com/wandoulabs/codis
package github.com/wandoulabs/codis: no buildable Go source files in /usr/local/codis/src/github.com/wandoulabs/codis
[root@localhost packages]# cd /usr/local/codis/src/github.com/wandoulabs/codis/
[root@localhost codis]# make

如果make时报以下错误,说明是路径问题,使用下面方法解决:


[root@node1 ~]# cd /usr/local/codis/src/github.com/
[root@node1 github.com]# ln -s wandoulabs CodisLabs(如果不链接一个新路径,make时会报路径错误;曾经被误导好久,然后通过新路径进入)
[root@node1 github.com]# cd CodisLabs/codis/
[root@node1 codis]# make
[root@node1 codis]# make gotest

安装完成后创建并复制文件:

[root@node1 codis]# mkdir -p /usr/local/codis/{logs,conf,scripts}
[root@node1 codis]# mkdir -p /data/codis_server/{logs,conf,data}
[root@node1 codis]# cp -rf bin /usr/local/codis/
[root@node1 codis]# cp config.ini /usr/local/codis/conf/
[root@node1 codis]# cp extern/redis-2.8.21/redis.conf /data/codis_server/conf/

5、配置codis_proxy

[root@node1 codis]# cat /usr/local/codis/conf/config.ini
coordinator=zookeeper
zk=192.168.0.152:2181,192.168.0.154:2181,192.168.0.155:2181
product=codis
dashboard_addr=192.168.0.152:18087
password=
backend_ping_period=5
session_max_timeout=1800
session_max_bufsize=131072
session_max_pipeline=1024
zk_session_timeout=30000
proxy_id=proxy_1
[root@localhost codis]# cat /usr/local/codis/conf/config.ini
coordinator=zookeeper
zk=192.168.0.152:2181,192.168.0.154:2181,192.168.0.155:2181
product=codis
dashboard_addr=192.168.0.152:18087
password=
backend_ping_period=5
session_max_timeout=1800
session_max_bufsize=131072
session_max_pipeline=1024
zk_session_timeout=30000
proxy_id=proxy_2
[root@localhost codis]# cat /usr/local/codis/conf/config.ini
coordinator=zookeeper
zk=192.168.0.152:2181,192.168.0.154:2181,192.168.0.155:2181
product=codis
dashboard_addr=192.168.0.152:18087
password=
backend_ping_period=5
session_max_timeout=1800
session_max_bufsize=131072
session_max_pipeline=1024
zk_session_timeout=30000
proxy_id=proxy_3

所有codis机器修改配置文件并启动codis-server:

[root@node1 packages]# cd /data/codis_server/conf/
[root@node1 conf]# ls
redis.conf
[root@node1 conf]# mv redis.conf 6379.conf
[root@node1 conf]# vim 6379.conf
daemonize yes
pidfile /var/run/6379.pid
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 0
loglevel notice
logfile "/data/codis_server/logs/codis_6379.log"
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename 6379.rdb
dir /data/codis_server/data
slave-serve-stale-data yes
slave-read-only yes

复制配置文件启动多实例:

[root@node1 conf]# cp 6379.conf 6380.conf
[root@node1 conf]# sed -i 's/6379/6380/g' 6380.conf

添加内核参数

[root@node1 conf]# echo "vm.overcommit_memory = 1" >>  /etc/sysctl.conf
[root@node1 conf]# sysctl –p

启动codis服务

[root@node1 conf]# /usr/local/codis/bin/codis-server /data/codis_server/conf/6379.conf 
[root@node1 conf]# /usr/local/codis/bin/codis-server /data/codis_server/conf/6380.conf

启动dashboard

/usr/local/codis/bin/codis-config /usr/local/codis/conf/config.ini dashboard &

初始化solt

/usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini slot init –f

通过http://192.168.0.152:18087来打开网页

Codis集群实现和安装详解_java

添加server groups,每一个server groups作为一个codis服务器组,且每一个组只有一个master多个slave;

[root@localhost scripts]# /usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini server add 1 192.168.0.152:6379 master
[root@localhost scripts]# /usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini server add 1 192.168.0.154:6380 slave
[root@localhost scripts]# /usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini server add 2 192.168.0.154:6379 master
[root@localhost scripts]# /usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini server add 2 192.168.0.155:6380 slave
[root@localhost scripts]# /usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini server add 3 192.168.0.155:6379 master
[root@localhost scripts]# /usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini server add 3 192.168.0.152:6380 slave

Codis集群实现和安装详解_java_02

设置 server group 服务的 slot 范围 Codis 采用 Pre-sharding 的技术来实现数据的分片, 默认分成 1024 个 slots (0-1023), 对于每个key来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) % 1024 每一个 slot 都会有一个且必须有一个特定的 server group id 来表示这个 slot 的数据由哪个 server group 来提供.

[root@localhost scripts]# /usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini slot range-set 0 300 1 online
[root@localhost scripts]# /usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini slot range-set 301 700 2 online
[root@localhost scripts]# /usr/local/codis/bin/codis-config -c /usr/local/codis/conf/config.ini slot range-set 701 1023 3 online

Codis集群实现和安装详解_java_03

Codis集群实现和安装详解_java_04

启动codis-proxy

这里在192.168.0.152机上启动其余改下名称即可启动
/usr/local/codis/bin/codis-proxy -c /usr/local/codis/conf/config.ini -L /usr/local/codis/logs/codis_proxy_1.log --cpu=8 --addr=0.0.0.0:19000 --http-addr=0.0.0.0:11000 &

配置codis-ha,实现codis-server的主从切换,主库挂了会提升一个从库为主库,从库挂了会将这个从库直接下线:

任意一台配置即可
[root@localhost ~]# go get github.com/ngaut/codis-ha
[root@localhost ~]# cd /usr/local/codis/src/github.com/ngaut/
[root@localhost ngaut]# cp -r codis-ha /usr/local/
[root@localhost ngaut]# cd /usr/local/codis
[root@localhost codis]# cd ..
[root@localhost local]# cd /usr/local/codis-ha/
[root@localhost codis-ha]# go build

创建codis-ha启动脚本

[root@localhost codis-ha]# vim /usr/local/codis-ha/start_codis_ha.sh
./codis-ha --codis-config=192.168.0.152:18087 -log-level="info" --productName=vmware-Codis &> ./logs/codis-ha.log &

创建日志目录

[root@localhost codis-ha]# mkdir /usr/local/codis-ha/logs

启动codis-ha

[root@localhost codis-ha]# sh start_codis_ha.sh 
[root@localhost codis-ha]# ps aux | grep codis-ha
root      51524  0.2  1.1 128584 11596 pts/1    Sl   00:15   0:00 ./codis-ha --codis-config=192.168.0.152:18087 -log-level=info --productName=vmware-Codis
root      51534  0.0  0.0 103252   836 pts/1    S+   00:20   0:00 grep codis-ha

6、Codis故障切换自动转移

现在把154机上codis主下线

[root@localhost codis]# ps aux | grep codis
root      49177  0.1  1.1 141484 11684 ?        Ssl  20:47   0:20 /usr/local/codis/bin/codis-server *:6379                           
root      49181  0.1  0.9 137388  9624 ?        Ssl  20:47   0:18 /usr/local/codis/bin/codis-server *:6380                           
root      49295  0.0  0.0 103252   836 pts/0    S+   23:43   0:00 grep codis
[root@localhost codis]# kill 49177
[root@localhost codis]# ps aux | grep codis
root      49181  0.1  0.9 137388  9624 ?        Ssl  20:47   0:18 /usr/local/codis/bin/codis-server *:6380                           
root      49297  0.0  0.0 103252   832 pts/0    S+   23:43   0:00 grep codis

Codis集群实现和安装详解_java_05

现在codis就搭建好了,当然也可以部署keepalived+haproxy高可用负载,这里就不介绍了,有兴趣的可以自己找下相关文档.