部署codis-server

Codis Redis和普通的Redis启动方式一样的,这里创建4个Codis Redis实例,两两一组

Master  192.168.119.100:26379
Slave   192.168.119.100:26380
Master  192.168.119.100:26479
Slave   192.168.119.100:26480
  • 调整内存分配策略

echo "1" > /proc/sys/vm/overcommit_memory
echo "512" > /proc/sys/net/core/somaxconn
vim /etc/sysctl.conf

修改如下参数:
vm.overcommit_memory = 1
net.core.somaxconn = 512

让sysctl生效
sysctl -p

禁用大内存页面
echo "never" > /sys/kernel/mm/transparent_hugepage/enabled

加入开机自启
vim /etc/rc.local
加入如下参数:
if test -f /sys/kernel/mm/transparent_hugepage/enabled ; then  
  echo never > /sys/kernel/mm/transparent_hugepage/enabled  
fi
  • 生成配置文件

cp extern/redis-2.8.21/redis.conf redis26379.conf
cp extern/redis-2.8.21/redis.conf redis26380.conf
cp extern/redis-2.8.21/redis.conf redis26479.conf
cp extern/redis-2.8.21/redis.conf redis26480.conf
  • 修改配置文件

    将几个Redis实例的pidfile、port和dbfilename进行区分,以redis26379.conf为例(配置文件主要更改以下几点)

grep -v '#' redis26379.conf|egrep 'pidfile|port|dbfilename|slaveof'
pidfile /var/run/redis26379.pid
port 26379
dbfilename dump26379.rdb

grep -v '#' redis26380.conf|egrep 'pidfile|port|dbfilename|slaveof'
pidfile /var/run/redis26380.pid
port 26380
dbfilename dump26380.rdb
slaveof localhost 26379    #将26380设置成为26379的从库

grep -v '#' redis26479.conf|egrep 'pidfile|port|dbfilename|slaveof'
pidfile /var/run/redis26479.pid
port 26479
dbfilename dump26479.rdb

grep -v '#' redis26480.conf|egrep 'pidfile|port|dbfilename|slaveof'
pidfile /var/run/redis26480.pid
port 26480
dbfilename dump26480.rdb   
slaveof localhost 26479   #将26480设置成为26479的从库
  • 启动codis

bin/codis-server redis26379.conf
bin/codis-server redis26380.conf 
bin/codis-server redis26479.conf
bin/codis-server redis26480.conf

备注:codis不是不负责维护主从,而是不会自动持续维护主从状态。在手动添加slave的时候会发送slave of指令,如果redis的slave of不写在配置文件里,重启会被重置。

配置Redis Server Group

每个Server Group就是一个Redis服务器组,包括一个Master和多个Slave,group id从1开始算起

bin/codis-config server add 1 localhost:26379 master
bin/codis-config server add 1 localhost:26380 slave
bin/codis-config server add 2 localhost:26479 master
bin/codis-config server add 2 localhost:26480 slave

移除节点

bin/codis-config server remove-group 1
bin/codis-config server remove-group 2

备注:添加Redis Server Group,只允许有一个master,可以有多个slave,group id需要是大于等于1的整数。

设置server group服务的slot范围

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

例如:设置编号为[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

备注:Codis采用Pre-sharding 的技术来实现数据的分片,默认分成1024个slots (0-1023),每一个slot都会有一个特定的server group id,后端最多支持1024个Codis Server,路由信息保存在ZooKeeper中。

启动coids-proxy
bin/codis-proxy -c config.ini -L ./log/proxy.log  --cpu=32 --addr=0.0.0.0:19000 --http-addr=0.0.0.0:11000 &

备注:
--cpu 是codis-proxy 使用的CPU核数,根据主机的情况设置;
--addr是codis-proxy的redis server监听地址;
--http-addr是codis-proxy启动的http server,显示的调试信息可以访问 http://server_addr:port/debug/vars ;

启动dashboard时,codis管理界面端口为18087,10086的端口,实际上用不到;刚启动codis-proxy默认是处于offline的状态,需要设置为online状态

bin/codis-config -c config.ini proxy online proxy_1

设置proxy为offline

bin/codis-config proxy offline proxy_1
{
  "msg": "OK",
  "ret": 0
}
[5]   Exit 1                  bin/codis-proxy -c config.ini -L proxy.log --cpu=2 --addr=0.0.0.0:19000 --http-addr=0.0.0.0:11000

通过浏览器访问codis的管理界面:http://192.168.119.100:18087/admin/

测试

使用redis-benchmark随意写入一些数据

redis-benchmark -h 192.168.119.100 -p 19000 -n 500000 -P 100  -r 1048576 -d 256 -t get,set,mset -c 800
-n 发起的请求总数
-P Pipeline请求数
-d SET/GET值大小
-c 并列连接的客户端数量

使用脚本插入数据

#/bin/bash
for i in {1..1000}
do
  echo $i
  redis-cli -h 192.168.119.100 -p 19000 set name$i $i
done

测试一下redis-master和redis-slave是否正常同步数据了

在redis-master上写数据

redis-cli -h 192.168.119.100  -p 26379
192.168.119.100:26379>set name test
OK
192.168.119.100:26379>set age 24
OK
192.168.119.100:26379:7000>

在redis-slave查看是否把数据同步过来了

redis-cli -h 192.168.119.100  -p 26380
192.168.119.100:26380> get name
"test"
192.168.119.100:26380> get age
"29"
192.168.119.100:26380> 
可以看到正常同步的。

下面做个测试,测试大体内容是

1)假设redis-master有问题,也可以理解为挂了
2)在页面把redis-slave手动提升为master
3)把有问题的master下线
4)假如刚刚有问题的master已经正常恢复服务了,转为redis-slave

在上面已经测试了,在redis-master写数据,redis-slave上是可以看到数据同步过来的,现在在redis-slave上写数据,看主能不能看到

redis-cli -h 192.168.119.100  -p 26380
192.168.119.100:26380> set MySQL innodb
OK
192.168.119.100:26380> get MySQL
"innodb"
192.168.119.100:26380>

在redis-master查看

redis-cli -h 192.168.119.100  -p 26379
192.168.119.100:26379> keys *
1) "name"
2) "age"
192.168.119.100:26379> 

可以看到,redis-slave写数据,是不会到master上的。

现在模拟redis-master down机

ps -ef |grep 26379 
root       6466      1  0 09:28 ?        00:00:32 bin/codis-server *:26379  
kill -9 6466

在web页面刷新可以看到master已经挂了
我们把redis-slave提升master,点Promote to Master按钮即可:
可以看到本来的master已经变成offline下线状态了,这时我们把它删除掉,点后面的X删除主机。假如刚刚下线的redis服务器恢复正常了,再点上面的Add New Redis Instance按钮添加主机:
可以看到刚刚下线redis服务器,现在变成了redis-slave的角色了。我们测试下数据是否正常同步

注意:现在26380端口的角色是master的了,在它上面写数据

redis-cli -h 192.168.119.100  -p 26380
192.168.119.100:26380> set aa bb
OK
192.168.119.100:26380> set cc dd
OK
192.168.119.100:26380>

新的redis-slave上查看数据也是就26379端口对应的redis

192.168.119.100:26379> get aa
"bb"
192.168.119.100:26379> get cc
"dd"
192.168.119.100:26379>

可以看到是正常同步的。

在线增加分片

添加redis master和slave到group 4

codis-config -c config.ini server add 4 10.13.43.144:6379 master
codis-config -c config.ini server add 4 10.13.50.214:6380 slave
数据迁移

将slot id为[768-1023]的slot数据,迁移到 server group 4上,执行完命令后,数据会在后台迁移,web页面中可以看到迁移的状态。

codis-config -c $CODISCONF/config.ini slot migrate 768 1023 4

通过访问http://192.168.119.100:18087/slots

可以看到slots的排列情况,不同的Group是不同的颜色。这样作数据迁移后很容易看到slot迁移后的情况。
如果要迁移slots可以在管理界面选择Migrate Slot(s) 然后选择需要将哪些slots迁移到哪个Group

bin/codis-config slot migrate 0 511 2 --delay=10

正常的slots的状态是online,正在迁移的slots的状态是migrate

数据迁移migrate的问题

因为填错了组,所以导致这个迁移任务一致显示出错,reblance卡住不能动,对此的解决方法是,到zk下面的migrate_task里面删掉任务

sh /usr/local/zookeeper/bin/zkCli.sh
ls /zk/codis/db_test/migrate_tasks
#在显示的里面最小的那个任务号码。放到下面这一个去
delete /zk/codis/db_test/migrate_tasks/XXXXX任务号码XXXX
自动均衡

Codis支持动态的根据实例内存, 自动对slot进行迁移, 以均衡数据分布.

自动均衡slots分布需要满足几个条件

所有的codis-server都必须设置了maxmemory参数
所有的slots都应该处于online状态, 即没有迁移任务正在执行
所有server group都必须有Master

  • 执行自动均衡

管理界面
在管理界面点击Auto Rebalance

命令行方式
bin/codis-config slot rebalance

关于redis的配置maxmemory

为何要设置这个maxmemory呢,因为codes在做主从切换的时候,用的是codis-ha;

codis-ha实现codis-server的主从切换,codis-server主库挂了会提升一个从库为主库,从库挂了会设置这个从库从集群下线。 而这个codes-ha需要我们明确每个redis可以使用的最大内存。不能是NAN GB,所以需要我们配置这个属性。拉到redis自带的配置文件的中间地方,有下面这段,我们取消maxmemory的注释就好了。

# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU cache, or to set
# a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
maxmemory 1GB
codis-server的HA

当一个group的master挂掉的时候,codis不会自动的将某个slave升级成master,codis-ha实现codis-server的主从切换,codis-server主库挂了会提升一个从库为主库,从库挂了会设置这个从库从集群下线。

  • 安装

export GOPATH=$HOME/goproj
cd $GOPATH
go get github.com/ngaut/codis-ha
cd src/github.com/ngaut/codis-ha
go build
  • 使用方法

./codis-ha--codis-config=192.168.92.136:18087 --productName=test &

注:productName为集群项目名称,codis-config为codis dashboard地址。

  • 使用supervisord管理codis-ha进程

yum -y install supervisord
/etc/supervisord.conf中添加如下内容:
[program:codis-ha]
autorestart = True
stopwaitsecs = 10
startsecs = 1
stopsignal = QUIT
command = /root/goproj/src/github.com/ngaut/codis-ha --codis-config=192.168.92.136:18087 --productName=test
user = root
startretries = 3
autostart = True
exitcodes = 0,2
  • 启动supervisord服务

/etc/init.d/supervisord start
chkconfig supervisord  on

此时,ps -ef |grep codis-ha你会发现codis-ha进程已经启动,这个时候你去停掉一个codis-server的master,看看slave会不会提升为master呢