概念与了解:Redis(1.7)Redis高可用架构(理论篇)
【0】试验环境
结构图如下:
(这里试验没有那么多机器,就用3台机器搭建试验)
redis1是redis集群的一个节点A,上面运行了两个redis实例,7001 7004
redis2是redis集群的一个节点B,上面运行了两个redis实例,7002 7005
redis3是redis集群的一个节点C,上面运行了两个redis实例,7003 7006
-- 试验集群包含 A/B/C A1/B1/C1 6个节点
A、B、C 为主节点对应Redis实例:7001 7002 7003
A1、A2、A3 为主节点的从库,对应Redis实例:7004 7005 7006
-- 交叉构建主从节点,对应关系为
【A > B】 【B>C】 【C>A1】
A:192.168.135.173
B:192.168.135.174
C:192.168.135.175
-- IP与端口分布:
redis4.0.11版本
cluster1:
主:192.168.135.173 7001 /data/redis/redis-cluster/nodes-7001/redis.conf
备:192.168.135.174 7005 /data/redis/redis-cluster/nodes-7005/redis.conf
cluster2:
主:192.168.135.174 7002 /data/redis/redis-cluster/nodes-7002/redis.conf
备:192.168.135.175 7006 /data/redis/redis-cluster/nodes-7006/redis.conf
cluster3:
主:192.168.135.175 7003 /data/redis/redis-cluster/nodes-7003/redis.conf
备:192.168.135.175 7004 /data/redis/redis-cluster/nodes-7004/redis.conf
-- 外界连接策略
外端可以用F5、keepalived+haproyx结果,实现2个负载均衡(3台主的写,3台备的读)
【1】安装redis
快速安装:
#【1.1】构建目录
#173 mkdir -p /data/redis/7001data mkdir -p /data/redis/7001log mkdir -p /data/redis/7001conf mkdir -p /data/redis/7004data mkdir -p /data/redis/7004log mkdir -p /data/redis/7004conf #174 mkdir -p /data/redis/7002data mkdir -p /data/redis/7002log mkdir -p /data/redis/7002conf mkdir -p /data/redis/7005data mkdir -p /data/redis/7005log mkdir -p /data/redis/7005conf #175 mkdir -p /data/redis/7003data mkdir -p /data/redis/7003log mkdir -p /data/redis/7003conf mkdir -p /data/redis/7006data mkdir -p /data/redis/7006log mkdir -p /data/redis/7006conf
#【1.2】安装(其实这一步可以省略,多实例不过是用不同的配置文件启动redis而已)
cd /soft/redis-4.0.14 && make PREFIX='/data/redis/7001data' install
cd /soft/redis-4.0.14 && make PREFIX='/data/redis/7004data' install
cd /soft/redis-4.0.14 && make PREFIX='/data/redis/7002data' install
cd /soft/redis-4.0.14 && make PREFIX='/data/redis/7005data' install
cd /soft/redis-4.0.14 && make PREFIX='/data/redis/7003data' install
cd /soft/redis-4.0.14 && make PREFIX='/data/redis/7006data' install
#【1.3】配置文件
vim /data/redis/7001conf/7001redis.conf
vim /data/redis/7004conf/7004redis.conf
vim /data/redis/7002conf/7002redis.conf
vim /data/redis/7005conf/7005redis.conf
vim /data/redis/7003conf/7003redis.conf
vim /data/redis/7006conf/7006redis.conf
然后目录和名字对应改一下即可(参数参考:Redis配置文件(4.0.14))
daemonize yes logfile "/data/redis/7001log/redis.log" #requirepass 123456
#masterauth 123456 bind 192.168.135.173 127.0.0.1 pidfile /data/redis/7001conf/redis.pid dbfilename redis.rdb dir /data/redis/7001conf/
port 7001
appendonly yes
appendfilename "appendonly.aof"
appendfsync always
cluster-enabled yes
cluster-config-file nodes-7001.conf
cluster-node-timeout 15000
appendonly yes
【1.4】全部启动起来
redis-server /data/redis/7001conf/7001redis.conf
.....以此为例
【1.5】构建的启动脚本 /data/redis/startall.sh,举例如下(每个机器根据自身情况修改)
#!/bin/bash if [ $1 == 'start' ]; then redis-server /data/redis/7002conf/7002redis.conf redis-server /data/redis/7005conf/7005redis.confelse redis-cli -p 7002 -h 192.168.135.174 shutdown redis-cli -p 7005 -h 192.168.135.174 shutdownfi
【2】安装redis-trib所需的 ruby脚本
注意(本文用的4.0.11 所以需要用ruby等一系列很麻烦的操作。redis 5.0以后的版本 可以直接使用 redis-cli的方式搭建(redis-cli --cluster create 192.168.80.131:7001 192.168.80.131:7002 192.168.80.131:7003 192.168.80.131:7004 192.168.80.131:7005 192.168.80.131:7006 --cluster-replicas 1),省去了第【2】步,直接到【3】)
一台机器装即可
3.0以上的redis才支持cluster,且需要 ruby 2.2以上版本才支持 redis-trib命令,而Centos7中默认的是2.0版本
ruby下载:http://www.ruby-lang.org/zh_cn/downloads/
ruby安装:http://www.ruby-lang.org/zh_cn/documentation/installation/#yum
如果是直接下的tar.gz,一般是源码。
yum源配置:Yum源配置
离线安装:https://blog.csdn.net/zhanaolu4821/article/details/99750304
#[2.1] 查看ruby是否存在
ruby -v
#如果存在则需要卸载原来的老版本
rpm -e ruby-2.0.0.648-33.el7_4.x86_64 --nodeps rpm -e ruby-irb-2.0.0.648-33.el7_4.noarch --nodeps rpm -e ruby-libs-2.0.0.648-33.el7_4.x86_64 --nodeps
#【2.2】安装依赖包
yum install -y zlib-devel curl-devel openssl-devel httpd-devel apr-devel apr-util-devel
#【2.3】源码安装ruby
#不存在可以去官网下载安装
#源码安装
./configure make make install ruby -v #检查是否安装成功
#默认情况下,Ruby 安装到 /usr/local
目录,并且已经在usr/local/bin/下面加了环境变量。
#如果想使用其他目录,可以把 --prefix=DIR
选项传给 ./configure
脚本。如果命令还是没用则退出登录用户再重登试试。
#【2.4】ruby-redis.gem安装(必须联网)
#这一步如果报错参考:gem install redis报错
#添加国内源命令
#gem source -l #查看当前gem源
#gem source -a https://gems.ruby-china.com/
#删除国外源并添加国内源
gem sources --add gem source -a https://gems.ruby-china.com/ --remove https://rubygems.org/
#要是自己下载的包就直接这样既可 gem install /soft/redis-4.1.3.gem
#要是网络安装
gem install redis
【3】创建redis cluster
前置核心:
(1)要先启动redis服务端
(2)设置集群的时候密码必须为空,可以设计好集群后再配置密码
(3)配置文件中的 bind 127.0.0.1 必须要改,改成 bind youripv4 127.0.0.1 ,这样其他机器和本机都可以直接访问
(4)如果redis数据库数据不为空,则删除掉所有的数据(比如 aof,rdb 等,还不赶紧则 flushall)
#【3.1】切换到源码目录下 cd /soft/redis-4.0.14/src/
cp ./redis-trib.rb /usr/bin #添加环境变量
#【3.2】开始创建集群
redis-trib.rb create --replicas 1 192.168.135.173:7001 192.168.135.173:7004 192.168.135.174:7002 192.168.135.174:7005 192.168.135.175:7003 192.168.135.175:7006
#5.0以后可以直接用 redis-cli --cluster create 192.168.80.131:7001 192.168.80.131:7002 192.168.80.131:7003 192.168.80.131:7004 192.168.80.131:7005 192.168.80.131:7006 --cluster-replicas 1
--cluster-replicas 1表示希望为集群中的每个主节点创建一个从节点(一主一从)。
--cluster-replicas 2表示希望为集群中的每个主节点创建两个从节点(一主二从)。
输完命令后,集群相关信息会展现出来如下图:(这个主从是自动判断分配的)
构建成功如下图:
#【3.3】创建失败
参考:Redis(1.12)Redis cluster搭建常见错误【4】连接集群及核验
#【4.1】去任意节点登录集群 redis-cli -c redis-cli -c -h 192.168.135.173 -p 7001
#【4.2】使用的时候会自动分布
set 和 get 都会跳到对应的实例上去。
#【4.3】核验检查
(1)redis-trib.rb check 192.168.135.173:7001 #(任意节点的IP:端口 即可)
(2)任意节点 redis-cli -c 登录上去之后,使用 CLUSTER 命令(按tab 可以自动补全)
redis -c -h 192.168.135.173 -p 7001
(2.1)CLUSTER NODES
(2.2)CLUSTER INFO
【5】添加删除集群节点
注意,千万不要cluster增删节点命令与 redis-trib.rb 增删节点混用!!!
【5.0】新增节点规划与操作
cluster 相关命令参考:https://www.cnblogs.com/kevingrace/p/7910692.html
192.168.135.174:7007 192.168.135.175:7008
192.168.135.174: cd /data/redis mkdir -p 7007{conf,log} cp 7002conf/7002redis.conf 7007conf/7007redis.conf #修改配置文件中的7002为7007即可
192.168.135.175: cd /data/redis mkdir -p 7008{conf,log} cp 7003conf/7003redis.conf 7008conf/7008redis.conf #修改配置文件中的7003为7008即可
【5.1】cluster meet 命令增删节点
【5.1.1】Cluster meet 增加节点(不建议使用这种办法,建议使用【5.2】)
#在任意节点登录都可以,我这里用 173:7001 节点登录了
redis-cli -c -h 192.168.135.173 -p 7001
#添加节点命令(用这个命令添加进来默认是没有分配槽位的,会在需要的时候自动把其他MSTER的槽位转移过来用的)
cluster meet 192.168.135.174 7007
cluster meet 192.168.135.175 7008
#效果如下图,默认是以主节点的身份添加进来的
#把其中一个设置为从,这里设置192.168.135.175:7008为7007的从
A:比如要登录7008
redis-cli -p 7008 -h 192.168.135.175 -c
B: 在A的登录环境下, cluster replicate 7007node_id
cluster replicate d80a9c494633a6d84697ac5330dfb024e4a0866d
#这是在没进行任何操作的情况,如果已经进行了set相关
Node 192.168.135.173:7001 is not empty
查看了一下,原来是7008因为我之前set了一下,自动给它分配了一个槽位,所以如上图操作,我把该槽位释放掉就可以执行让其变成从库了!
但如上图所示,并没有自动分配槽位给新增的主节点,而是等到使用的时候才会按需分配,且我们的13026槽位也并没有分配给某个具体master节点.所以,检查报错如下:
出现新的错误:[ERR] Not all 16384 slots are covered by nodes
修复:redis-trib.rb fix 192.168.135.175:7008 即,把这个槽从新分配一下给master
【5.1.2】cluster forget 命令移除节点
#登录
redis-cli -p 7001 -h 192.168.135.173 -c
#(1)移除节点命令(移除7007
CLUSTER FORGET d80a9c494633a6d84697ac5330dfb024e4a0866d
#(2)发现错误
(error)ERR Can't forget my master!
(error)ERR I tried hard but I can't forget myself...
#意思就是,从节点不能移除 master 节点,且如果登录的是主节点要移除的是自己也不行
#(3)解决办法
切换到另外一个主节点即可。
例如,删除 7007和7008
cluster forget d80a9c494633a6d84697ac5330dfb024e4a0866d
cluster forget c70173985021665bacd74231f03c2a001468e703
#(4)核验
cluster nodes
#(5)保存当前配置
cluster saveconfig
【5.2】redis-trib.rb 增删节点
参考:redis使用总结(二)
【5.2.1】redis-trib.rb 增加扩张节点
#(1)新增主节点,7001是原本存在的主节点(这里可以是集群中的任意节点),7007是新主节点
redis-trib.rb add-node 192.168.135.174:7007 192.168.135.173:7001
#命令的意思是,添加主节点 192.168.135.174:7001 到 192.168.135.17:7001所在集群
#报错,因为我们之前使用过它加入进群
[ERR] Node 192.168.135.174:7007 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
#解决
在192.168.135.174机器上
redis-cli -p 7007 -h 192.168.135.174 shutdown
rm -rf /data/redis/7007conf/{appendonly.aof,redis.rdb,redis.pid,nodes-7007.conf}
redis-server /data/redis/7007conf/7007redis.conf
再次执行命令,执行成功,如下图:
#(2)登录集群任意节点,获取 id标识
redis-cli -h 192.168.135.173 -c -p 7001 cluster nodes
#(3)添加从节点,7001是原本存在的主节点(这里可以写集群中的任意节点信息),7008是新增为7007从库的新节点
redis-trib.rb add-node --slave --master-id c70173985021665bacd74231f03c2a001468e703 192.168.135.175:7008 192.168.135.173:7001
#命令的意思,添加从节点,然后其主节点ID为...(通过cluster nodes获取 7007的id),从节点IP:端口, 加入 192.168.135.173:7001 所在的集群
#(4)为主节点重新分配solt
redis-trib.rb reshard 192.168.135.174:7007
#重新分配,会弹出如下对话框,输入4000,即设置该节点slot数为4000
How many slots do you wan to move(from 1 to 16384)? 4000
What is the receiving node ID? #输入7007的 id
Source node #1:all #从哪里分配?all则标识全部节点重新洗牌分配(新环境可以,但旧环境会导致停机的),也可以写具体的node_id
#自动平衡槽数量
redis-trib.rb rebalance 192.168.135.174:7007
【5.2.2】redis-trib.rb 缩减节点
#(1)流程说明 A:确定要下线移除的节点是否存在slot,如果有,需要先把slot迁移到其他节点,保证整个集群槽节点映射的完整性;
B:当下线的节点没有槽或本身是从节点时,就可以通知集群内其他节点(或者叫忘记节点),当下线的节点被集群忘记后正常关闭。
#(2)登录任意集群节点查看 node_id
redis-cli -c -h 192.168.135.173 -p 7001 cluster nodes
#(3)删除节点 #分为两种,一种是删除主节点 192.168.135.174:7007,另一种是删除从节点 192.168.135.175:7008
#删除从节点7008(因为没有分配哈希槽,可以直接删除)
redis-trib.rb del-node 192.168.135.175:7008 c70173985021665bacd74231f03c2a001468e703
#redis-trib.rb del-node ip:port node_id
#删除主节点7007(分配了hash槽,需要把hash槽转移到别的节点去,才能够删除)
直接删除肯定会报错的:
#(4)缩减槽位
redis-trib.rb reshard 192.168.135.174:7007 #后面这个IP及端口,其实是集群内任意节点都可以,主要是为了让命令识别是哪个集群,任意节点都可以让其识别出整个集群信息
#redis-trib.rb reshard --from e37957bd67cc4932183c6549ee7368cbc93b7499 --to ba694e2969adb6c06a1f7dc596168ccc57ee9e1d --slots 1500 --yes 192.168.135.173:7001
看上图中,下班部分的框线,意思是
(1)想要移走多少个slot?
(2)谁接受这些slot,这里我写的node_id 是7001的
(3)这些移动的槽来源在哪里,写我们的7007对应的node_id即可
#移走之后,可以删掉7007节点了
redis-trib.rb del-node 192.168.135.174:7007 99a603ef36215bfadf382dadb62f9bfe59711b41
#知道了上面reshard意思,我们可以直接用命令写完这些,不需要交互方式写。
redis-trib.rb reshard --from e37957bd67cc4932183c6549ee7368cbc93b7499 --to ba694e2969adb6c06a1f7dc596168ccc57ee9e1d --slots 1500 --yes 192.168.135.173:7001
#把7001对应的node_id 移动1500个槽给 7004
【6】redis cluster的故障转移
redis集群实现了,高可用,当集群内少量节点出现故障时,通过故障转移可以保证集群正常对外服务。
当集群里某个节点出现了问题,redis集群内的节点通过Ping Pong消息发现节点是否健康,是否有故障。
故障恢复:
如果下线节点是主节点,则需要在它的从节点中选一个替换它,保证集群的高可用,转移过程如下:
(1)资格检查(必须要主节点才有资格投票)
(2)准备选举时间
(3)发起投票
(4)选举投票,从库>50%
【6.1】查看当前集群状况,构造测试数据
redis-cli -c -p 7001 -h 192.168.135.173
好,如上图,现在三个主库上都有了。
模拟:现在重启 192.168.135.175 机器,包含7003和7006 2个节点
如上图,之前t5是在7006的,现在get t5切换到了7002 证明已经自动故障转移了
重启 192.168.135.175 7003和7006 节点之后,我们可以看到主从又自动分配了,但原本的主从关系已经随着故障转移彻底改变了。
【7】集群性能测试方法
这个命令在/data/redis/bin/redis-benchmark ,是redis自带的。
用法及参数如下:
redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests>] [-k <boolean>] -h <hostname> Server hostname (default 127.0.0.1) -p <port> Server port (default 6379) -s <socket> Server socket (overrides host and port) -a <password> Password for Redis Auth -c <clients> Number of parallel connections (default 50) -n <requests> Total number of requests (default 100000) -d <size> Data size of SET/GET value in bytes (default 3) --dbnum <db> SELECT the specified db number (default 0) -k <boolean> 1=keep alive 0=reconnect (default 1) -r <keyspacelen> Use random keys for SET/GET/INCR, random values for SADD Using this option the benchmark will expand the string __rand_int__ inside an argument with a 12 digits number in the specified range from 0 to keyspacelen-1. The substitution changes every time a command is executed. Default tests use this to hit random keys in the specified range. -P <numreq> Pipeline <numreq> requests. Default 1 (no pipeline). -e If server replies with errors, show them on stdout. (no more than 1 error per second is displayed) -q Quiet. Just show query/sec values --csv Output in CSV format -l Loop. Run the tests forever -t <tests> Only run the comma separated list of tests. The test names are the same as the ones produced as output. -I Idle mode. Just open N idle connections and wait. Examples: Run the benchmark with the default configuration against 127.0.0.1:6379: $ redis-benchmark Use 20 parallel clients, for a total of 100k requests, against 192.168.1.1: $ redis-benchmark -h 192.168.1.1 -p 6379 -n 100000 -c 20 Fill 127.0.0.1:6379 with about 1 million keys only using the SET test: $ redis-benchmark -t set -n 1000000 -r 100000000 Benchmark 127.0.0.1:6379 for a few commands producing CSV output: $ redis-benchmark -t ping,set,get -n 100000 --csv Benchmark a specific command line: $ redis-benchmark -r 10000 -n 10000 eval 'return redis.call("ping")' 0 Fill a list with 10000 random elements: $ redis-benchmark -r 10000 -n 10000 lpush mylist __rand_int__ On user specified command lines __rand_int__ is replaced with a random integer with a range of values selected by the -r option.
案例语句:
#(1)常规通用
-c 客户端,-r 请求多少个随机key ,-n 总请求量 ,-t 操作 ,-P 通道、线程 time /data/redis/bin/redis-benchmark -h 192.168.135.173 -p 7001 -c 200 -r 1000000 -n 2000000 -t get,set,lpush,lpop -P 16 -q
#(2)100个并发连接,100000个请求,检测host为192.168.135.173,port为6379的redis服务器性能
redis-benchmark -h 192.168.135.173 -p 7001 -c 100 -n 100000
#(3)测试存取大小为100字节的数据包的性能
redis-benchmark -h 192.168.135.173 -p 7001 -q -d 100
#(4)测试某些redis操作的性能
redis-benchmark -t set,lpush -n 100000 -q
#(5)只测试某些值存取的性能
redis-benchmark -n 100000 -q script load "redis.call('set','key1','value1')"
【8】redis5.0.x版本集群安装
所有的步骤思路,和4.0.11并无不同,只是命令语法改了一点而已
【8.1】创建集群并自动分配槽
redis-cli --cluster create 192.168.80.131:7001 192.168.80.131:7002 192.168.80.131:7003 192.168.80.131:7004 192.168.80.131:7005 192.168.80.131:7006 --cluster-replicas 1
【8.2】对集群槽位重新分片
redis-cli --cluster reshard 192.168.135.173:7001
How many slots do you want to move(from 1 to 16384)? 需要移动分配的槽位数量
What is the receiving node ID 指定接收这些槽位数的 节点ID
Source node #1: all/ID 重新分片的源节点(source node)
Do you want to proceed with the proposed reshard plan (yes/no)? yes 确认
【8.3】检查集群是否正常
redis-cli --cluster check 192.168.135.173:7001
【8.4】添加节点
redis-cli --cluster add-node 192.168.135.174:7007 192.168.135.173:7001
#命令中的 add-node 表示我们要 将一个节点添加到集群里面, add-node 之后跟着的是新节点的 IP 地址和端口号, 再之后跟着的是集群中任意一个已存在节点的 IP 地址和端口号
和其他主节点相比, 新节点还有两点区别:
新节点没有包含任何数据, 因为它没有包含任何哈希桶。
尽管新节点没有包含任何哈希嘈, 但它仍然是一个主节点, 所以在集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中。
(1)添加节点后,让节点成为主节点
#可以使用如下命令来分配槽位使其成为真正的主节点。
redis-cli --cluster reshard 192.168.135.174:7007 (这个IP+端口,可以是集群内任意节点信息)
(2)添加节点后,让节点变成从节点
#实现使用 cluster nodes 查看好对应的主节点 node_id =》登录上从节点:redis-cli -h 192.168.135.174 -p 7007 =》 设置该节点为指定主节点node_id的从库:命令如下
redis 192.168.135.174:7007> cluster replicate 主节点ID
【8.5】删除节点
#删除从节点
redis-cli --cluster del-node 192.168.135.174:7007 10363eb...
#删除主节点
#如果主节点有从节点,将从节点转移到其他主节点
#如果主节点有slot,去掉分配的slot,然后在删除主节点
redis-cli --cluster del-node 192.168.135.174:7007 108929...
[ERR] Node 127.0.0.1:7003 is not empty! Reshard data away and try again.
[ERR] 哈希槽非空
#重新分片去掉所有哈希槽
redis-cli --cluster reshard 192.168.135.174:7007
#重新分片后从节点也自动转移到其他主节点了
redis-cli --cluster del-node 192.168.135.174:7007 10363eb...
参考文献:
https://www.cnblogs.com/PatrickLiu/p/8458788.html