Redis 集群

一、Redis-Cluster 简介


【1】Redis 集群(Redis-Cluster)提供了在多个 Redis 节点间共享数据的功能。
【2】Redis 集群通过分区来提高可用性。可自动分割数据到不同的节点上,集群的部分节点失败或者不可达时能够继续处理请求。
【3】Redis Cluster 集群模式通常具有高可用性、可扩展性、分布式等特性。
【4】Redis 集群采用 P2P 模式,是完全去中心化的,不存在中心节点或者代理节点
【5】Redis 集群是没有统一的入口,客户端连接集群的任意节点(node)即可,集群内部的节点是相互通信的(PING-PONG机制),每个节点都是一个 Redis 实例。
【6】为了实现集群的高可用,即判断节点是否健康[能否正常使用],redis-cluster有这么一个投票容错机制如果集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法。如果集群中任意一个节点挂了,而且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法。
【7】那么为什么任意一个节点挂了(没有从节点)这个集群就挂了呢?  因为集群内置了16384个slot(哈希槽),并且把所有的物理节点映射到了这16384[0-16383]个slot上,或者说把这些 slot均等的分配给了各个节点。当需要在 Redis集群存放一个数据(key-value)时,redis会先对这个key进行 CRC16 算法,然后得到一个结果。再把这个结果对 16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定 key-value存储到哪个节点中。所以一旦某个节点挂了,该节点对应的 slot 就无法使用,那么就会导致集群无法正常工作。综上所述,每个 Redis集群理论上最多可以有16384个节点。

二、Redis-Cluster 查询路由方案


■  客户端随机地请求任意一个 Redis实例,然后由 Redis将请求转发给正确的 Redis节点。
■  Redis-Cluster 实现了一种混合形式的查询路由,但不是直接将请求从一个 Redis 节点转发到另一个 Redis 节点,而是在客户端帮助下直接重定向(redirected)到正确的 Redis 节点。如果访问的第一个节点就是目标节点,则直接返回结果。

三、Redis-Cluster 数据分片


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

解耦数据和节点之间的关系,简化了节点扩容和收缩难度
■ 节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据。
■ 支持节点、槽、键之间的映射查询,用于数据路由、在线伸缩等场景。
■ 无论添加、删除或者改变某个节点的哈希槽数量都不会造成集群不可用的状态。

四、Redis-Cluster 一致性保存


【1】Redis-Cluster 使用了异步复制:主节点对客户端请求回复状态后,异步发起写操作给从节点,会存在一个时间间隙。
【2】Redis-Cluster 出现网络分区时,当一个客户端与至少包含一个主节点在内的少数节点被孤立,可能导致在节点超时时间(node timeout)内,另一个网络分区内的大部分节点重新选举被孤立主节点的从节点为新的主节点。节点超时时间选项为 cluster-node-timeout 15000(毫秒)

五、使用 redis-trib.rb 搭建 Redis-Cluster


Redis集群至少需要3个节点,因为投票容错机制要求超过半数节点认为某个节点挂了该节点才是挂了,所以2个节点无法构成集群。 要保证集群的高可用,需要每个节点都有从节点,也就是备份节点,所以Redis集群至少需要6台服务器。因为我没有那么多服务器,也启动不了那么多虚拟机,所在这里搭建的是伪分布式集群,即一台服务器虚拟运行6个redis实例,修改端口号为(7001-7006),当然实际生产环境的 Redis 集群搭建和这里是一样的。

【1】新建3主3从 Redis-cluster:6 个 Redis 启动目录,并新建 6 份 Redis 配置文件 redis.conf。并启动 6 个 Redis。

1 port 7000
2 cluster-enabled yes
3 cluster-config-file nodes.conf  #集群配置名
4 cluster-node-timeout 15000
5 appendonly yes  #快照压缩功能开启

【2】配置 Ruby 运行环境:安装 Ruby 及 Ruby-Redis 管理工具(redis 的版本和 ruby 包的版本最好保持一致)

1 yum install ruby rubygems -y
2 gem install redis-5.0.4.gem

【3】配置 Redis-Cluster:
   ■ 使用 redis-trib.rb 的 create 命令创建 Redis-Cluster

1 ./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 
2 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 

   ■ 根据命令提示输入选项后(输入“yes”),会创建一个新的集群。
   ■ 选项 replicas 1:表示集群中的每个主节点对应一个从节点,后三个地址为从节点。
     
   ■ 查看当前集群信息:[cluster info]
   ■ 查看集群里有多少个节点:[cluster nodes]

六、进行 Redis 主节点扩展


【1】添加一个新主节点:添加一个空的主节点

1 port 7006
2 cluster-enabled yes
3 cluster-config-file nodes.conf  #集群配置名
4 cluster-node-timeout 15000
5 appendonly yes  #快照压缩功能开启

  将该节点添加到现有集群中,第一个参数是新节点的地址,第二个参数是任意一个已经存在的节点的IP和端口。

./redis-trib add-node 127.0.0.1:7006 127.0.0.1:7000

【2】移动 slot(槽)到该节点:只需要指定集群中其中一个节点的地址,redis-trib 就会自动找到集群中的其他节点。根据提示填写每个节点需移动的 slot 数量。

./redis-trib reshard 127.0.0.1:7000

七、进行 Redis 从节点扩展


【1】使用 redis-trib.rb 进行从节点扩展:新建一个 Redis 服务,使用如下命令使其成为指定主节点的从节点。

1 #./redis-trib.rb add-node --slave --master-id <主节点ID> <新增从节点ip:port> <原集群中任一节点ip:port>
2 redis-trib.rb add-node --slave --master-id f413fb7e6460308b17cdb71442798e1341b56cbc 127.0.0.1:6379 127.0.0.1:6384

【2】使用 [CLUSTER REPLICATE] 进行从节点扩展:使用 redis 客户端连接到从节点,使用如下命令使其成为指定主节点的从节点

redis 127.0.0.1:7006>cluster replicate <主节点 id>

八、Redis 节点移除或迁移


【1】使用 [del-node] 命令移除 redis 节点:可以直接移除从节点,但是使用该方法移除主节点时,需要确保这个主节点是空的。如果不是空的,需要将这个节点的数据重新分片到其他主节点上,否则会导致集群不可用。

./redis-trib del-node <Redis集群中的任意节点ip:port> <待移除节点id>

【2】Redis 从节点迁移:建议去从节点最多的主节点上进行从节点的迁移,从节点的迁移能够提高整个 Redis 集群的可用性。

CLUSTER REPLICATE <master-node-id>

九、Redis-Cluster 使用


【1】redis-cli 工具

1 #-c:表示连接到集群
2 $redis-cli -c -h 127.0.0.1 -p 7000
3 redis 127.0.0.1:7000>set key value
4  ->Redirected to slot[12180] located at 127.0.0.1:7003
5 OK

【2】使用 Jedis.jar 连接 Redis-Cluster

1 Set<HostAndPort> nodes = new LinkedHashSet<HostAndPort>();
2 nodes.add(new HostAndPort("127.0.0.1",7000));
3 nodes.add(new HostAndPort("127.0.0.1",7001));
4 nodes.add(new HostAndPort("127.0.0.1",7002));
5 nodes.add(new HostAndPort("127.0.0.1",7003));
6 nodes.add(new HostAndPort("127.0.0.1",7004));
7 nodes.add(new HostAndPort("127.0.0.1",7005));
8 
9 JedisCluster cluster = new JedisCluster(nodes,poolConfig);
 
posted @ 2020-11-20 11:20  Java程序员进阶  阅读(248)  评论(0编辑  收藏  举报