设为首页 收藏本站
查看: 1868|回复: 0

[经验分享] redis集群的搭建

[复制链接]

尚未签到

发表于 2018-11-2 09:56:12 | 显示全部楼层 |阅读模式
redis集群的搭建
  本文使用的是3台主机,每台主机2个节点,3台maser,3台salve的环境。
1. 环境介绍:

  3台CentOS>  192.168.1.35  
  192.168.1.36
  
  192.168.1.37
  redis-4.0.9.tar.gz
  ruby-2.4.4.tar.gz
2. 软件安装
安装redis:
  本文中的环境默认是不能连接外网的。所以软件包只能通过跳板机或者其他的机器通过scp上传。
  编译安装:
tar -xf redis-4.0.9.tar.gz  
mkdir -p /usr/local/redis
  
mv redis-4.0.9/* /usr/local/redis/
  
cd /usr/local/redis/
  
make && make install
  创建redis节点:
mkdir -p redis_cluster/{7000,7001}  
cp redis.conf redis_cluster/7000
  
cp redis.conf resis_cluster/7001
  分别修改7000/7001里面的配置文件的内容:
port 7000           //端口7000,7001  
bind  192.168.1.35  //改为35,36,37
  
daemonize yes     //redis后台运行
  
pidfile /var/run/redis_7000.pid     //pid对应7000,7001
  
cluster-enabled yes   //开启集群
  
cluster-config-file  nodes_7000.conf   //指定集群的配置文件,自动生成
  
cluster-node-timeout 15000  //设置集群超时时间
  
appendonly  yes        //aof日志开启,它会每次写操作都记录一条日志
  在另外的两台机器上重复上面的配置规则
  启动各个节点(另外两台也是同样地):
  redis-server redis_cluster/7000/redis.conf
  redis-server redis_cluster/7001/redis.conf
查看各个节点是否起来:  
$ ss -tnlp|grep redis
  
LISTEN 0 511 192.168.1.35:17000 *:* users:(("redis-server",24909,9))
  
LISTEN 0 511 192.168.1.35:17001 *:* users:(("redis-server",24914,9))
  
LISTEN 0 511 192.168.1.35:7000 *:* users:(("redis-server",24909,6))
  
LISTEN 0 511 192.168.1.35:7001 *:* users:(("redis-server",24914,6))
安装ruby:
tar -xf  ruby-2.4.4.tar.gz  
cd ruby-2.4.4
  
./configure --prefix=/usr/local/ruby
  
make && make install
  
/usr/local/ruby/bin/gem install redis
  或者
安装gem和redis的插件(https://rubygems.global.ssl.fastly.net/gems/redis-3.2.2.gem)  
# gem install -l redis-3.2.2.gem
3. 集群创建
  redis-trib.rb是redis官方推出的redis集群管理的工具,这个工具在redis的src目录下。
  /usr/local/ruby/bin/ruby /usr/local/redis/src/redis-trib.rb create --replicas 1 192.168.1.35:7000 192.168.1.35:7001 192.168.1.36:7000 192.168.1.36:70001 192.168.1.37:7000 192.168.1.37:7001
--replicas:指定每个主节点有几个从节点  
注意:需要有3个或者以上的主节点,否则在创建集群是会失败,并且存活的主节点数小于总节点数的一半时,整个集群就无法提供服务了。
  
原理:redis cluster在设计的时候,就考虑到了去中心化去中间件,就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。  Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)的方式来分配的。redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。所以我们在测试的时候看到set 和 get 的时候,直接跳转到了7000端口的节点。  Redis 集群会把数据存在一个 master 节点,然后在这个 master 和其对应的salve 之间进行数据同步。当读取数据时,也根据一致性哈希算法到对应的 master 节点获取数据。只有当一个master 挂掉之后,才会启动一个对应的 salve 节点,充当 master 。
4.集群验证:
  可以通过随便在一台机器上创建数据来验证整个集群。
通过redis-cli命令来登陆  
$ redis-cli -h 192.168.1.35 -c -p 7000
  
192.168.1.37:7000> set hello world
  
-> Redirected to slot [866] located at 192.168.1.35:7000
  
OK
  
192.168.1.35:7000> keys *
  
1) "hello"
  然后登陆另外一台的7000端口,查看key的内容。
$ redis-cli -h 192.168.1.36 -c -p 7000  
192.168.1..36:7000> get hello
  
-> Redirected to slot [866] located at 192.168.1.35:7000
  
"world"
  
192.168.1.35:7000>
  如果其他节点可以读取得到就说明集群运行正常。
5.redis集群管理工具redis-trib.rb
  redis-trib.rb是redis官方推出的管理redis集群的工具,集成在redis的源码src目录下,是基于redis提供的集群命令封装成简单、便捷、实用的操作工具。
  redis-trib.rb的功能参数:
Usage: redis-trib     
  create host1:port1 ... hostN:portN
  
              --replicas
  
  check host:port
  
  info host:port
  
  fix host:port
  
                  --timeout
  
  reshard host:port
  
                  --from
  
                  --to
  
                  --slots
  
                  --yes
  
                  --timeout
  
                  --pipeline
  
  rebalance host:port
  
                  --weight
  
                  --auto-weights
  
                  --use-empty-masters
  
                  --timeout
  
                  --simulate
  
                  --pipeline
  
                  --threshold
  
  add-node new_host:new_port existing_host:existing_port
  
                  --slave
  
                  --master-id
  
  del-node host:port node_id
  
  set-timeout host:port milliseconds
  
  call host:port command arg arg .. arg
  
  import host:port
  
                  --from
  
                  --copy
  
                  --replace
  
  help (show this help)
  
    For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node     in   the cluster.
  简单来看:redis-trib.rb提供了以下的功能:
create创建集群check检查集群info查看集群信息fix修复集群reshard在线迁移集群rebalance平衡集群节点的slot数量add-node将节点加入新的集群del-node从集群中删除节点set-timout设置集群节点间的心跳连接超时时间call在集群全部节点上执行命令import将外部的redis数据导入集群create创建集群:
  可选参数为replicas,表示需要几个slave。
  简单用法:
ruby redis-trib.rb create 192.168.1.20:7000 192.168.1.21:7000 192.168.1.22:7000  有一个从节点的创建命令:
ruby redis-trib.rb create  --replicas 1 192.168.1.20:7000 192.168.1.21:7000 192.168.1.22:7000 192.168.1.23:7000 192.168.1.24:7000 192.168.1.25:7000  创建流程如下:
  1、首先为每个节点创建ClusterNode对象,包括连接每个节点。检查每个节点是否为独立且db为空的节点。执行load_info方法导入节点信息。
  2、检查传入的master节点数量是否大于等于3个。只有大于3个节点才能组成集群。
  3、计算每个master需要分配的slot数量,以及给master分配slave。分配的算法大致如下: 先把节点按照host分类,这样保证master节点能分配到更多的主机中。 不停遍历遍历host列表,从每个host列表中弹出一个节点,放入interleaved数组。直到所有的节点都弹出为止。 master节点列表就是interleaved前面的master数量的节点列表。保存在masters数组。 计算每个master节点负责的slot数量,保存在slots_per_node对象,用slot总数除以master数量取整即可。 遍历masters数组,每个master分配slots_per_node个slot,最后一个master,分配到16384个slot为止。 接下来为master分配slave,分配算法会尽量保证master和slave节点不在同一台主机上。对于分配完指定slave数量的节点,还有多余的节点,也会为这些节点寻找master。分配算法会遍历两次masters数组。 第一次遍历masters数组,在余下的节点列表找到replicas数量个slave。每个slave为第一个和master节点host不一样的节点,如果没有不一样的节点,则直接取出余下列表的第一个节点。 第二次遍历是在对于节点数除以replicas不为整数,则会多余一部分节点。遍历的方式跟第一次一样,只是第一次会一次性给master分配replicas数量个slave,而第二次遍历只分配一个,直到余下的节点被全部分配出去。
  4、打印出分配信息,并提示用户输入“yes”确认是否按照打印出来的分配方式创建集群。
  5、输入“yes”后,会执行flush_nodes_config操作,该操作执行前面的分配结果,给master分配slot,让slave复制master,对于还没有握手(cluster meet)的节点,slave复制操作无法完成,不过没关系,flush_nodes_config操作出现异常会很快返回,后续握手后会再次执行flush_nodes_config。
  6、给每个节点分配epoch,遍历节点,每个节点分配的epoch比之前节点大1。
  7、节点间开始相互握手,握手的方式为节点列表的其他节点跟第一个节点握手。
  8、然后每隔1秒检查一次各个节点是否已经消息同步完成,使用ClusterNode的get_config_signature方法,检查的算法为获取每个节点cluster nodes信息,排序每个节点,组装成node_id1:slots|node_id2:slot2|...的字符串。如果每个节点获得字符串都相同,即认为握手成功。
  9、此后会再执行一次flush_nodes_config,这次主要是为了完成slave复制操作。
  10、最后再执行check_cluster,全面检查一次集群状态。包括和前面握手时检查一样的方式再检查一遍。确认没有迁移的节点。确认所有的slot都被分配出去了。
  11、至此完成了整个创建流程,返回[OK]
check检查集群
  使用check来检查集群的状态。只需要选择其中的一个节点即可:
$ /usr/local/ruby/bin/ruby /usr/local/redis/src/redis-trib.rb check 192.168.1.36:7000  
>>> Performing Cluster Check (using node 192.168.1.36:7000)
  
M: 631e3b56a0895f5ac62b15ad7467752877d8079e 1192.168.1.36:7000
  
   slots:5461-10922 (5462 slots) master
  
   1 additional replica(s)
  
M: d35e7bd3a31054b96dfe2d08d7472731753d6ceb 192.168.1.37:7000
  
   slots:10923-16383 (5461 slots) master
  
   1 additional replica(s)
  
M: 06fbb8062252b78093d4ef50188199a580bb86bd 192.168.1.35:7000
  
   slots:0-5460 (5461 slots) master
  
   1 additional replica(s)
  
S: 4e26eac416d32421800f91f78a9df070aa7d0855 192.168.1.35:7001
  
   slots: (0 slots) slave
  
   replicates d35e7bd3a31054b96dfe2d08d7472731753d6ceb
  
S: 8090354b1b3575ae1e331841964c6c33c55897da 192.168.1.37:7001
  
   slots: (0 slots) slave
  
   replicates 631e3b56a0895f5ac62b15ad7467752877d8079e
  
S: 0909bb82f88e0755bab3bc06f1cc3b4325c2a869 192.168.1.36:7001
  
   slots: (0 slots) slave
  
   replicates 06fbb8062252b78093d4ef50188199a580bb86bd
  
[OK] All nodes agree about slots configuration.
  
>>> Check for open slots...
  
>>> Check slots coverage...
  
[OK] All 16384 slots covered.
info查看集群的信息
  info命令用来查看集群的信息,同样只需要指定一个节点即可:
/usr/local/ruby/bin/ruby /usr/local/redis/src/redis-trib.rb info 192.168.1.36:7000  
192.168.1.36:7000 (631e3b56...) -> 1 keys | 5462 slots | 1 slaves.
  
192.168.1.37:7000 (d35e7bd3...) -> 0 keys | 5461 slots | 1 slaves.
  
192.168.1.35:7000 (06fbb806...) -> 1 keys | 5461 slots | 1 slaves.
  
[OK] 2 keys in 3 masters.
  
0.00 keys per slot on average.
fix修复集群:
  fix命令的流程跟check的流程很像,显示加载集群信息,然后在check_cluster方法内传入fix为 true的变量,会在集群检查出现异常的时候执行修复流程。目前fix命令能修复两种异常,一种是集群有处于迁移中的slot的节点,一种是slot未完全分配的异常。
  fix_open_slot方法是修复集群有处于迁移中的slot的节点异常:
  1、先检查该slot是谁负责的,迁移的源节点如果没完成迁移,owner还是该节点。没有owner的slot无法完成修复功能。
  2、遍历每个节点,获取哪些节点标记该slot为migrating状态,哪些节点标记该slot为importing状态。对于owner不是该节点,但是通过cluster countkeysinslot获取到该节点有数据的情况,也认为该节点为importing状态。
  3、如果migrating和importing状态的节点均只有1个,这可能是迁移过程中redis-trib.rb被中断所致,直接执行move_slot继续完成迁移任务即可。传递dots和fix为true。
  4、如果migrating为空,importing状态的节点大于0,那么这种情况执行回滚流程,将importing状态的节点数据通过move_slot方法导给slot的owner节点,传递dots、fix和cold为true。接着对importing的节点执行cluster stable命令恢复稳定。
  5、如果importing状态的节点为空,有一个migrating状态的节点,而且该节点在当前slot没有数据,那么可以直接把这个slot设为stable。
  6、如果migrating和importing状态不是上述情况,目前redis-trib.rb工具无法修复,上述的三种情况也已经覆盖了通过redis-trib.rb工具迁移出现异常的各个方面,人为的异常情形太多,很难考虑完全。 fix_slots_coverage方法能修复slot未完全分配的异常:
  未分配的slot有三种状态:
  1、所有节点的该slot都没有数据。该状态redis-trib.rb工具直接采用随机分配的方式,并没有考虑节点的均衡。本人尝试对没有分配slot的集群通过fix修复集群,结果slot还是能比较平均的分配,但是没有了连续性,打印的slot信息非常离散。
  2、有一个节点的该slot有数据。该状态下,直接把slot分配给该slot有数据的节点。
  3、有多个节点的该slot有数据。此种情况目前还处于TODO状态,不过redis作者列出了修复的步骤,对这些节点,除第一个节点,执行cluster migrating命令,然后把这些节点的数据迁移到第一个节点上。清除migrating状态,然后把slot分配给第一个节点。
reshard在线迁移slot:
  reshard命令可以在线把集群的一些slot从集群原来slot负责节点迁移到新的节点,利用reshard可以完成集群的在线横向扩容和缩容。
  reshard的参数介绍:
reshard        host:port   指定从哪个节点获取集群的信息  
                     --from        需要从哪些节点上迁移slot。--from all 所有节点
  
                     --to        slot需要迁移的目的节点node id
  
                     --slots    需要迁移的slot数量
  
                     --yes    设置该参数,会提示输入yes后再执行reshard
  
                     --timeout  设置migrate命令的超时时间
  
                     --pipeline    定义cluster getkeysinslot一次取出的key数量,默认为10
  参考文献
  redis集群教程
  redis集群规范
  https://redis.io/topics/cluster-spec
  https://redis.io/topics/cluster-tutorial



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-629685-1-1.html 上篇帖子: Redis命令操作详解 下篇帖子: python和redis之间的交互
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表