12天 -- Redis 中如何保证缓存与数据库的数据一致性?Redis 中的缓存击穿、缓存穿透和缓存雪崩是什么?Redis String 类型的底层实现是什么?(SDS)

Redis 中如何保证缓存与数据库的数据一致性?

1. Cache Aside(旁路缓存模式)

  • 读操作:先查询缓存,如果缓存命中则返回数据;若缓存未命中,则从数据库读取数据,并将数据写入缓存。
  • 写操作:先更新数据库,再删除缓存,确保缓存中的数据无效化。

优化方法:引入分布式锁避免并发读写冲突,配合延时双删进一步保障缓存一致性。

2. Read-Through(直读缓存模式)

  • 读操作:若缓存命中,直接返回数据;若缓存未命中,缓存系统从数据库加载数据并返回,同时更新缓存。
  • 写操作:同时更新缓存和数据库,确保两者一致。

优化方法:增加缓存操作的重试机制,引入消息队列确保缓存更新的可靠性。

3. Write-Through(直写缓存模式)

  • 写操作:所有写操作直接更新缓存,同时缓存负责同步更新数据库;所有读操作都通过缓存获取数据。

优化方法:引入分布式事务确保缓存和数据库更新的原子性,将失败的写操作记录到队列中稍后重试。

4. 双写策略

  • 写操作:同时更新数据库和缓存,读操作仅从缓存获取数据。

优化方法:为缓存更新和数据库写入增加事务机制,增加幂等性校验避免缓存重复更新。

5. 延时双删策略

  • 写操作:先删除缓存,更新数据库后,等待一定时间,再次删除缓存,确保一致性。

6. 异步消息队列同步

写操作:更新数据库后,通过消息队列发送事件通知缓存服务,异步更新或删除缓存,实现最终一致性。

优化方法:配置消息队列的持久化和重试机制,确保消息不会丢失,使用延迟队列重新尝试更新缓存。

7. Binlog 同步

  • 原理:利用数据库 Binlog 捕获增量数据变更,实时同步缓存数据,确保缓存与数据库的一致性。

优化方法:提高 Binlog 同步的实时性,使用高性能的消息传输协议减少延迟。

8. 设置缓存过期时间

  • 兜底方案:为 Redis 中的缓存数据设置合理的 TTL(如 30 分钟),最终强制重新加载最新数据。

9. 引入分布式锁

  • 读写锁控制:在业务层对同一数据加分布式锁,确保读写顺序性。

10. 版本号或时间戳

  • 版本号校验:在缓存和数据库中存储数据的版本号,更新时校验版本,确保数据一致性。

通过以上策略,可以根据具体的业务需求和系统架构选择合适的方案来保证 Redis 缓存与数据库的数据一致性。

Redis 中的缓存击穿、缓存穿透和缓存雪崩是什么?

1. 缓存击穿

概念

  • 指缓存中某个热点数据(频繁被访问的数据)突然过期,此时大量请求同一时间通过缓存直击数据库,导致数据库压力骤增,甚至可能崩溃。
  • 原因
  • 缓存的过期时间设置不合理,导致热点数据和缓存过期时间集中在同一时刻。
  • 高并发场景下,大量请求几乎同时到达,访问同一缓存数据。

2. 缓存穿透

概念

  • 指客户端请求的数据在缓存和数据库中都不存在,导致所有请求都直接穿透到数据库进行查询,增加了数据库的压力。
  • 原因
  • 请求携带非法参数,例如黑客故意构造不存在的 ID 请求。
  • 系统中存在大量不存在或无效的查询。

3. 缓存雪崩

概念

  • 指缓存中大量数据在短时间内同时失效,导致大量的请求在极短时间内直接访问数据库,数据库因瞬时压力过大而崩溃。
  • 原因
  • 缓存服务器突然宕机,导致所有缓存数据丢失。
  • 缓存数据的过期时间设置得过于集中,导致多个缓存数据同时过期。

Redis String 类型的底层实现是什么?(SDS)

SDS 的结构

SDS 是 Redis 用于表示字符串的底层数据结构,它由以下部分组成:

  • len:记录字符串的实际长度(不包括结尾的 \0)。
  • alloc:记录分配的总空间(不包括头部和结尾的 \0)。
  • flags:标志位,用于标识 SDS 的类型(如 SDS_TYPE_8SDS_TYPE_16 等)。
  • buf:存储字符串内容的动态数组,末尾会自动添加 \0,以兼容 C 语言的字符串函数。

SDS 的编码类型

SDS 有三种编码类型:

embstr:占用 64 Bytes 的空间,存储 44 Bytes 的数据。embstr 结构存储小于等于 44 个字节的字符串,其内存结构是字符串 SDS 结构体与其对应的 redisObject 对象分配在同一块连续的内存空间。

raw:存储大于 44 Bytes 的数据。此时,动态字符串 SDS 的内存与其依赖的 redisObject 的内存不在连续。

int:存储整数类型。如果存储的是整数,Redis 会直接使用整数类型存储,而不是字符串。

SDS 的优点

SDS 相比传统的 C 语言字符串(char*)具有以下优点:

  • 常数复杂度获取字符串长度:通过 len 属性可以直接获取字符串长度,时间复杂度为 O(1)。
  • 避免缓冲区溢出:通过 alloc 属性记录分配的总空间,可以有效避免缓冲区溢出。
  • 减少内存重分配次数:SDS 通过预分配空间的方式,减少了内存重分配的次数。
  • 二进制安全:SDS 不依赖于字符串中的 \0 来判断字符串是否结束,因此可以存储任意二进制数据。
  • 兼容 C 语言字符串函数:SDS 的末尾会自动添加 \0,因此可以兼容 C 语言的字符串函数。

SDS 的操作

Redis 提供了一系列函数来操作 SDS,例如:

  • 创建 SDSsdsnewsdsempty
  • 追加字符串sdscat
  • 复制字符串sdscpy
  • 释放 SDSsdsfree
  • 获取长度sdslen
  • 获取剩余空间sdsavail

通过 SDS,Redis 的 String 类型实现了高效、安全和灵活的字符串存储和操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值