Redis集群部署与维护

目录:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

一、 修订记录 3

二、 集群架构 4

三、 集群部署 4

1 创建redis-cluster目录 4

2 编译redis 5

3 编辑redis配置文件 5

4 配置redis集群 6

5 redis集群性能测试 7

6 常用redis处理命令 7

7 对集群进行重新分片 8

8 故障转移测试 8

9 添加新节点到集群 9

10 redis单实例业务存储分析 10

四、 Redis优化 11

1 主从同步 11

1)全部同步 11

2)增量同步Replication Backlog 13

3)同步超时repl-timeout 14

2 redis持久化之AOF机制 15

1AOF机制 15

2AOF rewrite AOF的重写机制 17

五、redis 关闭RDB持久化

 

一、 修订记录

修订日期 

版本号

描述

修订人

2015-8-26

1.0.0

创建

 

2015-11-10

1.0.1

添加redis集群优化

 

2016-03-18

1.0.2

添加redis单实例业务数据分析

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

二、 集群架构

Redis集群部署与维护 随笔 第1张

 

redis主从对应关系:

master:192.168.205.228:7000 slave:192.168.205.188:8003

master:192.168.205.228:7001 slave:192.168.208.38:8005

master:192.168.205.188:7002 slave:192.168.208.38:8004

master:192.168.205.188:7003 slave:192.168.205.228:8000

master:192.168.208.38:7004 slave:192.168.205.188:8002

master:192.168.208.38:7005 slave:192.168.205.228:8001

三、 集群部署

本次需要在三台服务器上搭建12redis,每台服务器4台,两主两从,形成一套redis集群系统,分别如下

192.168.205.228 7000 7001 8000 8001

192.168.205.188 7002 7003 8002 8003

192.168.208.38 7004 7005 8004 8005

其中7000-7005做主redis8000-8005做从redis,主从搭配根据redis-trib.rb执行的结果随机搭配。

1、 创建redis-cluster目录

cd /hxdata

mkdir redis-cluster

cd redis-cluster

mkdir 7000 7001 8000 8001

2、 编译redis

cd /usr/local/src/

wget http://download.redis.io/releases/redis-3.0.5.tar.gz

tar zxvf ./redis-3.0.3.tar.gz

cd redis-3.0.3

make

make install

3、 编辑redis配置文件

cp /usr/local/src/redis-3.0.3/src/redis-server /hxdata/redis-cluster/7000/

cp /usr/local/src/redis-3.0.3/src/redis-server /hxdata/redis-cluster/7001/

cp /usr/local/src/redis-3.0.3/src/redis-server /hxdata/redis-cluster/8000/

cp /usr/local/src/redis-3.0.3/src/redis-server /hxdata/redis-cluster/8001/

 

vim /usr/local/src/redis-3.0.3/redis.conf

daemonize yes

port 7000

cluster-enabled yes

cluster-config-file nodes-7000.conf

cluster-node-timeout 5000

PS:redis.conf配置文件根据实际情况修改参数,此处先修改两个参数,daemonizeyes表示后台运行,默认为noport改成自定义的端口号,默认为6379,本地需要运行4redis,端口号分别为7000()-8000()7001()-8001()。因此,port需要对应修改。开启集群cluster功能,设置cluster配置文件和超时时间。

cp /usr/local/src/redis-3.0.3/redis.conf  /hxdata/redis-cluster/7000/

cp /usr/local/src/redis-3.0.3/redis.conf  /hxdata/redis-cluster/7001/

cp /usr/local/src/redis-3.0.3/redis.conf  /hxdata/redis-cluster/8000/

cp /usr/local/src/redis-3.0.3/redis.conf  /hxdata/redis-cluster/8001/

 

/hxdata/redis-cluster/7000/redis-server /hxdata/redis-cluster/7000/redis.conf

/hxdata/redis-cluster/7001/redis-server /hxdata/redis-cluster/7001/redis.conf

/hxdata/redis-cluster/8000/redis-server /hxdata/redis-cluster/8000/redis.conf

/hxdata/redis-cluster/8001/redis-server /hxdata/redis-cluster/8001/redis.conf

4、 配置redis集群

通过集群命令行工具redis-trib.rb命令生存redis集群

./redis-trib.rb create --replicas 1 192.168.205.228:7000 192.168.205.228:7001 192.168.205.188:7002 192.168.205.188:7003 192.168.208.38:7004 192.168.208.38:7005 192.168.205.188:8002 192.168.205.188:8003 192.168.208.38:8004 192.168.208.38:8005 192.168.205.228:8000 192.168.205.228:8001

当看到一下信息表示集群配置成功

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.

Ps:配置redis集群时可能出现以下错误:

  • 错误内容:

/usr/bin/env: ruby: No such file or directory

yum install ruby

  • 错误内容:

./redis-trib.rb:24:in `require': no such file to load -- rubygems (LoadError)

from ./redis-trib.rb:24

yum install rubygems

  • 错误内容:

/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- redis (LoadError)

from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'

from ./redis-trib.rb:25

gem install redis

l 错误内容:

ERROR:  Could not find a valid gem 'redis' (>= 0), here is why:Unable to download data from https://rubygems.org/ - Errno::ECONNRESET: Connection reset by peer - SSL_connect (https://rubygems.org/latest_specs.4.8.gz)

gem sources --remove https://rubygems.org/

gem sources -a https://ruby.taobao.org/

gem sources -l

*** CURRENT SOURCES ***

 

https://ruby.taobao.org

# 请确保只有 ruby.taobao.org

gem install redis

5、 redis集群性能测试

redis-benchmark命令行工具在不通的主机上分别对另外两天主机进行测试

192.168.205.228 redis-benchmark -h 192.168.205.188 -p 7002 -n 1000000 -c 10

192.168.205.188 redis-benchmark -h 192.168.205.38 -p 7004 -n 1000000 -c 10

192.168.208.38 redis-benchmark -h 192.168.208.228 -p 7000 -n 1000000 -c 10

6、 常用redis处理命令

redis-benchmark: redis基准信息,redis服务器性能检测

redis-cli:redis客户端

./redis-trib.rb check 127.0.0.1:7000:检查集群状态

./redis-trib.rb reshard:redis分片工具

./redis-trib.rb add-node:增加节点

./redis-trib.rb del-node:删除节点

redis-cli –p 7000 cluster nodes:查看集群信息

redis-cli -c -p 8000 cluster replicate fcd07fd4f84fc60bf4a2a54519523bb00f853db1:设置80007003从节点

CLUSTER ADDSLOTS slot1 [slot2] ... [slotN]:将哈希槽指派给节点

CLUSTER DELSLOTS slot1 [slot2] ... [slotN]:移除某个节点的哈希槽

CLUSTER SETSLOT slot NODE node: 将指定的槽 slot 指派给节点 node

CLUSTER SETSLOT slot MIGRATING node: 将给定节点 node 中的槽 slot 迁移出节点,例:向节点 B 发送命令 CLUSTER SETSLOT 8 IMPORTING A

 

CLUSTER SETSLOT slot IMPORTING node: 将给定槽 slot 导入到节点 node,例:向节点 A 发送命令 CLUSTER SETSLOT 8 MIGRATING B

7、 对集群进行重新分片

./redis-trib.rb reshard 127.0.0.1:7000

8、 故障转移测试

redis-cli -p 7000 cluster nodes | grep master

 Redis集群部署与维护 随笔 第2张

redis-cli -p 7001 debug segfault

设置192.168.205.228:7001 redis失效

 Redis集群部署与维护 随笔 第3张 

redis-cli -p 7000 cluster nodes

可以看到192.168.205.228:7001的状态为failed,并且它的从库192.168.208.38:8005slave变更为master,说明主从配置正常

 Redis集群部署与维护 随笔 第4张

 

9、 添加新节点到集群

192.168.208.38上创建一个新的redis节点7006

cd /data/redis-cluster/

mkdir 7006

cd ./7005

cp redis-server ../7006

cp redis.conf ../7006

cd ../7006

vim redis.conf

port 7006

./redis-server ./redis.conf

lsof –i:7006

Redis集群部署与维护 随笔 第5张

 

192.168.205.228主机上将新增节点加入集群中

./redis-trib.rb add-node 192.168.208.38:7006 192.168.205.228:7000

redis-cli -p 7000 cluster nodes

可以看到红线处,7006已经加入集群

 Redis集群部署与维护 随笔 第6张

 

但是它目前还没有哈希槽,所以还不能算是主节点

 Redis集群部署与维护 随笔 第7张

 

设置7006为主节点

./redis-trib.rb reshard 127.0.0.1:7000

 Redis集群部署与维护 随笔 第8张

移动1000哈希槽到新节点

Redis集群部署与维护 随笔 第9张

输入新节点的ID

 Redis集群部署与维护 随笔 第10张

原节点是所有其它的节点

 Redis集群部署与维护 随笔 第11张

redis-cli -p 7000 cluster nodes

 Redis集群部署与维护 随笔 第12张

将新节点设置成192.168.208.38:7005slave

192.168.208.38

redis-cli –p 7006

127.0.0.1:7006> cluster replicate 4b78505d1a956edac2fd12dcb5301903855eafbb

 

10、 redis单实例业务存储分析

定期对redis集群中的某个实例(优先选择从库)进行业务存储分析,统计每个业务暂用内存的大小,合理规划内存的使用。当某个实例占用memory容量明显不同于其它实例时,可以通过此方法进行对比分析,查看是否有不合理的key占用大量的memory空间。

通过在一台从库上执行bgsave命令,将内存的数据通过rdb的方式持久化到硬盘上,由于bgsave命令会新开一个子进程,所以此命令并不影响主进程的使用,但是需要观察机器负载情况,如果因为其它原因(如硬盘读写问题)导致机器负载高,则会影响主进程的使用。

127.0.0.1:8000>bgsave

优化对rdb文件分析时间较长,出于安全考虑,最好将最新形成的rdb文件拷贝到非线上服务器上进行分析,如204.70/data1/下。

204.70上执行rdb分析的命令

rdb -c memory /data1/8000.rdb > 8000_20160318.csv

通过如下命令对形成的csv文件进行数据统计

cat 8001_20160312.csv | awk -F'[,|"]' '{print $4" "$6}' | awk -F '[_| ]' '{sum[$1]+=$NF}END{for(type in sum)print type,sum[type]}' | sort -nr -k2

示例:

Redis集群部署与维护 随笔 第13张

  

以上对redis集群单实例从库的数据分析,可以通过对单实例的数据来计算整个集群的业务数据分布和大小等情况。目前webredis cluster66从,所以如果计算整个集群mbkey容量,需要单实例的mb key大小乘以12,就可以得出mb业务的key在整个集群的占用内存的大小。

 

四、 Redis优化

1、 主从同步

1全部同步

 Redis集群部署与维护 随笔 第14张

 

redis主从完全同步时,从服务器都将向主服务器发送一个 SYNC 命令。接到 SYNC 命令的主服务器将开始执行 BGSAVE ,并在保存操作执行期间,将所有新执行的写入命令都保存到buffer这个缓冲区里面。当 BGSAVE 执行完毕后, 主服务器将执行保存操作所得的 .rdb 文件发送给从服务器, 从服务器接收这个 .rdb 文件, 并将文件中的数据载入到内存中。之后主服务器会以 Redis 命令协议的格式, 将写命令缓冲区中积累的所有内容都发送给从服务器。

但是,当从服务器载入rdb文件完成之前,buffer这个缓冲区满了,导致buffer超限,就会被redis master断开,从而出现I/O error trying to sync with MASTER: connection lost这个错误,这时就需要调整client-output-buffer-limit slave 后面的参数值。

redisslave bufferreplication buffermaster端上)存放的数据是下面三个时间内所有的master数据更新操作。

  • master执行rdb bgsave产生snapshot的时间
  • master发送rdbslave网络传输时间
  • slave load rdb文件把数据恢复到内存的时间

client-output-buffer-limit在配置文件中有三行配置,分别对一般clientslavepubsub

client-output-buffer-limit normal 0 0 0 #对一般的client  

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

client-output-buffer-limit pubsub 32mb 8mb 60 #对发布/订阅这种client

这里主要对slave做出调整

 Redis集群部署与维护 随笔 第15张

 

  • hard limit:buffer达到hard limit的限制后,master断开slave的连接
  • soft limit:当在soft seconds时间内,buffer的量达到soft limit的限制,master不会断开slave的连接,当buffer的量在soft seconds时间后依然超出soft limit的限制,则断开slave的连接。

redis处于运行状态并且不能重启的情况下,可以通过config set命令来调整client-output-buffer-limit参数,soft limithard limit需要换成字节。

config set client-output-buffer-limit  "normal 0 0 0 slave 536870912 536870912 120 pubsub 33554432 8388608 60"

2增量同步Replication Backlog

Redis 2.8 以后增加了部分同步功能, 这个功能主要用来抗网络闪断用的, 对于新加入的 Slave 是不适用,Redis 每次启动时都会随机生成一个 runid, 用来标识这个实例, 只有 runid 相同的才能使用增量同步, 所以 Slave 一旦重启只能全量同步。当 Slave 断开再重新连接 Master , 会带上上次同步的 offset , Master 根据这个值来决定发送那些数据给 Slave

当主服务器进行命令传播的时候,Maser不仅将所有的数据更新命令发送到所Slavereplication buffer,还会写入replication backlog,断开的Slave重新连接上Master的时候,Slave将会发送psync命令(包含复制的偏移量offset),请求partial resync。如果请求的 runid 不存在,那么执行全量的sync操作,相当于重新建立主从复制。

Replication Buffer Replication Backlog 的区别

  • Replication Buffer 对应于每个 Slave,通过 config set client-output-buffer-limit slave 设置, 每个Slave 一个单独的Buffer
  • replication backlog 是一个环形缓冲区,整个 Master 进程中只会存在一个,所有的 Slave公用
  • backlog 的大小通过repl-backlog-size参数设置, 默认值 1M
  • repl_backlog redis 启动的时候初始化为NULL,当有Slave连接上来的时候,会被指向创建的buffer
  • 在所有slave都断开的情况下,backlog在默认的3600秒后释放,可以通过repl-backlog-ttl来设置断开时间

3同步超时repl-timeout

repl-timeout 60 replication连接的超时时间

三种情况认为复制超时:

  • slave角度,如果在repl-timeout时间内没有收到master SYNC传输的rdb snapshot数据
  • slave角度,在repl-timeout没有收到master发送的数据包或者ping
  • master角度,在repl-timeout时间没有收到REPCONF ACK确认信息

redis检测到repl-timeout超时(默认值60s),将会关闭主从之间的连接,redis slave发起重新建立主从连接的请求。对于内存数据集比较大的系统,可以增大repl-timeout参数。一般需要大于master生成rdb的时间+rdb传输时间+slave载入rdb到内存的时间。

2、 redis持久化之AOF机制

1AOF机制

AOF Append Only File,实现机制:Redis将数据库做个快照,遍历所有数据库,将数据库中的数据还原为跟客户端发送来的指令的协议格式的字符串,然后Redis新建一个临时文件将这些快照数据保存,待快照程序结束后将临时文件名修改为正常的aof文件名,原有的文件则自动丢弃,由于在快照进行的过程中可能存在新增的命令修改了数据库中的数据,则在快照程序结束后需要将新修改的数据追加到aof文件中,后续的从客户端过来的命令都会不断根据不同的安全级别写到磁盘里面去。这样就支持了实时的持久化,只是可能会有短时间内的数据丢失,对一般系统还是可以容忍的。

redis配置文件中有一下配置选项用来配置AOF

appendonly yes #开启AOF持久化

appendfilename "appendonly.aof" # 保存的文件名

# 将数据刷新到磁盘的策略

# appendfsync always # 只要有新数据就fsync

appendfsync everysec # 支持延迟fsync

# appendfsync no # 不需要fsync

no-appendfsync-on-rewrite no

# yes : 在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。

# no : 在日志重写时,命令追加操作照常进行。

在默认情况下 aof进行重写的时候,aof的同步信息不是关闭的。在这种情况下,子进程rewrite在写硬盘 主进程 aof也在写硬盘。在rewrite的过程中 子进程对主进程造成了磁盘阻塞(disk io冲突),导致了报警信息的产生。但是这个参数修改成 yes之后 ,又会有安全上的问题。当rewrite的过程中 要是redis down掉的话 丢失的数据 就不是之前appendfsync 定下的策略,而是整个 rewrite 过程中的所有数据。

auto-aof-rewrite-percentage 100 # 自动rewrite增量值 

auto-aof-rewrite-min-size 64mb # 自动rewriteAOF文件最小字节数

2AOF rewrite AOF的重写机制

Redis触发AOF rewrite机制有三种:

  • Redis Server接收到客户端发送的BGREWRITEAOF指令请求,如果当前AOF/RDB数据持久化没有在执行,那么执行,反之,等当前AOF/RDB数据持久化结束后执行AOF rewrite
  • Redis配置文件redis.conf中,用户设置了auto-aof-rewrite-percentageauto-aof-rewrite-min-size参数,并且当前AOF文件大小server.aof_current_size大于auto-aof-rewrite-min-size(server.aof_rewrite_min_size),同时AOF文件大小的增长率大于auto-aof-rewrite-percentage(server.aof_rewrite_perc)时,会自动触发AOF rewrite
  • 用户设置“config set appendonly yes”开启AOF的时,调用startAppendOnly函数会触发rewrite
  • BGREWRITEAOF
  • AOF文件刷新的方式,有三种,参考配置参数appendfsync appendfsync always每提交一个修改命令都调用fsync刷新到AOF文件,非常非常慢,但也非常安全;appendfsync everysec每秒钟都调用fsync刷新到AOF文件,很快,但可能会丢失一秒以内的数据;appendfsync no依靠OS进行刷新,redis不主动刷新AOF,这样最快,但安全性就差。默认并推荐每秒刷新,这样在速度和安全上都做到了兼顾。
  • 可能由于系统原因导致了AOF损坏,redis无法再加载这个AOF,可以按照下面步骤来修复:首先做一个AOF文件的备份,复制到其他地方;修复原始AOF文件,执行:$ redis-check-aof –fix ;可以通过diff –u命令来查看修复前后文件不一致的地方;重启redis服务。
  • LOG Rewrite的工作原理:同样用到了copy-on-write:首先redisfork一个子进程;子进程将最新的AOF写入一个临时文件;父进程 增量的把内存中的最新执行的修改写入(这时仍写入旧的AOFrewrite如果失败也是安全的);当子进程完成rewrite临时文件后,父进程会收到 一个信号,并把之前内存中增量的修改写入临时文件末尾;这时redis将旧AOF文件重命名,临时文件重命名,开始向新的AOF中写入。
  • 最后,为以防万一(机器坏掉或磁盘坏掉),记得定期把使用 filesnapshotting Append-only 生成的*rdb *.aof文件备份到远程机器上。我是用crontab每半小时SCP一次。我没有使用redis的主从功能 ,因为半小时备份一次应该是可以了,而且我觉得有如果做主从有点浪费机器。这个最终还是看应用来定了。

五、redis 关闭RDB持久化

Redis 2.2 或以上版本,可以在不重启的情况下,从 RDB 切换到 AOF :

    为最新的 dump.rdb 文件创建一个备份。
    将备份放到一个安全的地方。
    执行以下两条命令:

    redis-cli> CONFIG SET appendonly yes

    redis-cli> CONFIG SET save ""

    确保命令执行之后,数据库的键的数量没有改变。
    确保写命令会被正确地追加到 AOF 文件的末尾。

步骤 2 执行的第一条命令开启了 AOF 功能: Redis 会阻塞直到初始 AOF 文件创建完成为止, 之后 Redis 会继续处理命令请求, 并开始将写入命令追加到 AOF 文件末尾。

步骤 3 执行的第二条命令用于关闭 RDB 功能。 这一步是可选的, 如果你愿意的话, 也可以同时使用 RDB 和 AOF 这两种持久化功能

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄