Redis 实践指南与核心概念
一、Java 中常用的 Redis 使用场景与实践
-
缓存(Caching)
-
场景:热点数据、频繁访问的数据,如商品详情、用户信息。通过缓存减少数据库压力,提高系统响应速度。
-
工业界实践 :
- 淘宝/天猫:商品详情页、用户会话、购物车等核心数据大量使用 Redis 缓存,通过多级缓存(CDN -> Nginx/OpenResty Lua -> 本地缓存 -> Redis Cluster -> DB)分担流量,降低数据库压力。秒杀场景下,利用 Redis 预热库存、扣减库存,并通过 Lua 脚本保证原子性。
- 美团:大规模 KV 存储服务(如 Squirrel 内存 KV、Cellar 持久化 KV)承载万亿级请求,保持高可用性,广泛应用于团购、外卖等业务的核心数据缓存 。
- 拼多多/字节跳动:类似电商、内容推荐等场景,也大量使用 Redis 作为缓存层,优化数据读取性能,支撑高并发访问。
-
实现:在 Java 中,通常使用 Spring Cache、Redisson 或 Jedis 等客户端。Spring Cache 提供了声明式缓存支持,通过注解即可实现。
-
示例 :
java@Service public class ProductService { @Autowired private RedisTemplate<String, Object> redisTemplate; @Cacheable(value = "products", key = "#productId", unless = "#result == null") public void getProductById(Long productId) { } } ```
-
配置与引用 :
-
Maven 依赖 :引入
spring-boot-starter-data-redis
和spring-boot-starter-cache
。 -
application.properties
配置 :propertiesspring.redis.host=localhost spring.redis.port=6379 spring.redis.password= spring.redis.database=0 spring.redis.timeout=5000ms spring.cache.type=redis # 配置缓存的默认过期时间(例如:1小时) spring.cache.redis.time-to-live=3600000
-
Key 命名规范 :工业界通常会采用
业务域:业务类型:唯一标识
的方式,例如product:detail:123
,user:info:abc
。这有助于管理和排查问题。 -
过期时间:根据数据热度、一致性要求设置。对于强一致性要求不高的数据,可以设置较长过期时间;对于实时性要求高的数据,过期时间应短,或配合消息队列进行主动失效。
-
-
-
分布式锁(Distributed Locks)
-
场景:在分布式系统中,确保同一时间只有一个服务实例能执行特定代码块,防止并发问题,如秒杀系统库存扣减、防止重复提交订单。
-
工业界实践 :
- 电商平台(淘宝、拼多多):在秒杀、抢购等高并发场景下,广泛使用 Redis 分布式锁来控制库存的原子性扣减,防止超卖。通常会结合 Lua 脚本保证操作的原子性,并利用 Redisson 等框架提供的看门狗机制自动续期,避免死锁。
- 美团/滴滴:在订单处理、支付、优惠券发放等核心业务流程中,使用分布式锁来保证数据一致性,避免重复操作或并发冲突。
-
实现 :基于 Redis 的
SETNX
命令(或SET key value NX EX
)实现。工业界常用 Redisson 框架,它提供了更高级的锁功能,如可重入锁、公平锁、看门狗机制(自动续期)。 -
示例 :
java@Autowired private RedissonClient redissonClient; public void processOrder(String orderId) { RLock lock = redissonClient.getLock("order_lock:" + orderId); try { // 尝试获取锁,等待10秒,锁自动释放5秒(看门狗默认30秒,这里是手动设置) if (lock.tryLock(10, 5, TimeUnit.SECONDS)) // 业务逻辑:处理订单,例如扣减库存、创建订单记录 } } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("Order processing interrupted for " + orderId + ": " + e.getMessage()); } finally { // 确保锁被当前线程持有才释放,防止误删 if (lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); } } }
-
避坑指南 :
- 必须设置过期时间:防止因服务宕机导致死锁。
- 使用唯一标识:避免误删其他线程的锁。
- 任务执行时间 < 锁超时时间:避免业务未完成锁已释放,导致并发问题。Redisson 的看门狗机制可以自动续期,缓解此问题。
-
-
消息队列(Message Queue)
-
场景:异步处理、服务解耦、流量削峰填谷,如订单支付成功后的后续处理(发货、积分)、日志收集、数据同步。
-
工业界实践 :
- 美团/饿了么:在订单状态变更、配送信息更新、用户消息通知等场景,利用 Redis 作为轻量级消息队列,实现服务间的异步通信和解耦。
- 字节跳动/快手:在短视频、直播等场景,利用 Redis Stream 存储用户行为日志、点赞、评论等实时数据,进行实时处理和分析。
- 电商平台:用于处理用户下单后的异步操作,如库存扣减、积分发放、短信通知等,避免阻塞主流程。
-
实现 :利用 Redis 的 List(
LPUSH
/BRPOP
)或 Stream 数据结构。List 简单易用,适合简单的队列;Stream 功能更强大,支持消费者组、消息持久化等,更适合复杂的 MQ 场景。 -
示例(List 实现简单队列) :
java@Autowired private StringRedisTemplate redisTemplate; public void sendMessage(String queueName, String message) { redisTemplate.opsForList().leftPush(queueName, message); // 生产者:从左侧入队 } public String receiveMessage(String queueName) { // 消费者:阻塞式从右侧出队,等待0秒表示一直阻塞直到有消息 String message = redisTemplate.opsForList().rightPop(queueName, 0, TimeUnit.SECONDS); return message; }
-
-
计数器/排行榜(Counters/Leaderboards)
- 场景:实时统计网站访问量、文章点赞数、商品销量、游戏积分榜、用户活跃度。
二、Redis 核心原理与面试要点
-
为什么 Redis 这么快?
- 基于内存:所有数据都存储在内存中,避免了磁盘 I/O 的开销。
- 单线程模型:Redis 内部使用单线程处理所有请求,避免了多线程的上下文切换开销和锁竞争问题。虽然是单线程,但 Redis 采用了 I/O 多路复用技术(如 epoll、kqueue),可以在一个线程中同时监听多个 socket 连接,实现高并发。
- 高效的数据结构:Redis 内部实现了多种高效的数据结构,如跳跃表(Skip List)、压缩列表(Zip List)、哈希表(Hash Table)等,针对不同的数据类型进行了优化,使得操作效率极高。
- 非阻塞 I/O:使用 I/O 多路复用,避免了传统阻塞 I/O 的等待。
- C 语言实现:C 语言的执行效率高,且对内存控制更精细。
-
Redis 的主要数据结构及应用场景
- String(字符串) :最基本的数据类型,可以存储字符串、整数或浮点数。常用于缓存、计数器、分布式锁(配合
SETNX
)。- 底层实现 :SDS(Simple Dynamic String),类似于 C++ 的
std::string
,支持动态扩容,减少内存重新分配次数,并记录长度,获取字符串长度为 O(1)。
- 底层实现 :SDS(Simple Dynamic String),类似于 C++ 的
- Hash(哈希) :键值对集合,适合存储对象。常用于存储用户信息、商品信息等。
- 底层实现 :当哈希的键值对数量较少且键值长度较小时,使用
ziplist
(压缩列表)存储,节省内存;否则使用hashtable
(哈希表)。
- 底层实现 :当哈希的键值对数量较少且键值长度较小时,使用
- List(列表) :有序的字符串列表,可以从两端进行插入和删除。常用于消息队列、最新消息列表。
- 底层实现 :Redis 3.2 之前使用
ziplist
和linkedlist
,之后统一使用quicklist
,它是一个双向链表,每个节点是一个ziplist
,兼顾了内存效率和操作性能。
- 底层实现 :Redis 3.2 之前使用
- Set(集合) :无序的字符串集合,元素唯一。常用于存储共同关注、抽奖活动、标签。
- 底层实现 :当集合中元素都是整数且数量较少时,使用
intset
(整数集合)存储,节省内存;否则使用hashtable
。
- 底层实现 :当集合中元素都是整数且数量较少时,使用
- ZSet(有序集合) :有序的字符串集合,每个元素关联一个分数,通过分数进行排序。常用于排行榜、带权重的任务队列。
- 底层实现 :当有序集合中元素数量较少且元素长度较小时,使用
ziplist
存储;否则使用skiplist
(跳跃表)和hashtable
的组合,跳跃表用于快速查找和范围查询,哈希表用于 O(1) 时间复杂度获取元素分数。
- 底层实现 :当有序集合中元素数量较少且元素长度较小时,使用
- Geospatial(地理空间):存储地理位置信息,可以计算两点距离、查找附近的人/地点。底层基于 ZSet 实现。
- HyperLogLog:用于基数统计(不重复元素的数量),例如统计网站 UV。允许一定误差,但内存占用极小。
- Stream:Redis 5.0 引入的新的数据结构,类似于 Kafka,支持多消费者组、消息持久化、消息回溯等。适用于消息队列、事件日志。
- String(字符串) :最基本的数据类型,可以存储字符串、整数或浮点数。常用于缓存、计数器、分布式锁(配合
-
Redis 持久化机制
- RDB(Redis Database):快照持久化,在指定时间间隔内将内存中的数据集快照写入磁盘。优点是恢复速度快,适合备份;缺点是可能丢失最后一次快照之后的数据。
- AOF(Append Only File):增量持久化,记录 Redis 执行的每个写命令。优点是数据完整性高,丢失数据少;缺点是文件可能较大,恢复速度相对 RDB 慢。
- 混合持久化(Redis 4.0+):RDB 和 AOF 的结合,启动时加载 RDB 文件,再重放 AOF 文件中 RDB 快照之后的操作,兼顾了恢复速度和数据完整性。
-
Redis 淘汰策略(内存满了怎么办?)
- 当 Redis 内存达到上限时,会根据配置的淘汰策略来删除键。
noeviction
:默认策略,不删除任何键,写操作会报错。allkeys-lru
:从所有键中选择最近最少使用的键进行淘汰。volatile-lru
:从设置了过期时间的键中选择最近最少使用的键进行淘汰。allkeys-random
:从所有键中随机淘汰。volatile-random
:从设置了过期时间的键中随机淘汰。allkeys-ttl
:从所有键中选择即将过期的键进行淘汰。volatile-ttl
:从设置了过期时间的键中选择即将过期的键进行淘汰。
-
Redis 事务
- Redis 事务通过
MULTI
、EXEC
、DISCARD
、WATCH
命令实现。 MULTI
:开启事务,后续命令入队。EXEC
:执行所有入队命令。DISCARD
:取消事务,清空命令队列。WATCH
:监视一个或多个键,如果在事务执行前这些键被其他客户端修改,则事务会被打断(乐观锁)。- 特点:Redis 事务是原子性的(要么都执行,要么都不执行),但不支持回滚(命令入队时检查语法错误,执行时即使出错也不会回滚)。
- Redis 事务通过
-
Redis 主从复制
- 目的:实现数据冗余、读写分离、故障恢复。
- 原理:主节点负责写操作,从节点负责读操作。主节点将写命令同步给从节点。
- 全量复制:当从节点第一次连接主节点或断线重连后,主节点会生成 RDB 文件发送给从节点,从节点加载 RDB 文件。
- 增量复制:主从节点都维护一个复制偏移量和复制积压缓冲区,主节点将新的写命令发送给从节点。
-
Redis Sentinel(哨兵)
- 目的:解决主从复制的自动故障转移问题,实现高可用。
- 功能:监控 Redis 主从节点状态、自动故障转移(当主节点宕机时,从节点中选举新的主节点)、通知客户端新的主节点地址。
- 部署:通常部署多个 Sentinel 实例,形成 Sentinel 集群,通过投票机制决定是否进行故障转移。
-
Redis Cluster(集群)
- 目的:解决单机 Redis 的容量和并发瓶颈,实现分布式存储和高可用。
- 分片:Redis Cluster 采用哈希槽(Hash Slot)的方式进行数据分片,共有 16384 个哈希槽,每个键通过 CRC16 算法计算哈希值,然后对 16384 取模,决定分配到哪个槽。
- 节点:每个节点负责一部分哈希槽,节点之间通过 Gossip 协议进行通信,维护集群状态。
- 高可用:每个主节点可以有多个从节点,当主节点宕机时,从节点可以自动晋升为主节点。
- 扩容与缩容:支持在线扩容和缩容,通过迁移哈希槽实现。
-
缓存穿透、缓存击穿、缓存雪崩
- 缓存穿透 :查询一个不存在的数据,导致每次请求都打到数据库。解决方案:布隆过滤器、缓存空对象。
- 缓存击穿 :某个热点数据过期,大量请求同时打到数据库。解决方案:设置热点数据永不过期、加分布式锁。
- 缓存雪崩 :大量缓存同时失效,导致所有请求都打到数据库。解决方案:缓存过期时间错开、多级缓存、熔断降级。
-
Redis 为什么没有替代品?
-
性能卓越:在内存数据库领域,Redis 的性能表现非常突出,能够满足绝大多数高并发场景的需求。
-
功能丰富:除了基本的键值存储,还提供了丰富的数据结构和功能(如发布订阅、事务、Lua 脚本等),能够应对多种复杂业务场景。
-
生态成熟:拥有庞大的社区支持、丰富的客户端库和完善的周边工具,易于集成和使用。
-
简单易用:API 简洁明了,学习成本低,部署和维护相对简单。
-
高可用和扩展性:通过主从复制、Sentinel、Cluster 等机制,提供了完善的高可用和横向扩展解决方案。
-
应用广泛:在互联网行业得到了广泛应用,积累了大量的实践经验和解决方案。
-
工业界实践:
- 新闻/内容推荐平台(字节跳动、腾讯新闻):实时统计文章阅读量、点赞数、评论数,并根据这些指标生成热门文章排行榜。
- 电商平台(淘宝、京东):实时更新商品销量、评价数,并用于生成商品热销榜、好评榜。
- 游戏公司:实时更新玩家积分、排名,用于游戏排行榜。
-
实现 :使用 String 的
INCR
/DECR
命令实现简单计数;使用 Sorted Set(ZSet)实现排行榜,ZSet 能够根据分数自动排序。 -
示例(ZSet 实现排行榜):
java@Autowired private StringRedisTemplate redisTemplate; public void updateScore(String userId, double score) { redisTemplate.opsForZSet().add("game_leaderboard", userId, score); } public Set<ZSetOperations.TypedTuple<String>> getTopPlayers(long count) { // 获取分数从高到低的前N名玩家 Set<ZSetOperations.TypedTuple<String>> topPlayers = redisTemplate.opsForZSet().reverseRangeWithScores("game_leaderboard", 0, count - 1); return topPlayers; }
-
-
Session 共享(Session Sharing)
-
场景:分布式部署的 Web 应用(如微服务架构),用户登录后 Session 需要在不同服务实例间共享,以实现无状态服务。
-
工业界实践 :
- 大型互联网公司:几乎所有大型分布式 Web 应用都会将用户 Session 存储在 Redis 中,以实现 Session 共享和高可用。这使得用户在访问不同服务实例时,无需重新登录,提升用户体验。
- 微服务架构:在微服务体系中,Session 共享是实现无状态服务的重要一环,Redis 作为高性能的内存数据库,是理想的 Session 存储方案。
-
实现:将 Session 存储到 Redis 中。Spring Session Redis 提供了开箱即用的解决方案,无需手动管理 Session 的存取。
-
配置示例(Spring Boot) :
properties# application.properties spring.session.store-type=redis spring.redis.host=localhost spring.redis.port=6379 # ... 其他 Redis 配置
-
-
布隆过滤器(Bloom Filter)
-
场景:判断一个元素是否存在于一个大规模集合中,允许一定的误判率,但绝不允许漏判。常用于防止缓存穿透(查询不存在的数据导致数据库压力)、垃圾邮件过滤、用户黑名单。
-
工业界实践 :
- 新闻/内容推荐平台(字节跳动):用于判断用户是否已读某篇文章,避免重复推荐;或用于过滤垃圾评论、敏感词。
- 电商平台(淘宝、拼多多):在防止缓存穿透方面发挥重要作用,预先判断商品 ID、用户 ID 等是否存在,减少对数据库的无效查询。
- 美团/滴滴:在黑名单过滤、防止恶意请求等方面有应用。
-
实现:Redis Modules 提供了布隆过滤器功能(如 RedisBloom),Java 客户端如 Redisson 可以集成。
-
示例 :
java// 假设使用 Redisson 的 RBloomFilter @Autowired private RedissonClient redissonClient; public void checkAndAddUser(String userId) { RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("user_exists_filter"); // 初始化布隆过滤器,预计插入1000万个元素,误判率1% (m=10000000, fpp=0.01) // 实际生产中,这些参数应根据业务需求精确计算 if (!bloomFilter.isInitialized()) { bloomFilter.tryInit(10000000L, 0.01); } if (!bloomFilter.contains(userId)) { // 布隆过滤器说不存在,则一定不存在。执行业务逻辑并添加到布隆过滤器 bloomFilter.add(userId); // 实际业务:查询数据库,如果存在则添加到缓存,如果不存在则缓存空值 } else { // 布隆过滤器说可能存在,则可能存在(有误判率)。继续查询缓存或数据库 } }
-
三、缓存一致性解决方案
<math xmlns="http://www.w3.org/1998/Math/MathML"> 缓存策略 = 写入策略 × 失效策略 缓存策略 = 写入策略 \times 失效策略 </math>缓存策略=写入策略×失效策略
常用模式:
-
Cache-Aside(旁路缓存)
- 读流程 :
$ \text{先读缓存} \rightarrow \text{缓存未命中} \rightarrow \text{读DB} \rightarrow \text{回填缓存} $
- 写流程 :
$ \text{先更新DB} \rightarrow \text{再删除缓存} $
- 工业界实践:这是最常用的模式,简单有效。删除缓存而非更新缓存是为了避免并发写导致的数据不一致问题(例如,线程A更新DB后更新缓存,线程B在线程A更新DB后、更新缓存前更新DB并更新缓存,导致缓存中是旧数据)。
- 读流程 :
-
Write-Through(直写缓存)
- 所有写操作同时更新缓存和DB。
- 工业界实践:通常用于对数据一致性要求极高,且写操作不频繁的场景。性能开销较大,因为每次写都要同步更新两个存储。
-
Write-Behind(回写缓存)
- 写操作只更新缓存,然后异步地将数据回写到DB。
- 工业界实践:性能最高,但数据一致性风险最大,因为数据可能只存在于缓存中,尚未写入DB。适用于对数据丢失不敏感的场景,如日志、计数器。
数据同步公式:
<math xmlns="http://www.w3.org/1998/Math/MathML"> T c o n s i s t e n c y = max ( T d b _ w r i t e , T c a c h e _ i n v a l i d ) + δ n e t w o r k T_{consistency} = \max(T_{db\write}, T{cache\invalid}) + \delta{network} </math>Tconsistency=max(Tdb_write,Tcache_invalid)+δnetwork
四、常见问题解决清单与工业界应对
问题类型 | 现象 | 解决方案 | 工业界应对 |
---|---|---|---|
缓存雪崩 | 大量 Key 同时失效,导致大量请求直接打到数据库,使数据库宕机。 | 1. 随机过期时间 :在原有过期时间上增加随机值,使 Key 分散失效。 2. 多级缓存 :引入本地缓存或二级缓存。 3. 熔断降级:当 Redis 不可用时,直接返回默认值或错误,保护数据库。 | 工业界实践:大型互联网公司通常会结合随机过期、多级缓存(如 Guava Cache/Caffeine)、服务熔断(Hystrix/Sentinel)等手段。对于重要数据,有时会设置永不过期,通过消息队列或定时任务主动更新。 |
缓存穿透 | 查询不存在的数据,缓存不命中,导致每次请求都穿透到数据库,造成数据库压力。 | 1. 布隆过滤器 :预先存储所有可能存在的 Key,查询前先通过布隆过滤器判断 Key 是否存在。 2. 缓存空值:对于查询结果为空的数据,也将其缓存起来,并设置较短的过期时间。 | 工业界实践:广泛使用布隆过滤器进行第一层过滤,结合缓存空值策略,有效拦截恶意攻击和无效查询。 |
热 Key 问题 | 单个 Key 访问量过大,导致 Redis 某个节点(或单机 Redis)的 CPU 或网络带宽成为瓶颈。 | 1. 本地缓存 :在应用层增加本地缓存(如 Caffeine),减少对 Redis 的访问。 2. Key 分片 :将热 Key 分散到多个 Key 上,例如 hotkey:1 , hotkey:2 ,通过哈希等方式访问。 3. 读写分离:对于读多写少的场景,可以考虑将热 Key 的读请求分发到多个 Redis 从节点。 |
工业界实践:大型互联网公司通常会结合本地缓存、Key 分片(如将商品库存拆分为多个 Key)、以及 Redis 集群的读写分离能力来应对。对于极热 Key,甚至会考虑在 CDN 层进行缓存。 |
大 Key 问题 | 单个 Value 过大(例如超过 1MB),导致网络传输开销大、Redis 内存碎片化、主从复制延迟、AOF/RDB 持久化效率低。 | 1. 数据拆分 :将大 Value 拆分为多个小 Key-Value 存储 。 2. 压缩存储 :对 Value 进行压缩后再存储 。 3. 选择合适的数据结构:例如,使用 Hash 存储对象,而不是将整个 JSON 字符串作为 String 存储 。 | 工业界实践:普遍严格限制 Key 的大小(例如,建议不超过 10KB,最大不超过 512MB,但实际开发中应远小于此) 2">2< 。通过代码规范、Lint 工具、以及 Redis 监控系统进行检测和治理 。对于不可避免的大 Key,会进行拆分或压缩 。 |
Key 过期时间 | Key 的存活时长设置不合理,导致数据提前失效或长期占用内存。 | 根据业务场景和数据特性合理设置过期时间。对于需要长期存在的 Key,可以设置为永不过期,并通过业务逻辑或消息队列进行主动更新/删除。 | 工业界实践:很多公司会强制要求 Key 的最大存活时长(例如 1天、7天),防止 Key 长期占用内存或因业务逻辑错误导致 Key 无法删除。对于特殊场景,需要申请白名单。 |
五、Redis 核心数据结构
-
基础类型
- 字符串(String) :最基本的数据类型,可以存储字符串、整数或浮点数。支持位操作(Bitmap)。
- 命令示例 :
SET key value
,GET key
,INCR key
,DECR key
,GETBIT key offset
,SETBIT key offset value
- 命令示例 :
- 哈希(Hash) :存储键值对的集合,适合存储对象。一个 Hash 可以存储多个字段和值。
- 命令示例 :
HSET user:1 name "Alice" age 30
,HGET user:1 name
,HGETALL user:1
- 命令示例 :
- 列表(List) :有序的字符串列表,底层是双向链表实现。可以作为队列或栈使用。
- 命令示例 :
LPUSH queue task1 task2
,RPUSH queue task3
,LPOP queue
,RPOP queue
,LRANGE queue 0 -1
- 命令示例 :
- 集合(Set) :无序的字符串集合,元素唯一。支持集合间的操作,如交集、并集、差集。
- 命令示例 :
SADD tags redis mysql
,SMEMBERS tags
,SISMEMBER tags redis
,SINTER set1 set2
- 命令示例 :
- 有序集合(ZSet) :Set 的一个扩展,每个成员都关联一个分数(score),通过分数进行排序。适用于排行榜、带权重的队列。
- 命令示例 :
ZADD leaderboard 100 user1 90 user2
,ZRANGE leaderboard 0 -1 WITHSCORES
,ZSCORE leaderboard user1
- 命令示例 :
- 字符串(String) :最基本的数据类型,可以存储字符串、整数或浮点数。支持位操作(Bitmap)。
-
高级结构
- 位图(Bitmap) :实际上是 String 类型,通过位操作实现。常用于统计用户活跃度、签到等。
- 命令示例 :
SETBIT login:20231101 100 1
(表示用户ID 100在2023年11月1日活跃)
- 命令示例 :
- HyperLogLog :用于基数估算(统计独立元素的数量),允许有少量误差,但内存占用极小。适用于统计 UV、独立访客数等。
- 命令示例 :
PFADD ip_20231101 192.168.1.1 192.168.1.2
,PFCOUNT ip_20231101
- 命令示例 :
- 地理空间(GEO) :存储地理位置信息(经度、纬度),并支持计算距离、查找附近的人/地点。
- 命令示例 :
GEOADD cities 116.40 39.90 Beijing
,GEODIST cities Beijing Shanghai
,GEORADIUS cities Beijing 100 km
- 命令示例 :
- 流(Stream) :Redis 5.0 引入的全新数据结构,类似于 Kafka,支持多生产者、多消费者、消费者组、消息持久化等。适用于构建消息队列、事件溯源等。
- 命令示例 :
XADD orders * product_id 1001 user_id 200
,XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS orders >
- 命令示例 :
- 位图(Bitmap) :实际上是 String 类型,通过位操作实现。常用于统计用户活跃度、签到等。
六、Redis 新特性解析
-
Redis 7.0 Multi-Part AOF
- 特性 :将 AOF 文件分割为多个片段(如
appendonly.1.aof
,appendonly.2.aof
),而不是一个巨大的文件。 - 优势 :
- 文件大小控制:单个 AOF 文件不会无限增长,便于管理。
- 重写效率提升:增量式重写替代全量重写,减少重写时的阻塞时间。
- 故障恢复加速:只需加载损坏的片段,而不是整个 AOF 文件,提高恢复速度。
- 特性 :将 AOF 文件分割为多个片段(如
-
Redis 8.0 布隆过滤器(原生支持)
-
特性:Redis 8.0 计划原生支持布隆过滤器,无需通过 Redis Modules。
-
优势:更低的部署和使用成本,更好的性能和稳定性。
-
与模块版对比 :
参数 模块版(RedisBloom) 原生实现(Redis 8.0) 内存占用 可变 固定预分配 误判率 可配置 默认 0.1%(可能可配置) 集群支持 需同步 自动同步
-
七、思维导图框架
八、开源项目设计(todo)
项目名:Redis-Solution-Kit
目录结构:
bash
├── distributed_lock
│ ├── redlock.py # Redlock实现
│ └── test_deadlock.py
├── cache_consistency
│ ├── double_delete.py # 双删策略
│ └── binlog_sync.py # 基于MySQL binlog同步
├── bloom_filter
│ ├── redis8_native.py # 原生布隆过滤器
│ └── scaling_bf.py # 动态扩容实现
└── disaster_recovery
├── avalanche.py # 雪崩防护
└── penetration.py # 穿透防护