有一个 Redis 通知的问题想问一下大家

2022-07-11 20:05:20 +08:00
 JoseGuo
最近需要做一个订单超时未支付自动取消的功能
研究一下方案后,暂时决定用监听 Redis 失效 Key 来实现
简单测试了一下可以用,但有一个小问题
网络搜的实现过程 第一步大部分都是打开 redis.conf 里的键事件的通知
即这样设置 notify-keyspace-events Ex
但是我没按这个来 默认的设置没改动 仍然可用
即 notify-keyspace-events ""
有没有大佬可以解释一下这种情况
感谢
5651 次点击
所在节点    Redis
57 条回复
flashBee233
2022-07-12 10:03:11 +08:00
37 楼的 2 )思路也可以 ,比如规定的是超过 30 分钟未支付订单超时,10:00 下单 10:30 超时 前端检测当前时间是否超过 10:30 且是未完成的订单,但这又依赖前端的请求前端不打开这个页面就不会执行这个操作
jucelin
2022-07-12 10:05:37 +08:00
定时扫,业务上也配合判定下时间
JoseGuo
2022-07-12 10:08:21 +08:00
破案了 确实现在开启的配置是 notify-keyspace-events AE 并不是""
asmoker
2022-07-12 10:37:45 +08:00
@JoseGuo Ex 就够了吧
bthulu
2022-07-12 11:20:24 +08:00
@qinxi 更冷的知识, 一分钟数据量有没有可能会把内存撑爆呢? 比如日志类的, 每条数据算 10k, 每秒一千人访问, 每人 10 条日志, 就是 100M. 一分钟就是 6G.
nekoneko
2022-07-12 11:27:01 +08:00
体量不大的话
1. 时间轮
2. 定时任务
3. 延时队列
fifa899
2022-07-12 11:28:13 +08:00
MQ 队列.延迟消费才是正解.redis 都用了.广播通知,延迟消息还是交给 MQ 比较专业
qinxi
2022-07-12 11:35:05 +08:00
@bthulu #45 1 分钟的订单能把内存撑爆 还来这问解决方案?
10 秒行不行?
日志需要延迟队列?
ccppgo
2022-07-12 11:41:52 +08:00
订单过期时间 + 定时任务才是正解吧 复杂度最低
qinxi
2022-07-12 11:48:10 +08:00
@bthulu #45 你要是非得来杠, 即使每分钟 10 万订单这种方式也可以解决, 思路就是缩短时间 10s 15s 30s 根据情况来.
你已经每分钟 10 万订单了开 50 台机器处理不过分吧? 你算算我现在每台机器多少数据呢?
这种问题需要处理数据分配而已. 分发节点负责把 10 万的 id 分发给 50 个节点不复杂吧?
lesismal
2022-07-12 12:20:42 +08:00
redis 通知是存在的问题,比如通知的瞬间,刚好你监听事件的这个服务与 redis 断线了、没收到通知。
时间+定时任务判断处理订单状态就行了。

这里的时间与隔壁帖子根据当前时间计算当前体力、而不是定时去计算更新增加后的体力的玩法其实是类似的。
可以考虑记下这个词:COW(copy on write),其实本质就是只在真正需要的时候才去触发实际操作、尽量减少成本的浪费。
liudaolunhuibl
2022-07-12 13:50:37 +08:00
redis 的这个 key 通知机制不太好,建议用消息队列的延时队列或者自己实现一个时间轮算法,总之需要的效果就是达到一段时间之后再去检查状态
wu00
2022-07-12 14:07:00 +08:00
肯定是上“定时任务”调度器,一般都提供延时任务。
比如 quartz 、sidekiq 、hangfire 之类的,能统计、执行结果、重试。
自己用 redis/mq 实现一套耗时耗力还不靠谱
wu00
2022-07-12 14:16:48 +08:00
下单的同时创建一个 delayjob ,xx 分钟后执行,第三方组件去负责调度就行了。
你只管控制 delayjob 里面并发和幂等,未支付就关闭,其他状态就忽略,几乎能控制在秒级,下单并发大你就不会在这提问了。
nilai
2022-07-12 15:24:09 +08:00
redis 的 key 的过期机制 并不是完全精确的过期, 它内部有算法,比如每次按一定的百分比来进行抽样。 这样有可能会导致明明已经过期的 key, 但是它还存在于 redis 中
VisionKi
2022-07-12 15:57:41 +08:00
前段时间也在找类似的解决方案,楼主的方案在于如果宕机了就无法监听到了,最后用了 redis 的 zset 实现。
实现方法:
存入订单的 id ,以过期时间的时间戳为 score 。只需要每秒取出分数小于当前时间戳的 id ,再异步处理业务即可。

有个问题就是 zset 没有类似 LPOP 的原子性操作,不能取出删除一步到位,不过对于单机应用来说也够用了。
JoseGuo
2022-07-12 16:59:13 +08:00
@VisionKi 嗯 我也考虑这样做

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/865511

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX