Redis八股

📅 发布时间:2026/7/12 13:14:21 👁️ 浏览次数:
Redis八股
1.什么是缓存穿透缓存后不再存在ID访问数据库布隆过滤器我们假设ID缓存了经过HASH计算得到0000000000111111111这样的。那么布隆内部维护了一堆数组将对应号位的置1下次再次hash如果全是1就代表存在也会存在hash冲突解决方法增加数组长度多次has2.什么是缓存击穿热点数据设了过期key刚好大并发来了直接击穿1.加锁2.异步更新线程来了发现过期了但是照常返回然后异步更新缓存。会有旧数据问题3.缓存雪崩key的过期时间一致时间到了并发冲烂随机时间4.redis做为缓存mysql的数据如何与redis进行同步呢双写一致性线程中断导致旧数据1.加锁读写锁Redisson在读的时候添加共享锁可以保证读读不互斥、读写互斥。当我们更新数据的时候添加排他锁。它是读写、读读都互斥这样就能保证在写数据的同时是不会让其他线程读数据的避免了脏数据。这里面需要注意的是读方法和写方法上需要使用同一把锁才行。其实排他锁底层使用的也是SETNX它保证了同时只能有一个线程操作锁住的方法。读锁加锁条件当前没有线程持有写锁释放后只要没有读锁了写锁就能竞争。写锁加锁条件当前没有任何线程持有读锁或写锁释放后读锁和写锁都能竞争。2.mqcanal当数据库发生修改cancl类似从库的机制监听文件如果发送改变到达mqmq进行接收。然后进行处理。可能会有旧数据3.延时双删删除时间不好确定改页不好改容易导致旧数据污染5.Redis持久化在Redis中提供了两种数据持久化的方式1) RDB2) AOF。RDB因为是二进制文件保存时体积也比较小所以它恢复得比较快。但它有可能会丢数据。bgsave开始时会fork主进程得到子进程子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB我们通常在项目中也会使用AOF来恢复数据。虽然AOF恢复的速度慢一些但它丢数据的风险要小很多。在AOF文件中可以设置刷盘策略。我们当时设置的就是每秒批量写入一次命令。每隔几秒读取新的命令文件、RDB块 AOF慢6.Redis过期策略惰性删除懒加载执行key操作前查询定时删除某一段时间查询SLOW模式是定时任务执行频率默认为10hz每次不超过25ms可以通过修改配置文件redis.conf的hz选项来调整这个次数2) FAST模式执行频率不固定每次事件循环会尝试执行但两次间隔不低于2ms每次耗时不超过1ms。Redis的过期删除策略是惰性删除 定期删除两种策略配合使用。7.Redis过期淘汰策略Redis中的内存不够用时此时在向Redis中添加新的key那么Redis就会按照某一种规则将内存中的数据删除掉这种数据的删除规则被称之为内存的淘汰策略。LRU最近后访问就删最近后LFU热点数据淘汰法8.Redis分布式锁的实现SETNX给指定key设置值仅当 key 不存在时成功返回 1key 已存在则失败返回 0 原子性操作如果一直获取锁怎么办呢Redisson框架如果业务代码卡在循环里一直不结束Redisson 的看门狗确实会一直给锁续期直到线程本身被终止。偏向锁 → 轻量级锁 → 重量级锁在高并发下一个业务有可能会执行很快。客户1持有锁的时候客户2来了以后并不会马上被拒绝。它会自旋不断尝试获取锁。如果客户1释放之后客户2就可以马上持有锁性能也得到了提升。轻量级锁机制Redisson实现的分布式锁是可重入的吗是可重入的如果是当前线程持有锁就会1防止死锁如果有多台redis做主从呢RedLock(红锁)不能只在一个redis实例上创建锁应该是在多个redis实例上创建锁(n / 2 1)避免在一个redis实例上加锁。效率过低zookeeper推荐Redlock 是 Redis 官方推荐的多节点分布式锁算法核心思路是在多个独立的 Redis 节点至少 3 个上同时加锁只有超过半数节点加锁成功才算整体加锁成功解决单节点故障导致锁失效的问题。import org.redisson.RedissonRedLock; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import java.util.concurrent.TimeUnit; public class RedissonRedLockDemo { // 多个独立的 Redis 客户端连接不同的 Redis 节点 private final RedissonClient redissonClient1; private final RedissonClient redissonClient2; private final RedissonClient redissonClient3; public RedissonRedLockDemo(RedissonClient client1, RedissonClient client2, RedissonClient client3) { this.redissonClient1 client1; this.redissonClient2 client2; this.redissonClient3 client3; } public void doBusinessWithRedLock() { // 1. 获取每个 Redis 节点的锁对象 RLock lock1 redissonClient1.getLock(business_lock); RLock lock2 redissonClient2.getLock(business_lock); RLock lock3 redissonClient3.getLock(business_lock); // 2. 构建 RedLock整合多节点锁 RedissonRedLock redLock new RedissonRedLock(lock1, lock2, lock3); try { // 3. 加锁必须指定 leaseTime禁用续期避免多节点续期不一致 // waitTime最多等5秒拿锁leaseTime锁最多持有30秒 boolean locked redLock.tryLock(5, 30, TimeUnit.SECONDS); if (!locked) { throw new RuntimeException(多节点加锁失败放弃执行); } // 执行业务逻辑多节点锁保证分布式环境下的原子性 System.out.println(RedLock 加锁成功执行业务...); Thread.sleep(1000); // 模拟业务耗时 } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(加锁被中断, e); } finally { // 4. 释放锁会同时释放所有节点的锁 if (redLock.isHeldByCurrentThread()) { redLock.unlock(); System.out.println(RedLock 释放成功); } } } }Redis 集群 / 主从主死亡从顶上9.Redis集群主从复制、哨兵模式、Redis分片集群。1.主从同步全量同步到增量同步主写从读全量同步是指从节点第一次与主节点建立连接的时候使用全量同步流程第一从节点请求主节点同步数据其中从节点会携带自己的replication id和offset偏移量。第二主节点判断是否是第一次请求主要判断的依据就是主节点与从节点是否是同一个replication id如果不是就说明是第一次同步那主节点就会把自己的replication id和offset发送给从节点让从节点与主节点的信息保持一致。第三在同时主节点会执行BGSAVE生成RDB文件后发送给从节点去执行从节点先把自己的数据清空然后执行主节点发送过来的RDB文件这样就保持了一致。当然如果在RDB生成执行期间依然有请求到了主节点而主节点会以命令的方式记录到缓冲区缓冲区是一个日志文件最后把这个日志文件发送给从节点这样就能保证主节点与从节点完全一致了后期再同步数据的时候都是依赖于这个日志文件这个就是全量同步。增量同步指的是当从节点服务重启之后数据就不一致了所以这个时候从节点会请求主节点同步数据主节点还是判断不是第一次请求不是第一次就获取从节点的offset值然后主节点从命令日志中获取offset值之后的数据发送给从节点进行数据同步。10.怎么保证Redis高可用性可以使用主从集群但是如果主死了没有监测机制就会发送无redis可用我们引入哨兵机制哨兵机制可以实现主从集群的自动故障恢复里面就包含了对主从服务的监控、自动故障恢复、通知 如果主节点死了会给从节点上升为新的主节点。同时告诉客户端新的主节点你们使用的Redis是单点还是集群哪种集群优先用1 主 1 从 哨兵保证高可用单实例控制内存不同业务拆独立 Redis不盲目上分片集群用最简单、最稳定、功能最完整的方案支撑业务。11.Redis脑裂由于Redis master节点和Redis slave节点和Sentinel处于不同的网络分区使得Sentinel没有能够心跳感知到master所以通过选举的方式提升了一个slave为master这样就存在了两个master就像大脑分裂了一样。这样会导致客户端还在old master那里写入数据新节点无法同步数据当网络恢复后Sentinel会将old master降为slave这时再从新master同步数据这会导致old master中的大量数据丢失。由于网络原因两个master那么old主节点降级为从同步新主丢失数据网络分区导致主节点被隔离哨兵集群把从节点提升为新主但旧主还在接收客户端写入最终出现两个主节点同时对外提供服务数据不一致。解决办法关于解决的话我记得在Redis的配置中可以设置第一可以设置最少的slave节点个数比如设置至少要有一个从节点才能同步数据第二个可以设置主从数据复制和同步的延迟时间达不到要求就拒绝请求就可以避免大量的数据丢失。min-replicas-to-write 1旧主发现没有从节点和它保持连接因为网络分区从节点都在新主那边不满足 “至少 1 个从节点” 的写入条件直接拒绝所有写请求。min-replicas-max-lag 5进一步限制即使从节点还在连接但复制延迟超过 5 秒说明同步异常主节点也会拒绝写入。12.Redis分片集群分片集群主要解决的是海量数据存储的问题集群中有多个master每个master保存不同数据并且还可以给每个master设置多个slave节点就可以继续增大集群的高并发能力。同时每个master之间通过ping监测彼此健康状态就类似于哨兵模式了。当客户端请求可以访问集群任意节点最终都会被转发到正确节点。13.Redis 分片集群读和写14.Redis为什么快完全基于内存的C语言编写。采用单线程避免不必要的上下文切换和竞争条件。使用多路I/O复用模型非阻塞IO。例如BGSAVE和BGREWRITEAOF都是在后台执行操作不影响主线程的正常使用不会产生阻塞。阻塞IO多路复用socket select 线程客户端链接select -select可以获取事件线程来获取对应事件处理多个客户端链接一个select避免单对单的线程开辟也可以多并发读取信息也是非阻塞读取信息