Redis笔记
简介:
redis时基于内存的单线程,IO多路复用,高性能,支持数据持久化,丰富的数据结构
redis支持数据类型:
1. string:基础键值对,用于存储文本,数字,字符串,常用于缓存,计数器或者存储基本信息
2. hash:键值对集合,适合存储对象属性,常用于:用户会话,配置信息。字段较少时内存效率高
3. list:有序可重复的列表集合,基于双向链表实现,支持在头尾插入或者删除元素,适用于消息队列,任务调度。
4. set:无序且元素唯一的集合,支持交集,并集等运算,常用于标签系统,去重,或者用户权限管理。
5. Sorted Set (ZSet):带权重的有序集合,在集合基础上为每个元素关联值,支持按值排序和范围查询,适用于排行榜或者其他排序
6. Stream:持久化的消息队列,高可靠消息队列(优于List),用于订单异步处理、实时风控与审计
7. Geo:处理地理信息,LBS应用:查找“附近门店”、“附近优惠”
8. HyperLogLog:用于基数统计,海量数据的UV(独立访客)统计、注册IP数等去重计数
9. Bitmap:位图操作,记录每日签到、统计活跃用户总数
reids为什么时单线程还这么快:
纯内存操作,非阻塞IO多路复用,单线程避免了上下文切换和锁竞争
redis的事务满足ACID吗?
总结:Redis 的事务(通过 MULTI / EXEC / DISCARD / WATCH 实现)并不完全满足传统关系型数据库的 ACID 特性,保证隔离性一致性,不保证原子性和持久性
特性 是否满足 说明
原子性 ❌ 不满足 不支持回滚,执行中的错误不会中止后续命令
一致性 ✅ 基本满足 数据结构约束得以保持,单线程执行无并发干扰
隔离性 ✅ 完全满足 串行执行,无事务间干扰
持久性 ⚠️ 部分满足 依赖持久化配置,默认不保证
使用建议
如果需要严格的 ACID 事务(尤其是原子性和回滚能力),不要使用 Redis,应考虑关系型数据库。
Redis 事务适合保证一组命令连续执行、不被其他客户端的命令打断(隔离性),并通过 WATCH 实现乐观锁,适用于计数器、库存等轻量级场景。
若要增强持久性,可以开启 AOF 并配置 appendfsync always,但会大幅降低性能。
原子性(Atomicity)
-
传统含义:事务中的所有操作要么全部成功,要么全部失败(回滚)。
-
Redis 实际情况:不完全满足,不支持回滚。
-
如果事务中某个命令在入队时出现语法错误(如参数数量不对),整个事务会被 拒绝,所有命令都不执行。
-
如果事务中某个命令在执行时出错(例如对 String 类型调用
LPOP),Redis 会继续执行队列中的后续命令,已经执行成功的命令不会回滚,失败的命令仅返回错误给客户端。 -
因此,Redis 无法自动撤销已执行的操作,需要开发者自行处理逻辑补偿。
-
设计理由:Redis 官方认为回滚的复杂性远超其收益,且大多数事务失败是编程错误,应该在上层避免。
一致性(Consistency)
-
传统含义:事务执行前后,数据库的完整性约束(如外键、唯一性等)不被破坏。
-
Redis 实际情况:基本满足。
-
Redis 数据结构本身有类型约束,错误类型的操作会被拒绝并返回错误,不会破坏内部数据结构。
-
由于单线程模型,
EXEC执行期间不会有其他命令穿插,因此不会出现脏读导致的逻辑不一致。 -
但程序员须确保业务逻辑的一致性(如转账扣款与入账必须成对执行),Redis 不会自动保证。
-
隔离性(Isolation)
-
传统含义:多个事务并发执行时,互相不可见,如同串行执行。
-
Redis 实际情况:完全满足(最高隔离级别:可序列化)。
-
Redis 是单线程处理命令,
EXEC会一次性顺序执行事务队列中的所有命令,在此期间 不会处理任何其他客户端的请求。 -
因此,事务之间天然串行,不存在脏读、不可重复读、幻读等问题。
-
配合
WATCH命令可实现乐观锁,隔离性依然得到保证。
-
持久性(Durability)
-
传统含义:事务一旦提交,其结果永久保存,即使系统故障也不会丢失。
-
Redis 实际情况:取决于持久化配置,默认不满足。
-
如果 Redis 仅运行在内存中(不开启 RDB 或 AOF),事务提交后数据可能因进程退出而全部丢失。
-
即使开启了 RDB 或 AOF,持久化时机也不是实时同步的:
-
RDB 按间隔生成快照,故障时可能丢失最近一次快照后的所有事务。
-
AOF 默认每秒同步一次(
appendfsync everysec),最多丢失一秒数据;若设为always每次命令都同步,性能极差。
-
-
因此,Redis 事务不具备 ACID 意义上的持久性。
-
数据常用缓存:redis,memcache,其中两种缓存的区别:
存储类型:memcached均是简单的字符串,而redis具有,string,list,set,zset,hash等类型
持久化:memcache存储到内存中,一旦断电或者重启数据容易丢失,redis也是存储到内存中的,但是可以持久化,周期性的会把数据保存到硬盘中,重启或者断电不会丢失数据
灾难恢复:memcache挂掉后数据不可回复,redis数据丢失后可以通过aof恢复,并且redis支持数据备份
过期策略(定期删除&惰性删除&混合策略&配置优化):
-
惰性删除:
描述:在访问一个键时,如果这个键过期了redis不会立即删除它,而是让这个键存在内存中,下次访问时redis才会检查过期时间,如果过期才会删除
好处:减少了redis的删除操作,降低了CPU使用率
缺点:过期键在一段时间内占据内存空间
-
定期删除:
描述:为解决惰性删除导致内存占用问题,redis还实现了定期删除策略,定期随机的检查一批次的键的过期时间,并删除已经过期的键
好处:通过主动删除来减少内存占用
缺点:内存虽然得到释放,但十分消耗CPU资源(尤其是在大量过期键的情况下,CPU要用来处理请求而不是用来删除过期KEY)
-
混合策略:
定期删除随机抽取检查一部分键并删除其中过期的,当客户端尝试访问一个键时如果该键已经过期,redis会检查并删除这个键,即减少了CPU使用率又有效的解决了内存占用问题
配置和优化:
active-expire-effort:可以调整定期删除的频率和范围,值越低表示越积极的定期删除,比如1:更积极的定期删除,5:相对保守的定期删除
hz:redis内部循环的频率,间接影响定期删除的执行频率
优化:在内存使用非常关键的应用中,可以增加active-expire-effor的值来提交删除效率,而在对延迟要求较高的时候通过减少该值来减少CPU占用
淘汰机制:
某个KEY在过期的情况下,定期删除没删除成功,惰性删除没生效(也没有再次去访问这个key),这样的过期key就会大量堆积在内存中,redis的内存就会越来越高,导致redis内存快耗尽,这时应该采用内存淘汰机制,redis提供了八个淘汰机制(vo la ti le-lfu、allkeys-lfu、volatile-lru、allkeys-lru、volatile-ttl、volatile-random、allkeys-random、noe vi c tion)
- noeviction:不进行淘汰数据,当缓存写满时再有请求进来就不提供服务,直接返回报错。redis用作缓存的时候实际数据通常较大,总有新数据写入,这个策略不包含淘汰机制,所以也不会腾出新的空间,所以一般不用做缓存服务中
- volatile-lfu(redis 4.0新增的):在设置过期时间的键值中,移除最近不频繁使用的键值
- allkeys-lfu(redis 4.0新增的):在所有键值中,移除最近不频繁使用的键值
- volatile-lru:在设置了过期时间的键值中,移除最少使用的键值
- allkeys-lru:在所有键值中,移除最少使用的键值(通常优先使用这个策略,可以充分利用LRU经典缓存算法优势,提升性能问题,如果业务数据有明显冷热数据区分,建议使用)
- volatile-ttl:在设置了过期时间的键值中,移除即将过期的键值
- volatile-random:在设置了过期时间的键值中, 随机移除某个键值(如果业务数据没有明显冷热数据区分,建议使用这个策略,随机淘汰过期数据)
LRU:按最近使用最少的原则来筛选数据,最不常用的数据会筛选出来,然后把所有数据组成一个链表,最右边是最不常用数据(lru),最左边是MRU(最新使用数据或者最新写入数据)

LRU算法需要用链表形式管理缓存数据,移除元素时从链表队尾移除,增加到头部,会带来额外的空间开销,当有数据访问的时候需要吧链条挪到MRU端,如果有大量数据被访问,就会带来很多链表操作会很耗时降低redis缓存性能
所以在redis中LRU算法做了简化,减轻数据淘汰对缓存性能的影响;redis会记录每个数据最后一次访问的时间戳(键值的数据结构),然后redis在要淘汰数据的时候会随机选出N个数据把它当作一个集合,然后对这个数据集合做对比吧lru字段最小的数据从集合中删除出去
配置:maxmemory-samples=redis选出的数据个数N,
LFU:根据key最近被访问频率来淘汰,很少被访问的优先淘汰,访问最频繁的则留下来,LFU算法能最好的表示最热点的数据,假如使用LRU某个数据不是频繁使用的,但是因为最近有人使用了一次,就会被认为是热点数据,不会被淘汰,反而访问频率最高的数据因为在这个时间段内没有被访问就会被淘汰,LFU并不会因为一次使用而使这个key成为热点数据
按访问次数移动链表是低效的,可能会存在大量访问次数相同的key,但实际我们不需要准确具体的访问次数,某些访问特别大的key(热点数据),在热点过去后可能都不会在访问了,但是因为访问次数大而一直占用着内存不被淘汰,需要一个方法淘汰(有点像LRU),可以设置逐步衰减访问次数来解决
- LRU:最近最不频繁使用的,跟使用次数有关,淘汰次数最少的
- LFU:最近最少使用的,跟最后一次时间有关,淘汰离当前时间最久的
redis实现分布式锁:
redis实现分布式锁主要是确保在分布式系统上当一个服务或者节点在处理某些资源的时候,其他服务或者节点不会同时访问或者修改同一个资源,以防止数据不一致或者竞争条件(保证数据的原子性)。redis因为高性能和易于使用的特点常被用作实现分布式锁的解决方案
锁的键名:lock_key ;锁值:unique_value;PX 3000 :设置过期时间为300s,NX当键不存在的时候才设置
设置锁:set lock_key unique_value NX PX 3000
检查锁:GET lock_key
释放锁:DEL lock_key
redlock算法:
- 获取当前时间
- 在N个独立的redis节点上一次尝试获取指定锁,每个节点的锁尝试获取时都应该设置相同的过期时间(比如5s)
- 计算获取锁的持续时间,如果大多数节点上成功获取了锁(至少达到N/2+1个节点),并且获取锁的总时间小于锁的过期时间,那么任务锁已经被成功获取了
- 如果锁被成功获取,则所有节点上设置相同的过期时间,如果锁获取失败,则在所有节点上释放以获取的锁
- 在持有锁的过程中定期续期,以防止某些原因导致死锁
- 无论操作成功与否,操作完成后释放锁
注意事项:
- 超时时间:确保超时时间足够短,避免长时间占用资源,但也足够长用来应付网路延迟或者redis服务延迟
- 重试机制:如果无法获取锁,应该又重试机制
- 监控和日志,记录所有锁相关的操作以便于调试和监控
- 安全性:确保使用唯一值来避免误删除其他客户端的锁
分布式锁应该具备那些条件:
- 在分布式系统环境下,一个方法在同一个时间只能被一个机器的一个线程执行
- 高可用的获取锁和释放锁
- 高性能的获取锁和释放锁
- 具备可重入特性
- 具备锁失效机制,防止死锁
- 具备非阻塞锁特性,即使没有获取到锁将直接返回获取锁失败
分布式锁的实现:
- 基于数据库实现分布式锁(适用于并发小的系统)
- 基于缓存(redis)实现分布式锁(效率高,最流行,存在锁超时的问题)
- 基于zookeeper实现分布式锁(可靠,但效率不高)
分布式锁必须特性:
- 互斥性,同一时刻只有一个客户端能持有锁
- 防死锁,锁必须又超时机制,防止客户端崩溃导致无法释放
- 容错性,redis节点宕机时,锁机制仍然可用
- 可重入性,同一个客户端可以多次获取同一把锁
- 高性能,加锁解锁操作要搞笑
分布式锁的解决方案:
- setnx+expire(非原子操作):需要保证数据原子性(了解特性,但生产环境勿用)
-
工作原理:先使用
SETNX命令(SET if Not eXists)尝试设置一个键,如果键不存在则设置成功并获得锁。随后立即使用EXPIRE命令为锁设置一个过期时间,防止因程序异常未能释放而导致死锁。 -
致命缺陷:
SETNX和EXPIRE是两个独立的Redis命令,不具备原子性。如果在执行完SETNX后、执行EXPIRE之前,程序发生崩溃(如进程crash或宕机),这个锁将永远无法过期,导致所有客户端再也无法获取到锁,造成 “死锁” - 使用set key value nx ex 一条命令完成:为了解决的setnx+expire非原子性问题,Redis 2.6.12版本及以上提供了增强版的
SET命令。-
工作原理:通过一条命令,原子性地完成加锁和设置过期时间。一个标准的加锁命令,如:SET lock_key unique_value NX EX 30
-
lock_key: 锁的名称。 -
unique_value: 一个全局唯一的标识符(如UUID),用于标识锁的持有者,防止误删他人持有的锁。 -
NX: (Not eXists) 只在key不存在时设置,确保互斥性。 -
EX 30: 设置键的过期时间为30秒(单位秒),避免死锁。
-
-
注意事项:
-
即使加锁是原子的,释放锁的操作仍然必须保持原子性,否则可能误删他人持有的锁。因此,释放锁时必须通过Lua脚本,先判断
unique_value是否匹配,再执行删除,确保“删锁的是锁的持有者”。 -
业务执行时间不能超过锁的过期时间。
-
-
- redisson:它的核心优势在于自动处理了许多手动实现时容易出错的问题。实现原理:
① 可重入性 (Reentrant)
-
问题:同一线程在已持有锁的情况下,若再次请求同一把锁,会因
SET NX的互斥性而阻塞自己,导致死锁。 -
Redisson方案:使用Hash(哈希表)数据结构存储锁,以
UUID:threadId作为字段(Field),以线程的重入次数作为值(Value)。 -
加锁流程(Lua脚本原子执行):
-
检查锁键
myLock是否存在。 -
若不存在:创建Hash,设置
field=UUID:threadId, value=1,并设置过期时间。 -
若存在,检查Hash中是否有当前线程的
field:若有,将value加1,表示重入,同时刷新过期时间;若无,表示其他线程持有锁,加锁失败。
-
-
释放锁流程(Lua脚本原子执行):
-
检查
field是否存在:若不存在,返回nil,不做任何操作。 -
若存在,将其
value减1。 -
若减1后
value大于0,表示仍有重入,仅刷新过期时间。 -
若减1后
value等于0,表示完全释放,删除整个锁键,并通过publish命令发布释放消息,通知等待的线程。
-
② 自动续期 - 看门狗 (Watchdog)
-
问题:业务执行时间不确定,可能超过锁的超时时间,导致锁被提前释放,其他线程趁机而入,破坏数据一致性。
-
Redisson方案:看门狗机制。当使用
lock()方法且未显式指定leaseTime时,Redisson会启动一个后台线程(看门狗)。 -
工作机制:
- 加锁成功后,看门狗启动一个定时任务,每
internalLockLeaseTime(默认30秒) / 3 = 10秒运行一次 - 每次执行时,检查锁是否仍由当前线程持有:若是,则通过Lua脚本将锁的过期时间重置为
internalLockLeaseTime(即30秒) - 只要业务线程还活着,看门狗就会持续续期,保证锁不会因超时而被自动释放
- 业务完成后调用
unlock(),看门狗任务会被主动取消并终止
- 加锁成功后,看门狗启动一个定时任务,每
-
重要提示:如果调用lock(10, TimeUnit.SECONDS)指定了leaseTime,看门狗机制将不会启动,锁将在10秒后无条件释放
总结与对比
| 特性 | setnx + expire | set nx ex | Redisson |
|---|---|---|---|
| 原子性加锁 | ❌ 否 | ✅ 是 | ✅ 是 |
| 可重入性 | ❌ 否 | ❌ 否 | ✅ 是 |
| 自动续期 | ❌ 否 | ❌ 否 | ✅ 是 (看门狗) |
| 安全释放锁 | ❌ 复杂,需自实现 | ✅ 需手动实现(通过Lua) | ✅ 内置 |
| 是否推荐生产 | 🚫 极力不推荐 | ⚠️ 简单场景可用,风险自担 | ✅ 强烈推荐 |
总结:setnx+expire是必死方案;set nx ex是基础原子方案;而Redisson提供了生产级特性,解决依赖的复杂问题。
Big Key和Hot Key:
总结:
bigkey : 数据量大的key;危害:阻塞网络,数据倾斜;处理:拆分,压缩,清理
重在“避大”,通过拆分、压缩、异步删除来降低单 Key 的内存和耗时。
hotKey : 访问频率高的key;危害:单节点压力过大;处理:本地缓存,读写分离,分片
重在“散热”,通过本地缓存、读写分离、副本碎片化将热点流量打散到多节点。
如果业务同时存在 Big Key & Hot Key(例如一个很大的 ZSet 又被高频访问),优先拆分解决 Big Key 问题,否则本地缓存也无法解决网络传输和序列化开销。
Big Key(数据量大的 Key)
常见类型与判断标准
-
String 类型:value 超过 10 KB(常规建议阈值为 10KB~1MB,视业务而定)
-
Hash / List / Set / Sorted Set:元素个数超过 5000(经验值,也可放宽到 1万~5万)
-
超过 1 MB 的 String 或 超过 1 万个成员的集合类型,基本可认定为 Big Key
危害细化
- 阻塞网络
- 数据倾斜
- 慢查询 & 阻塞:对 Big Key 执行
DEL、GET、HGETALL、LRANGE等 O(N) 命令会长时间占用主线程,导致服务卡顿甚至超时。 - 集群带宽压力:在 Redis Cluster 中,Big Key 在大 Key 迁移(如扩缩容、槽重平衡)时会产生大量网络传输,拖慢整个集群
- 内存碎片 & 淘汰困难:大内存块频繁申请释放容易产生碎片;maxmemory-policy 在面对 Big Key 时可能无法及时淘汰
处理策略深度解析
| 策略 | 具体做法 | 适用场景 |
|---|---|---|
| 拆分 | 1. String 分块:将一个大 JSON 拆成多个小 key(如 user:1000:profile、user:1000:history)2. Hash/Set 分片:将单个大 Hash 按业务字段拆成多个小 Hash(如按 ID 取模 hash_0、hash_1...)3. List 分页:使用 LPUSH + LTRIM 控制列表长度 |
绝大多数场景,尤其集合类型 |
| 压缩 | 1. 序列化压缩:如将 Java 对象用 Protobuf/Kryo 序列化后存 String 2. 文本压缩:对 JSON/XML 使用 GZIP 或 Snappy 压缩后存入 Redis(读写时解压) |
存储大文本、二进制数据 |
| 清理 | 1. 异步删除:使用 UNLINK 代替 DEL,避免阻塞主线程2. 懒过期:设置过期时间 + 惰性删除,避免集中大批量清理 3. 扫描清理:使用 HSCAN / SSCAN / ZSCAN 分批删除元素 |
明确不再需要的 Big Key |
特别注意:禁止在主节点上直接使用 KEYS 查询 Big Key,应使用 --bigkeys 参数(redis-cli --bigkeys)或在从节点执行 SCAN + DEBUG OBJECT。
Hot Key(访问频率极高的 Key)
危害补充
-
CPU 瓶颈:单节点处理 Hot Key 请求占用大量 CPU,导致同节点的其他普通请求延迟飙升。
-
“狗桩效应”:缓存击穿后瞬时大量请求穿透到后端 DB,可能引发 DB 被打垮。
-
集群流量倾斜:在 Redis Cluster 中,Hot Key 只会落在某个特定 slot 对应的主节点,导致集群整体吞吐量被该节点极限卡住。
处理策略深度解析
| 策略 | 原理与实现 | 注意事项 |
|---|---|---|
| 本地缓存 | 在应用内存中(如 Caffeine、Guava Cache、HashMap)缓存 Hot Key 的数据,设置较短过期时间(秒级),配合 Redis 的 pub/sub 或主动失效通知来同步更新。 | 适用于读远大于写、数据一致性要求不高的场景;本地缓存需要防击穿(单机锁)。 |
| 读写分离 | 主节点处理写请求,从节点分担读请求。通过负载均衡将热点读请求分散到多个从节点。 | 从节点也可能成为新的 Hot Key 瓶颈(尤其当从节点数量不足时);写后读一致性会变弱。 |
| 分片(副本碎片化) | 1. 客户端分片:在 key 后加上随机后缀(如 hotkey_1、hotkey_2...hotkey_N),应用随机选择后缀读取,写入时同时更新所有副本。2. 代理分片:通过 Twemproxy/Predis 等代理进行一致性哈希。 |
写入成本高(需写 N 份),适合极高读 QPS、极低写频率的场景(如活动页浏览量)。 |
| 读写分离+副本随机 | Redis 6.0 开始支持 只读副本,客户端可设置 READONLY 模式,从多个从节点中随机选一个读取。 |
可与分片结合使用,进一步摊薄热点。 |
进阶方案:Redis 6.0 的客户端缓存(Client-side caching)
Redis 6.0 引入了 Tracking 机制,服务端主动通知客户端哪些 key 已失效,客户端本地缓存可自动失效,大幅减少网络传输和热点压力。
监控与发现手段
| 问题类型 | 推荐工具/命令 |
|---|---|
| Big Key 发现 | redis-cli --bigkeys(扫描)、MEMORY USAGE key、redis-rdb-tools(离线分析 RDB) |
| Hot Key 发现 | redis-cli --hotkeys(需要 LFU 策略)、MONITOR(随机采样,线上慎用)、FT.SEARCH 扩展、阿里云/腾讯云自带热点分析 |
持久化:
redis的RDB和AOF:
RDB:
快照持久化。原理:会在指定的时间间隔内将内存中的数据集以二进制的方式全量写入.rdb文件中
自动触发:通过save配置的频率,比如save 900 1(900s内至少1次修改则触发)
手动触发:执行bgsave(后台异步保存)或save(阻塞进程--不推荐)
执行流程:
- redis父进程执行fork()系统调用,创建一个子进程
- 子进程将当前内存中的数据写入一个.rdb的文件中
- 写入完成后,子进程用临时文件原子替换旧的rdb文件
- 关键点:fork()利用Linux的写时复制技术,父子进程共享一份物理内存页,只有当父进程或者子进程试图修改某页数据的时候才会复制该页,这使得bgsave在创建快照期间,不会阻塞主进程的读写操作,且内存开销可控。
优点:
- 性能高:持久化由子进程完成的,父进程只需处理fork()时的短暂阻塞,不影响主流程。
- 恢复快:RDB是紧凑的二进制文件,加载速度比AOF快得多,适合大规模数据恢复
- 体积小:经过压缩,文件体积通常小于AOF
缺点:
- 安全性能低:因为时定期快照,如果redis在两次快照中间宕机,这段时间的数据就丢失了
- fork()开销大:当数据集很大的时,fork本身会耗时较长,且可能引发内存占用瞬时翻倍
AOF:
原理:日志追加的方式,记录每个写操作命令,重启时通过重新执行这些操作命令来恢复数据
写入策略:
- always:每次由写命令时,立即同步到磁盘。最安全,但是性能最差
- everysec : 每秒同步一次,最多丢失数据1秒,性能与安全兼顾
- no: 由操作系统决定何时同步,性能最好,但是安全性最低
重写机制:
- 随着写操作增多,AOF文件会越来越大,redis通过重写来瘦身。
- 子进程读取当前内存中的数据,生成一个新的AOF文件
- 在重写期间父进程仍在处理写请求,这些新命令会同时写入旧AOF缓冲区和重写缓冲区
- 子进程重写完成后,父进程将重写缓冲区中的增量命令追加到新文件中
- 最后新文件原子替换旧文件
优点:
数据安全性高:可配置everysec最多丢失1秒数据,甚至always完全不丢失
可读性强:AOF是纯文本格式,即使数据损坏了,也容易人工修复或分析
自动修复:若AOF文件末尾损坏了,redis提供redis-check-oaf工具修复
缺点:
文件体积过大:即使经过重写,AOF文件页通常比RDB大
恢复速度慢:重启时需要重放所有命令,当AOF文件过大时恢复时长远高于RDB
性能影响:即使使用everysec,fsync操作仍可能带来一定的磁盘I/O压力
RDB VS AOF:
文件格式,数据完整性,恢复速度,执行效率,优缺点全方位对比

AOF重写:解决AOF文件过大的机制,通过读取当前内存状态生成最小命令集
同时开始RDB和AOF,重启时用那个恢复数据:优先使用AOF,数据更完整
最佳方案:
appendfsync everysec # AOF 每秒刷盘 aof-use-rdb-preamble yes # 混合持久化 save 900 1 # 保留 RDB 作为冷备 save 300 10 save 60 10000
redis的集群架构:
无中心化,哈希槽,节点间的gossip通信,重点解释数据如何分片存储的
集群中某个节点宕机了怎么处理:设计节点升级,集群可能进入fail状态
IO多路复用机制:select、poll、epoll的区别,redis是如何处理多个socket连接的
redis主从复制原理:
全量同步,增量同步,心跳机制
工作原理:从节点启动 → 配置replicaof → 连接主节点 → 发送PING → 认证 → 发送PSYNC
↓
主节点判断 → 全量复制(+FULLRESYNC)或 增量复制(+CONTINUE)
↓
全量复制: 主BGSAVE→发送RDB→从清空加载→发送缓冲命令→进入命令传播
增量复制: 主从Backlog中取缺失命令→发送→进入命令传播
↓
命令传播期间,主持续发送写命令,从发送REPLCONF ACK,主从通过心跳监控状态
哨兵模式:监控,选主,通知,解决主节点故障自动切换的问题
业务场景:
缓存:首页所需要的统计结果,比如某些商品的收藏数,点赞数,下单量等,排行榜等
排行榜(zSet)
如何保证数据库mysql和缓存redis的一致性?先更新数据库,在删除缓存,需要讨论延迟双删,binlog监听等并承认强一致性很难,通常追求最终一致性


浙公网安备 33010602011771号