redis集群

redis集群

注意:我使用的版本是6.0.10,不同版本可能略有差别

redis集群的出现解决了redis在分布式方面的需求(3.0版本出现),而且解决了原本的哨兵模式sentinel无法解决从节点下线的问题。

redis-cluster使用虚拟槽的方式来进行分片,把所有的节点映射到0-16383槽点上,cluster负责维护节点到哈希槽之间的关系,当需要在redis集群中存放键值对时,redis先对key使用crc16算法算出一个结果,然后对16384取余,redis会根据节点数量将哈希槽映射到不同的节点上

每个Redis集群节点需要两个TCP连接打开,正常的TCP端口用来服务客户端,例如6379,加10000的端口用作数据端口,必须保证防火墙打开这两个端口

为什么采用虚拟槽的方式

数据分片的路由策略一般有三种:取模、一致性hash、虚拟槽

取模

取模是根据元素对节点数取模获得的 但是存在问题就是如果增加或减少节点时,数据的路由会发生变化,没有什么可扩展性

有 N 台服务器,有一台宕机,变为 N-1 台,每 N*(N-1)个数中, 只有(n-1)个单元,%N, %(N-1)得到相同的结果,命中率在服务器宕机的短期内, 急剧下降至 (N-1)/(N*(N-1)) = 1/(N-1),服务器越多, 则 down 机的后果越严重!

一致性hash

一致性hash是对2^32^ 取模,将Hash值空间组成虚拟的圆环,整个圆环按照顺时针方向依次排列,之后将每个服务器进行hash运算,确定服务器在hash环上的地址,确定了服务器地址后,对数据同样使用hash算法,将数据定位到服务器上,如果定位的位置没有服务器,从顺时针寻找,找到的第一台服务器即为该数据最终的服务器位置

当某个节点 down 后,只影响该节点顺时针之后的 1 个节点,而其他节点不受影响,因此,Consistent Hashing 最大限度地抑制了键的重新分布

但是存在的问题是很难保证客户端的请求平均分配在各个节点,不能很好地负载均衡,在服务器很少的时候,容易出现服务器节点分布不均

虚拟槽

虚拟槽是根据某个散列函数得到槽位,找到对应的节点,N 个真实节点,把每个真实节点映射成 M 个虚拟节点,再把 M*N 个虚拟节点,散列在圆环上,各真实节点对应的虚拟节点相互交错分布,这样,某真实节点 down 后,则把其影响平均分担到其他所有节点上

集群命令

  • CLUSTER INFO:获取集群的信息
  • CLUSTER NODES:获取集群当前已知的所有节点,以及这些节点的相关信息
  • CLUSTER MEET :将ip和port所指定的节点添加到集群当中
  • CLUSTER FORGET <node_id>:从集群中移除 node_id 指定的节点
  • CLUSTER REPLICATE <node_id>:将当前节点设置为 node_id 指定的节点的从节点
  • CLUSTER SAVECONFIG:将节点的配置文件保存到硬盘里面
  • CLUSTER ADDSLOTS [slot ...]:将一个或多个槽分配给当前节点
  • CLUSTER DELSLOTS [slot ...]:从当前节点移除一个或多个槽
  • CLUSTER FLUSHSLOTS:移除分配给当前节点的所有槽
  • CLUSTER SETSLOT NODE <node_id>:将槽分配给 node_id 指定的节点,如果槽已经分配给另一 个节点,那么先让另一个节点删除该槽>,然后再进行分配
  • CLUSTER SETSLOT MIGRATING <node_id>:将本节点的槽迁移到指定的节点中
  • CLUSTER SETSLOT IMPORTING <node_id>:从指定节点导入槽到本节点
  • CLUSTER SETSLOT STABLE:取消对槽的导入(import)或迁移(migrate)
  • CLUSTER KEYSLOT :计算键 key 应该被放置在哪个槽
  • CLUSTER COUNTKEYSINSLOT :返回槽目前包含的键值对数量
  • CLUSTER GETKEYSINSLOT :返回 count 个槽中的键
  • migrate 目的节点ip 目的节点port 键名 数据库号码 超时时间 [copy] [replace]:迁移某个键值对

集群配置

修改redis.conf来设置集群参数

conf 复制代码
# 开启集群模式
cluster-enabled yes
# 每个节点对应的配置文件
cluster-config-file nodes-6380.conf

手动配置集群

在使用客户端连接时

shell 复制代码
#-c 表示集群连接  如果不使用集群连接,无法访问到集群内的数据
redis-cli -c -p 6379

# 可以使用redis-cli来分配槽点
redis-cli -p 6381 cluster addslots {10923..16383}

查看集群节点

shell 复制代码
cluster nodes
------------------------
57702920ad1a9849cb61ff6b83f9aba97effee9e :6379@16379 myself,master - 0 0 0 connected 12458

此时只有一个节点,所以集群节点只有一个

然后将6380和6381加入到集群中

shell 复制代码
127.0.0.1:6379> cluster meet 127.0.0.1 6380
OK
127.0.0.1:6379> cluster meet 127.0.0.1 6381
OK

127.0.0.1:6379> cluster nodes
85f3b3d55caa4699abaa916b1a7a800b06226b18 127.0.0.1:6380@16380 slave 57702920ad1a9849cb61ff6b83f9aba97effee9e 0 1614926896368 1 connected
d49e7bc9e01c4f0b687c46d964ef6cdccf90fff2 127.0.0.1:6381@16381 slave 57702920ad1a9849cb61ff6b83f9aba97effee9e 0 1614926895337 1 connected
57702920ad1a9849cb61ff6b83f9aba97effee9e 127.0.0.1:6379@16379 myself,master - 0 1614926895000 1 connected 12458

查看集群信息

shell 复制代码
127.0.0.1:6379> cluster info
--------------------------------------
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:4
cluster_size:3
cluster_current_epoch:2
cluster_my_epoch:2
cluster_stats_messages_ping_sent:331
cluster_stats_messages_pong_sent:299
cluster_stats_messages_fail_sent:1
cluster_stats_messages_sent:631
cluster_stats_messages_ping_received:298
cluster_stats_messages_pong_received:330
cluster_stats_messages_meet_received:1
cluster_stats_messages_fail_received:1
cluster_stats_messages_update_received:90
cluster_stats_messages_received:720

也使用命令来自己分配槽点

shell 复制代码
cluster addslots [slot ...]

集群中所有master参与投票,如果半数以上的master节点与其中一个master节点通信超过cluster-node-timeout,则认为该master节点挂掉

也可以为集群中的主节点配置从节点

shell 复制代码
cluster replicate f82552a7942609ee90e5201d563804c065588847

如果需要重新构建集群关系的话,需要删除每个节点的node.conf和rdb文件,否则集群搭建不成功

配置集群

上述操作有些麻烦,有次无意间发现原来redis-cli中是可以创建集群的

shell 复制代码
# 查看帮助命令
redis-cli --cluster help

发现可以使用create来创建集群

lua 复制代码
create         host1:port1 ... hostN:portN
                 --cluster-replicas <arg>

示例如下

css 复制代码
redis-cli --cluster create 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385 127.0.0.1:6386 --cluster-replicas 1

脚本操作集群

redis-trib.rb是Redis源码中提供的一个辅助工具,可以非常方便的来操作集群,它是用 ruby写的,因此需要在服务器上安装相应环境

安装Ruby环境

安装Ruby

  • 下载ruby安装包,地址www.ruby-lang.org/en/download...
  • 然后分别configure、make、make install
  • 安装后通过ruby -v 查看一下版本,看是否正常

安装rubygems

  • 下载包,地址rubygems.org/pages/downl...
  • 解压后进入解压文件夹,运行 ruby setup.rb
  • 安装后通过gem --v查看一下版本,看是否正常

安装redis的ruby library

  • 使用淘宝源下载,gem sources --remove rubygems.org/ ,然后添加gem sources -a ruby.taobao.org/
  • 可以通过gem sources -l 查看源
  • 运行gem install redis
脚本操作
初始化集群
shell 复制代码
# create表示要初始化集群 --replicas 1表示每个主数据库拥有的从数据库为1个
ruby redis-trib.rb create --replicas 1 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385 127.0.0.1:6386
添加新节点
shell 复制代码
# 添加主节点
redis-trib.rb add-node 127.0.0.1:6387 127.0.0.1:6381

# 添加从节点
redis-trib.rb add-node --slave --master-id 主节点id 新节点的ip和端口 旧节点ip和端口
删除节点
shell 复制代码
# 如果删除的是已经占有哈希槽的节点会失败,需要先将该节点占用的hash槽分配出去
redis-trib.rb del-node 127.0.0.1:7005 节点id
数据迁移
shell 复制代码
ruby redis-trib.rb reshard ip:port 

这就告诉Redis要重新分片,ip:port可以是集群中任何一个节点

集群不可用情况

集群中每个节点都会定期向其他节点发出ping命令,如果没有收到回复,就认为该节点为疑似下线,然后在集群中传播该信息;当集群中的某个节点,收到半数以上认为某节点已下线的信息,就会真的标记该节点为已下线,并在集群中传播该信息

  • 如果集群任意master挂掉,且当前master没有slave,则集群进入fail状态
  • 如果集群超过半数的master挂掉,不管有没有slave,集群进入fail状态

集群支持高级特性

如果要在集群上使用事务、LUA脚本等功能,必须保证所操作的key在同一个槽点中,可以使用hash tags来确保在同一个槽点中,如下面所示的格式,redis会根据{}中提供的字符来进行hash操作寻找多对应的槽点,使得相关键都分配到同一个节点以支持多键操作(MGET)

shell 复制代码
{person.did}person:did

zhhll.icu/2021/数据库/非关...

本文由mdnice多平台发布

相关推荐
大白要努力!3 分钟前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
tatasix1 小时前
MySQL UPDATE语句执行链路解析
数据库·mysql
南城花随雪。1 小时前
硬盘(HDD)与固态硬盘(SSD)详细解读
数据库
儿时可乖了1 小时前
使用 Java 操作 SQLite 数据库
java·数据库·sqlite
懒是一种态度1 小时前
Golang 调用 mongodb 的函数
数据库·mongodb·golang
天海华兮1 小时前
mysql 去重 补全 取出重复 变量 函数 和存储过程
数据库·mysql
gma9992 小时前
Etcd 框架
数据库·etcd
爱吃青椒不爱吃西红柿‍️2 小时前
华为ASP与CSP是什么?
服务器·前端·数据库
Yz98763 小时前
hive的存储格式
大数据·数据库·数据仓库·hive·hadoop·数据库开发
苏-言3 小时前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring