目录

一、Redis6为什么引入了多线程

二、Redis的热Key问题如何解决

三、Redis的大Key问题如何解决

四、缓存与数据库双写不一致问题如何解决

五、redis分布式锁实现

六、分布式系统中常用的缓存方案有哪些

七、Redis集群策略

八、常见的缓存淘汰算法

九、redis主从复制的核心原理


一、Redis6为什么引入了多线程

在Redis6.0中引入多线程的主要原因是为了提高其网络处理的效率,尤其是在网络I/O上。以前版本的Redis是纯粹的单线程模式,这主要限制在网络请求的读写上。Redis本身的命令执行是非常快的,但在处理大量小请求时,网络通信尤其是数据发送和接受的处理可能会成为瓶颈。
以下是Redis6.0引I入多线程的一些主要原因和优势:
1.网络I/O瓶颈:在之前的纯单线程版本中,如果有非常多的小请求需要处理,网络I/O(数据包的解析和写入等)可能会限制整体吞吐量。通过引入多线程,Redis能够并行化网络数据的读写,从而克服这一瓶颈。
2.提升带宽利用率:通过多线程处理,可以更好地利用网络带宽,尤其是在大数据量传输的情形下,能够显著减少单线程造成的等待时间。
3.降低延迟:并行处理网络请求可以减少请求排队的时间,从而降低请求的平均延迟,提高Redis在高并发场景下的响应速度。
4.充分利用多核CPU:现代服务器通常具有多核CPU架构,单线程模式无法充分利用多核的优势。引入多线程后,可以更好地利用多核资源,提升Redis的整体吞吐量。
5.略微改变的工作模型:Redis6.0中,多线程主要用来处理请求的网络I/O,而实际的命令执行仍然在单线程中进行。这种设计避免了多线程对数据一致性和命令原子性的影响同时提升了网络处理的效率。

二、Redis的热Key问题如何解决

1.构建本地缓存

2.将热key分解为多个key,将请求分摊

3.限流

三、Redis的大Key问题如何解决

Redis的大Key问题是指单个Key所对应的数据量过大,一般单个key超过10kb就被认为是大Key,
这会导致以下问题:
1.网络延迟增大:传输大数据需要更多的时间
2.阻塞Redis性能:大Key的操作会阻塞Redis单线程的性能。
3.内存不足和导致OOM:大Key可能会占用过多内存,影响其它部分的缓存使用。
为了解决这些问题,可以采取以下解决方案:
解决方案
1.分拆大Key
big list:list1、list2、..listN
bighash:可以将数据分段存储,比如一个大的key,假设存了1百万的用户数据,可以拆分成200个key,每个key下面存放5000个用户数据

2.将大key压缩之后再存储

3.用scan命令一批批查询

4.开启惰性删除

四、缓存与数据库双写不一致问题如何解决

写数据库之后会更新缓存。读数据库之后,由于缓存中没有,也会更新缓存。所以多线程环境下会造成数据库和缓存数据不一致。

解决方案:

1.使用分布式读写锁

2.使用canal监听mysql的binlog,异步更新缓存

五、redis分布式锁实现

setnx+setex:存在设置超时时间失败的情况,导致死锁
set(key,value,nx,px):将setnx+setex变成原子操作
问题:
任务超时,锁自动释放,导致并发问题。使用redisson解决(看门狗监听,自动续期)
以及加锁和释放锁不是同一个线程的问题。在value中存入uuid(线程唯一标识),删除锁时判断该标识(使用lua保证判断+删除原子操作)
不可重入,使用redisson解决(实现机制类似AQS,计数)
异步复制可能造成锁丢失,使用redLock解决
1.顺序向五个节点请求加锁
2.根据一定的超时时间来推断是不是跳过该节点
3.三个节点加锁成功并且花费时间小于锁的有效期
4.认定加锁成功

六、分布式系统中常用的缓存方案有哪些

客户端缓存:页面和浏览器缓存,APP缓存,H5缓存,localStorage和sessionStorage
CDN缓存:内容存储,数据的缓存,内容分发,负载均衡
nginx缓存:静态资源
服务端缓存:本地缓存,外部缓存
数据库爱存:持久层缓存(mybatis,hibernate多级缓存),mysql查询缓存
操作系统缓存:Page Cache、Buffer Cache

七、Redis集群策略

Redis提供了三种集群策略:
1.主从模式:这种模式比较简单,主库可以读写,并且会和从库进行数据同步,这种模式下,客户端直接连主库或某个从库,但是但主库或从库宕机后,客户端需要手动修改IP,另外,这种模式也比较难进行扩容,整个集群所能存储的数据受到某台机器的内存容量,所以不可能支持特大数据量
2.哨兵模式:这种模式在主从的基础上新增了哨兵节点,但主库节点宕机后,哨兵会发现主库节点宕机,然后在从库中选择一个库作为进的主库,另外哨兵也可以做集群,从而可以保证但某一个哨兵节点宕机后,还有其他哨兵节点可以继续工作,这种模式可以比较好的保证Redis集群的高可用,但是仍然不能很好的解决Redis的容量上限问题。
3.Cluster模式:Cluster模式是用得比较多的模式,它支持多主多从,这种模式会按照key进行槽位的分配,可以使得不同的key分散到不同的主节点上,利用这种模式可以使得整个集群支持更大的数据容量,同时每个主节点可以拥有自己的多个从节点,如果该主节点宕机,会从它的从节点中选举一个新的主节点。
对于这三种模式,如果Redis要存的数据量不大,可以选择哨兵模式,如果Redis要存的数据量大,并且需要持续的扩容,那么选择Cluster模式。

八、常见的缓存淘汰算法

FIFO(First InFirstOut,先进先出),根据缓存被存储的时间,离当前最远的数据优先被淘汰;
LRU(LeastRecentlyUsed,最近最少使用),根据最近被使用的时间,离当前最远的数据优先被淘汰;
LFU(LeastFrequentlyUsed,最不经常使用),在一段时间内,缓存数据被使用次数最少的会被淘汰。

九、redis主从复制的核心原理

通过执行slaveof命令或设置slaveof选项,让一个服务器去复制另一个服务器的数据。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。
全量复制:
1.主节点通过bgsave命令fork子进程进行RDB持久化,该过程是非常消耗CPU、内存(页表复制)、硬盘IO的
2.主节点通过网络将RDB文件发送给从节点,对主从节点的带宽都会带来很大的消耗
3.从节点清空老数据、载入新RDB文件的过程是阻塞的,无法响应客户端的命令;如果从节点执行
bgrewriteaof,也会带来额外的消耗

部分复制:
1.复制偏移量:执行复制的双方,主从节点,分别会维护一个复制偏移量offset
2.复制积压缓冲区:主节点内部维护了一个固定长度的、先进先出(FIFO)队列作为复制积压缓冲区,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。
3.服务器运行ID(runid):每个Redis节点,都有其运行ID,运行ID由节点在启动时自动生成,主节点会将自己的运行ID发送给从节点,从节点会将主节点的运行ID存起来。从节点Redis断开重连的时候,就是根据运行ID来判断同步的进度:
如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使用部分复制(到底能不能部分复制还要看offset和复制积压缓冲区的情况);
如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不是当前的主节点,只能进行全量复制。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐