Redis集群

集群

Redis主从模式产生的问题

因为写操作都是在主机中,所以在并发写的时候一台主机可能会挂掉。


 

什么是集群

Redis集群实现了对Redis的水平扩容,即启动N个redis结点,将整个数据库分布存储在这N个结点中,每个结点存储总数据的1/N

Redis集群通过分区来(partition)提供一定程度的可用性(availability):即使集群中有一部分结点失效或者无法进行通讯,集群也可以继续处理命令请求。


 

两种模式

传统的代理主机模式

缺点:需要8台服务器,太占用资源。且代理服务器挂了,整个都无法使用。

无中心化集群

只需要六台主机即可使用,不同结点之间会转发请求。


 

搭建Redis集群

目录结构

      • redis-7.0.0
      •   src
      •     redis-server
      •     redis-cli
      • myredis
      •   cluster
      •     redis6379.conf
      •     redis6389.conf
      •     redis6380.conf
      •     redis6390.conf
      •     redis6381.conf
      •     redis6391.conf

配置文件

内容如下(redis6379.conf)

说明:

cluster-enabled yes  #打开集群

cluster-config-file nodes-6379.conf  #设置结点配置文件名字

cluster-node-timeout 15000  #设置结点失联时间,超过该时间(毫秒),集群自动进行主从切换

补充命令:

vi中快速替换命令:%s/被替换内容/新内容

可以用%s/6379/6380 快速将6379替换为6380

启动服务器

合体

首先要关掉防火墙

systemctl status firewalld    -可以查看防火墙状态

使用systemctl stop firewalld可以关闭防火墙

使用“./redis-cli --cluster create --cluster-replicas 1 ip:port...”来进行合并

./redis-cli --cluster create --cluster-replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6389 127.0.0.1:6390 127.0.0.1:6391

由于此次测试是在一台虚拟机上,所以用的是本机地址,在真实的环境下使用真实的IP地址。

可能会遇到的问题

若节点在本地可以访问,但是无法远程访问,且可以ping得通。

在配置文件里,将protected-mode设置为no

将bind 127.0.0.1这一行注销


 

集群操作

集群策略连接

使用命令: ./redis-cli -c -p 6379  #-c表示采用集群策略连接,设置数据会自动切换到相应的写主机。

每次插入数据时候,若需要移动key就会提示已经分配到ip:port的主机。

查看集群信息

使用命令:cluster nodes 可以查看集群信息

可以看到哪些服务器是主机,哪些服务器是从机。

第一列是id,服务器的唯一标识符。3247d52ba20f549aac10868b1ad28b2e381f9c5b

第二列是节点IP地址和端口号。如:127.0.0.1:6379@16379 

第三列是节点的身份。如:master 

第四列是显示节点所属主机的id。如: -

第五列是最后一次发送ping的时间。如:0

第六列是最后一次收到ping的时间。 如:1652171722462,使用的是Unix时间戳表示

第七列是结点epoch值。如:1

第八列是链接状态。如:  connected

第九列是插槽范围。如:0-5460


 

集群分配策略

一个集群至少要有三个主结点

创建集群的时候的选项“--cluster-replication 1”表示我们希望为集群中每个主节点创建一个从节点

分配原则是尽量保证每个主数据库运行在不同的IP地址。每次主库和从库也不在一个IP地址。

这么做的原因:若从库和主库都在一个服务器上,若此服务器崩了,那么主库和从库都是去了作用,设置从库的目的就是在主库崩掉时,从库来代替主库。


 

插槽

基本概念

插槽数量:一个Redis集群包含16384个插槽(hash slot),数据库中的每个键都属于这16384个插槽中的一个。

插槽计算方式:集群使用公式CRC16(key) % 16384 来计算键(key)属于哪个插槽,其中CRc16(key)语句用于计算键key的CRC16校验和。类似于哈希函数。

集群处理数据方式:集群中的每个节点都负责处理一部分插槽。

操作

设置单个Key

设置单个Key时,如果发现Key的插槽不在当前服务器,会自动分配到其他服务器。

设置多个Key

不在一个slot下的键值,不能直接使用mset

可以通过{}来定义组的概念,从而使key的{}中内容相同的键值对放在一个slot中

上述中 key1 value1,key2 value2,key3 value3都属于Bo,计算插槽的时候是根据组的名字来计算的,也就是根据“Bo”来计算的,

获取键的插槽

cluster keyslot <组名或key名>

命令简记:KeySlot 键的插槽。

获取插槽中key数量

 cluster countkeysinslot <插槽值>

命令简记:Count Keys In Slot 计算插槽中的key数量。

获取插槽中key的名字

cluster getkeysinslot <插槽值> <个数>

命令简记:Get Keys In Slot 获取插槽中的key。


 

故障恢复

主结点下线,从机结点能否自动升为主节点?

15秒超时后就会自动变为主节点

主结点恢复后,主从关系会如何?

主节点回来变为从节点

如果所有某一段插槽的主从结点都挂掉,redis服务是否还能继续?

如果某一段插槽的主从都挂掉,而配置中cluster-require-full-converage 为yes,那么整个集群都会挂掉

如果某一段插槽的主从都挂掉,而配置中cluster-require-full-converage 为no,那么该段内的插槽中的数据全不能使用,也无法存储


 

集群的Jedis开发

创建并使用集群

使用HostAndPort类创建主机端口号对象

再把HostAndPort对象加载到JedisCluster对象中。


 

Redis集群优点

    • 实现扩容
    • 分摊压力
    • 无中心配置相对简单

Redis集群的不足

    •  多键操作不被支持
    • 多键的Redis事务不被支持
    • LUA脚本不被支持
    • 由于集群方案出现较晚,很多公司已经采用了其他的集群方案,而代理或者客户端分片的方案想要迁移到redis cluster,需要整体迁移而不是逐步过渡,复杂度较大

Redis缓存穿透

现象

应用服务器压力变大,Redis的命中率降低,一直查询数据库。

造成原因

出现很多非正常url访问,Redis查询不到,然后就查询数据库,多数因为黑客攻击。

解决方法

1.对空值缓存

如果一个查询返回的数据为空(不管数据是否存在),都把这个空结果(null)进行缓存,设置空结果的过期时间会很短,最长不超过五分钟。

2.设置可访问名单

使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次访问和bitmap里面的id进行比较,如果访问id不在bitmaps里面,进行拦截,不允许访问。

3.采用布隆过滤器

布隆过滤器是1970年由布隆提出的,实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数)。

4.进行实时监控

当返现Redis的命中率开始急速降低,需要排查访问对象和访问的数据,和运维人员配置,可以设置黑名单限制服务。

5.报警

 

Redis缓存击穿

现象

数据库访问压力瞬间增大

redis里面并没有出现大量的key过期

redis正常运行,但数据库已经崩了

造成原因

redis中某个key过期了,但是这个key被大量访问。

解决方案

1.预先设置热门数据

在redis高峰访问之前,把一些热门数据提前存入到redis里面,加大这些热门数据key的时长。

2.实施调整

现场监控哪些数据热门,实施调整key的过期时长。

3.使用锁:

在缓存失效的时候,不立即去访问数据库。

先使用缓存工具的某些带成功操作返回值的操作(如Redis的setnx)去set一个mutex key(锁)。

当操作返回成功时,再进行访问数据操作,并设置缓存,最后删掉mutex key(锁)。

当操作返回失败,证明有线程在访问数据库,当前线程睡眠一段时间再重试。

 

Redis缓存雪崩

现象

数据库压力变大,服务器崩溃

造成原因

在极少时间段,查询大量的key集中过期。

解决方案

1.构建多级缓存架构

nginx缓存+redis缓存+其他缓存(ehcache等)

2.使用锁或队列

用加锁或者队列方式保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并请求落到底层存储系统上。不适用高并发情况,且效率极低。

3..设置过期标志更新缓存

记录缓存数据是否过期(设置提前量),如果过期会通知另外的线程在后台去更新实际key的缓存。

4.将缓存失效时间分散开

在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样就很难引发集体失效的事件。

 

posted @   Laplace蒜子  阅读(58)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示