redis zset结构在工作中你有哪些业务场景用到了?多说一些,排行榜之类就算了
2 个回答
在漆黑的夜里,你需要一道光照亮夜行的路,我燃烧了我自己,但也造就了你我不能相拥。奥斯卡除了常见的排行榜之外,工作中 Redis 的 ZSet(Sorted Set)在其他场景下也有丰富的应用,以下是我在实际业务中使用 Redis ZSet 的一些典型场景经验和实践: ### 一、任务延迟队列 - **业务场景:** - 延迟订单支付处理(如电商订单超时自动关闭)。 - 超时自动确认收货或自动评价。 **具体实现:** - 使用时间戳作为分数,任务或订单 ID 作为元素插入ZSet。 - 定期查询分数(即到期时间)小于当前时间的数据,取出后进行业务处理。 示例: ```bash ZADD order_timeout_queue <到期时间戳> orderId ``` ```java // Java实现示例 Set<String> timeoutOrders = redis.zrangeByScore("order_timeout", 0, System.currentTimeMillis()); ``` ### 1. 延迟消息队列(轻量级延时任务) 使用Redis ZSet实现延时消息或延时任务,取代复杂的延迟队列框架(如RocketMQ延迟消息)。 **场景举例:** - 电商系统延迟取消订单 - 短信验证码过期处理 - 异步任务延迟执行 **实现思路:** - `ZADD delay_queue timestamp orderId` - 后台定时轮询分数,取出到达执行时间的任务执行。 ### 2)流量或IP限流、风控系统限流场景 使用Redis ZSet实现滑动窗口限流,尤其适用于精确统计某时间段内用户的访问频率。 **具体场景:** - API接口防刷、验证码发送频率限制 - 用户登录次数或失败次数限制 **具体实现:** - 以访问的时间戳作为分数,每次用户请求时记录当前访问时间戳到ZSet中。 - 查询ZSet中最近一段时间内的访问记录数量,超过阈值时拒绝访问。 ```bash ZADD user:login:fail:userId 当前时间戳 唯一请求标识 ZREMRANGEBYSCORE key 0 当前时间戳-窗口期(如一分钟) ZCARD key # 计算请求次数,超过阈值则限流 ``` ### 事件历史记录(带时间排序) 用于需要保留精确时间序列事件记录的业务场景: **场景举例:** - 用户历史访问记录或操作记录(如最近浏览商品、用户浏览轨迹) - 用户行为日志,便于事后审计、分析 **实现方式:** - ZSet分数为时间戳,事件或记录ID为元素。 ```shell ZADD user:1001:actions 1710000001 "view:product:998877" ZADD user:1001:actions 1710000031 "add_cart:product:998877" ZRANGEBYSCORE user:1001:actions 1710000000 1710000100 ``` ### 定时任务调度管理系统 简单的定时任务执行器,支持快速增加、修改、取消定时任务。 **使用方法:** - ZSet 存储任务 ID 和任务执行的预定时间。 - 后台定时轮询 Redis,找到已到期任务立即执行。 ```shell ZADD scheduled_jobs 1710057600 "job:sync_orders" ``` ### 任务优先级队列 使用优先级值作为score值,分值低的任务先处理: ```shell ZADD task_priority 1 task_high_001 ZADD task_priority 5 task_low_002 # 消费端取任务 ZRANGEBYSCORE task_priority -inf +inf LIMIT 0 1 ``` ### 数据缓存自动过期(类似TTL但可控粒度更细) Redis 自带的过期机制粒度是键级的,有时需要更精细的业务过期策略: - 使用ZSet自行实现细粒度元素级别过期。 - 后台进程定时清理过期缓存数据。 如缓存某些高频查询的结果(非Redis自带过期): ```shell ZADD cache_expiry 1710057600 cacheKey001 ``` ### 分布式调度场景 分布式定时器或Job系统,每个任务调度精确到秒: - 使用ZSet记录每个任务下次执行时间。 - 每个节点从Redis中抢占执行权并更新任务下次执行时间。 ## 个人推荐的高效方案(根据经验优先级): | 场景 | 推荐程度 | 推荐原因 | |---------------------------|----------|-------------------------------------------| | 延时消息队列 | ⭐⭐⭐⭐⭐ | 简单高效,不依赖外部队列 | | 滑动窗口限流 | ⭐⭐⭐⭐⭐ | 性能高,精准控制用户行为 | | 时间序列事件记录 | ⭐⭐⭐⭐ | 存储有序事件记录,数据分析便利 | | 定时任务管理 | ⭐⭐⭐⭐ | 简单可靠,适合中小型项目 | | 元素级缓存过期 | ⭐⭐⭐⭐ | 细粒度控制缓存过期 |发布于 2025-03-06 16:49 •IP属地 广东举报评论收藏
不要和差点意思的人周旋。流月### 一、问题背景 Redis 自带的过期机制(TTL)只支持 **整个key** 的过期时间,而无法单独对 **一个key中的元素** 设置不同的过期时间。 举个例子: - 如果你用Hash结构存储多个用户的缓存数据: ```shell HSET user_cache user:1001 '{"name":"张三"}' HSET user_cache user:1002 '{"name":"李四"}' ``` 你对`user_cache`这个key只能设置一个统一的过期时间: ```shell EXPIRE user_cache 60 # 整个user_cache 60秒后过期 ``` **无法实现单个用户数据的单独过期时间,比如:** - 用户1001的数据只缓存5分钟; - 用户1002的数据缓存2分钟; - 用户1003的数据缓存10分钟。 用Redis默认的过期机制做不到这种 **更精细的缓存管理**。 ### 二、使用ZSet实现细粒度过期的方案 借助Redis的ZSet,可以实现 **元素级别的缓存过期**。 **核心思想:** - 用ZSet存储每个元素的过期时间(score = 过期时间戳)。 - 通过后台程序定时检查ZSet,清理过期的缓存数据。 具体步骤: **① 存入缓存:** - 将实际缓存数据存入Hash: ```shell HSET user_cache user:1001 '{"name":"张三"}' ``` - 在ZSet中记录该缓存的过期时间(假设5分钟后过期): ```shell ZADD user_cache_expiry 1710059200 "user:1001" ``` 这里的`1710059200`表示5分钟后的Unix时间戳。 **② 后台清理程序:** 后台程序(如Java、Python脚本等)定时运行: ```shell currentTimestamp = 当前时间戳 过期的元素 = ZRANGEBYSCORE user_cache_expiry 0 currentTimestamp ``` 得到所有过期的缓存元素后,从Hash中删除: ```shell HDEL user_cache user:1001 user:1002 ... ``` 最后再从ZSet中移除过期的标记: ```shell ZREM user_cache_expiry user:1001 user:1002 ... ``` ### 三、举一个完整例子(便于理解): 假如你缓存每个用户的最新查询数据,要求: - 用户A缓存3分钟 - 用户B缓存1分钟 - 用户C缓存5分钟 缓存过程: ```shell # 存储缓存数据 HSET query_cache user:A 'result for A' HSET query_cache user:B 'result for B' HSET query_cache user:C 'result for C' # 存储各自的过期时间戳 ZADD query_cache_expiry <当前时间戳+180秒> "user:A" ZADD query_cache_expiry <当前时间戳+60秒> "user:B" ZADD query_cache_expiry <当前时间戳+300秒> "user:C" ``` 后台清理过程(每分钟执行一次): ```shell current = 当前时间戳 expiredUsers = ZRANGEBYSCORE query_cache_expiry 0 current for user in expiredUsers: HDEL query_cache user # 删除缓存数据 ZREM query_cache_expiry user # 删除ZSet中的过期标记 ``` 这样,每个缓存元素就能实现自己的“TTL”,精确控制缓存生命周期。 ### 四、总结优势: - **精细粒度**:每个元素都有独立的过期时间。 - **灵活控制**:业务逻辑更清晰,满足复杂的业务需求。 - **节省空间**:自动过期,避免长期占用缓存空间。 这就是『使用ZSet自行实现细粒度元素级别过期』的完整含义和实现方式。发布于 2025-03-06 15:30 •IP属地 辽宁举报评论收藏
公众号进入网站体验更佳

