分布式缓存Redis之cluster集群

写在前面

  本学习教程所有示例代码见GitHub:https://github.com/selfconzrr/Redis_Learning

  官方文档:
  集群教程:http://www.redis.cn/topics/cluster-tutorial.html
  集群规范:http://www.redis.cn/topics/cluster-spec.html

  这里写图片描述

  jedis客户端操作redis主要三种模式:单台模式、分片模式(ShardedJedis)、集群模式(BinaryJedisCluster),分片模式是一种轻量级集群。

  单台模式、分片模式(ShardedJedis)前面已经讲述过。这篇文章主要来看集群模式。

  现在项目上用redis的话,很少说不用集群的情况,毕竟如果生产上只有一台redis会有极大的风险,比如机器挂掉,或者内存爆掉,都会导致数据丢失。从Redis3.0,Jedis2.9版本开始有了cluster的概念。

一、Redis集群介绍

Redis 集群的特点

1)是一个提供在多个Redis间节点间共享数据的程序集;
2)并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误。
3)通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令。
4)Redis 集群是 Redis 的一个分布式实现;
5)所有的redis节点彼此互联**(PING-PONG机制),内部使用二进制协议优化传输速度和带宽;
6)节点的fail是通过
集群中超过半数的节点检测失效时**才生效;
7)客户端与redis节点直连,不需要中间proxy代理层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
8)Redis 集群是3.0之后才引入的,在3.0之前,使用哨兵(sentinel)机制(前面的文章已经介绍过)来监控各个节点之间的状态。

Redis 集群的优势

  • 自动分割数据到不同的节点上。
  • 整个集群的部分节点失败或者不可达的情况下能够继续处理命令。

Redis 集群的数据分片

  Redis 集群没有使用一致性hash,而是引入了哈希槽的概念。Redis 集群有16384个哈希槽(slot),当需要在 Redis 集群中放置一个 key-value 时,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

  比如当前集群有3个节点,那么:

  • 节点 A 包含 0 到 5500号哈希槽
  • 节点 B 包含5501 到 11000 号哈希槽
  • 节点 C 包含11001 到 16383号哈希槽

  这种结构很容易添加或者删除节点。比如如果我想新添加个节点D, 我需要从节点 A, B, C中分部分槽到D上。如果我想移除节点A,需要将A中得槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可。

  由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。

Redis只会为主节点分配哈希槽

  集群分区,最主要的目的是在移除、添加一个节点时对已经存在的缓存数据的定位影响尽可能的降到最小。

  和memcached一样,Redis也采用一定的算法进行键-槽(key->slot)之间的映射。memcached采用一致性哈希(consistency hashing)算法进行键-节点(key-node)之间的映射,而redis集群使用集群公式来计算键 key 属于哪个槽:

HASH_SLOT(key)= CRC16(key) % 16384

Redis 集群的主从复制模型

  为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品。

  在我们的例子中具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用。

  然而如果在集群创建的时候(或者过一段时间),我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了。不过当B和B1 都失败后,集群是不可用的。

什么时候整个集群不可用(cluster_state:fail)?

  • 如果集群任意master挂掉,且当前master没有slave,集群进入fail状态。也可以理解成集群的slot映射[0-16383]不完成时进入fail状态;
  • 如果集群超过半数以上master挂掉,无论是否有slave集群进入fail状态

  **ps:**当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误。

二、搭建并使用Redis集群

这两篇介绍的非常详细。
https://www.cnblogs.com/hjwublog/p/5681700.html
http://blog.csdn.net/boonya/article/details/49362819

  只在这总结一下经常遇到的问题:主要是随着年代的更新,版本的更新,很多源/库,现在都没了。

1、redis-trib.rb命令提示not command,即不能执行集群安装命令:

  redis-trib.rb是redis官方推出的管理redis集群的工具,集成在redis的源码src目录下。因为redis-trib.rb是用ruby语言编写,系统没有安装ruby环境。

  **解决办法:**Ubuntu下安装ruby命令:

sudo apt-get install ruby

2、再进一步,提示出错:cannot load such file --redis

  这是因为需要安装驱动,在安装驱动之前,需要替换资源库,否则资源请求地址会报错,不知道从什么时候开始,使用淘宝的gemsruby资源库(https://ruby.taobao.org/),会提示Error fetching https://ruby.taobao.org/

  发现原来是taobao Gems 源已停止维护,现由 ruby-china 提供镜像服务,即我们要换源:http://gems.ruby-china.org/

  补充此处的几条命令:

1、删除默认的官方源:
gem sources -r https://rubygems.org/

2、(以前的) 添加淘宝源:
gem sources -a https://ruby.taobao.org/

3、(现在应该添加的)注意:这里是http而不是https
gem sources -a http://gems.ruby-china.org/

4、查看当前源:
gem sources -l

3、redis-trib.rb具有以下功能:

  ● create :创建集群
  ● check :检查集群
  ● info :查看集群信息
  ● fix :修复集群
  ● reshard :在线迁移slot
  ● rebalance :平衡集群节点slot数量
  ● add-node :将新节点加入集群
  ● del-node :从集群中删除节点
  ● set-timeout :设置集群节点间心跳连接的超时时间
  ● call :在集群全部节点上执行命令
  ● import :将外部redis数据导入集群
  ● redis-trib.rb主要有两个类: ClusterNode 和 RedisTrib 。 ClusterNode保存了节点本身以及处于集群中的所有节点的状态, RedisTrib 则是redis-trib.rb各个功能的实现。

  比如:

向集群中添加节点,7037是新增节点,7036是集群中已有的节点
./redis-trib.rb add-node 192.168.2.128:7037 192.168.2.128:7036
重新分配槽
./redis-trib.rb reshard 192.168.2.128:7031
指定当前节点的主节点
cluster replicate cf48228259def4e51e7e74448e05b7a6c8f5713f
删除节点
./redis-trib.rb del-node 192.168.2.128:7037 'a56461a171334560f16652408c2a45e629d268f6'

4、在安装redis-cluster过程中可以节省时间的操作集合

1)如何快速启动六个(或更多)服务器?

方法一:依次进入每个节点目录(时间都浪费在切换目录上了),执行 ./redis-server redis.conf.

方法二:写个shell脚本,vim startall.sh就会打开vim编辑器,创建一个空的文本:
即将方法一在命令行操作的指令集合到文本里。以一个节点为例:

cd redis01
./redis-server redis.conf
cd ..
cd redis02
blurblur....

  执行./startall.sh 提示permission denied说明权限不足,执行命令chmod 777 startall.sh修改权限即可。

方法三:用脚本循环启动,这样更方便省时

for((i=1;i<=6;i++)); do /usr/local/redis/bin/redis-server /usr/local/redis-cluster/703$i/redis.conf; done

三、redis cluster命令

集群(cluster)
cluster info 打印集群的信息
cluster nodes 列出集群当前已知的所有节点(node),以及这些节点的相关信息节点
cluster meet 将ip和port所指定的节点添加到集群当中,让它成为集群的一份子

cluster forget <node_id> 从集群中移除node_id指定的节点
cluster replicate <node_id> 将当前节点设置为node_id指定的节点的从节点
cluster saveconfig 将节点的配置文件保存到硬盘里面

cluster slaves <node_id> 列出该slave节点的master节点
cluster set-config-epoch 强制设置configEpoch槽(slot)

cluster addslots [slot …] 将一个或多个槽(slot)指派(assign)给当前节点
cluster delslots [slot …] 移除一个或多个槽对当前节点的指派
cluster flushslots 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点

cluster setslot node <node_id> 将槽slot指派给node_id指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽,然后再进行指派
cluster setslot migrating <node_id> 将本节点的槽slot迁移到node_id指定的节点中
cluster setslot importing <node_id> 从node_id 指定的节点中导入槽slot到本节点

cluster setslot stable 取消对槽slot的导入(import)或者迁移(migrate) 键
cluster keyslot 计算键key应该被放置在哪个槽上
cluster countkeysinslot 返回槽slot目前包含的键值对数量
cluster getkeysinslot 返回count个slot槽中的键

其它
cluster myid 返回节点的ID
cluster slots 返回节点负责的slot
cluster reset 重置集群,慎用

四、Redis集群方案

最早的Redis Sharding分片方案,然后Sentinel哨兵方案,前面介绍的是官方推出的Redis-cluster方案。

基于代理的分片方案:

------至所有正在努力奋斗的程序猿们!加油!!
有码走遍天下 无码寸步难行
1024 - 梦想,永不止步!
爱编程 不爱Bug
爱加班 不爱黑眼圈
固执 但不偏执
疯狂 但不疯癫
生活里的菜鸟
工作中的大神
身怀宝藏,一心憧憬星辰大海
追求极致,目标始于高山之巅
一群怀揣好奇,梦想改变世界的孩子
一群追日逐浪,正在改变世界的极客
你们用最美的语言,诠释着科技的力量
你们用极速的创新,引领着时代的变迁

——乐于分享,共同进步,欢迎补充
——Any comments greatly appreciated
——诚心欢迎各位交流讨论!QQ:1138517609
——CSDN:https://blog.csdn.net/u011489043
——简书:https://www.jianshu.com/u/4968682d58d1
——GitHub:https://github.com/selfconzrr

发布了73 篇原创文章 · 获赞 224 · 访问量 32万+

猜你喜欢

转载自blog.csdn.net/u011489043/article/details/78864147