PS:创作不易,感谢阅读,希望对读者有所帮助,喜欢的话可以【关注】支持一下,作者会持续更新 Java 生态圈常见知识。黑色加粗为重点关注内容!
基本原理
- Zset
- 存储需要延迟处理的业务 ID
- 利用Zset排序特性,通过zadd添加元素,并设置分数为延迟时间
- 轮询比对分数与当前时间大小,获取超过当前时间的业务 ID
- Hash
- 存储业务 ID 对应的任务参数
- 取出业务 ID 对应的数据进行业务处理
实现过程
- 生产者
- 使用Zset的Zadd命令添加业务 ID 到Zset队列中
- 其中当前时间戳、业务 ID 分别作为ZSet的score和vlaue
- 同时,使用Hash的HMSET命令将业务数据添加到Hash队列中
- 其中业务ID、业务参数字符串分别作为Hash的field和value
- 消费者
- 开启一个轮询的线程
- 使用 ZSet 的 zrangeByScore 命令批量获取【小于等于】当前时间的业务 ID
- 使用 ZSet 的 ZRem 命令删除这一批业务 ID
- 使用 Hash 的 HMGET 获取业务 ID 所对应的业务数据
- 使用 Hash 的 HDEL 删除业务 ID 所对应的业务数据
- 推送业务数据至下游执行业务处理
- 注意:
- 弹出订单内容数据的同时进行数据删除,zrangeByScore、zrem、Hmget、Hdel 命令要在同一个 Lua 脚本中执行
- 如果数据处理失败则可能需要从数据库重新查询补偿
- 如果在数据处理完后才删除数据,需要并发控制,存在重复执行的可能性
数据结构
- Zset
- key:自定义消息池
- vlaue:业务 ID
- score:延迟的时间戳
- Hash
- field:业务ID
- value:业务相关参数
Zset命令
- zadd: 将一个或多个成员元素及其分数值加入到有序集当中
- zadd KEY SCORE VALUE
- zrangeByScore:返回有序集合中指定分数区间的成员列表
- zrangeByScore key min max [WITHSCORES] [LIMIT offset count]
- zrangeByScore(key, 0, System.currentTimeMillis(), 0, 10):查询距离当前时间,最早的10条任务进行消费
- zrem:移除有序集中的一个或多个成员,不存在的成员将被忽略
- zrem(key, id)
Hash命令
- Hmset:同时将多个field-value(字段-值)对设置到哈希表中
- HMSET KEY_NAME FIELD1 VALUE1 ...FIELDN VALUEN
- Hmget: 命令用于返回哈希表中,一个或多个给定字段的值。
- HMGET KEY_NAME FIELD1...FIELDN
- Hdel:删除哈希表key中的一个或多个指定字段,不存在的字段将被忽略。
- HDEL KEY_NAME FIELD1.. FIELDN
优势:
- Redis zset 支持高性能的排序
- Redis 是在内存上进行操作的,速度非常快。
- Redis 可以搭建集群,当消息很多时候,我们可以用集群来提高消息处理的速度,提高可用性。
- Redis 具有持久化机制,当出现故障的时候,可以通过 AOF 和 RDB 方式来对数据进行恢复,保证了数据的可靠性