Redis 读取和写入速度是否一致?需要同时申请两个令牌的业务应该怎么实现?

2022-04-21 03:03:16 +08:00
 Richard14

业务上需要同时校验两种资源令牌,确保资源足够的情况下才会处理请求,否则会直接拒绝请求。

假设两个资源的 key 分别是 a 和 b ,业务需要判断当 a 和 b 同时有剩余(不小于 1 )的情况下才会判断允许,否则判断拒绝。实现上我的想法是用 lua 脚本确保原子性,否则比如用 mget 这种获取的话,虽然能一次获取两个,但是后面还要把对应数值减 1 (表示该资源被占用了),并发下状态同步问题不太好搞。

lua 脚本的话能确保原子性,但是实现上也有一些区别,比如以下三种方案(以下场景为假设每次取令牌值为 1 ,实际每次占用的令牌值不一定为 1 )

1 、最直观的

-- lua
1.mget A ,B
2.如果 A 大于 0 且 b 大于 0 ,DECR A, DECR B ,返回 true
3.否则返回 false

2.先减然后再补回

-- lua
1.DECR A ,DECR B
2.根据 decr 后的结果推测减之前是否大于 0 ,如果是的话返回 true
3.如果不是的话再 INCR A, INCR B ,返回 false

有无大佬熟悉 redis 性能的,上述两种操作用哪种会更快一些呢?另外也很好奇比如在集群状态下,A 和 B 两个令牌的状态有可能是跨节点的,这种情况又该怎么处理同步问题呢?如果要用 redlock 方案的话上一把大锁的话感觉开销过于高了。

971 次点击
所在节点    问与答
3 条回复
rrfeng
2022-04-21 09:02:04 +08:00
肯定 1 啊,符合逻辑直觉。另外这点性能不用费劲考虑…属于过度优化了。

集群模式了解一下 redis cluster hash tags
tangtj
2022-04-21 14:09:11 +08:00
集群版本下,使用 lua 的话. 会要求你所涉及到的所有 key 都需要在一个分片.
timethinker
2022-04-21 16:24:34 +08:00
看情况

如果大多数情况令牌都足够充裕,第二种实际上是更好的做法,因为直接写了,相比第一种,少了一个读的操作。
如果大多数情况下令牌不够充裕,那么第二种相比第一种多了一个写的操作。

但是很显然,我们大概率无法提前得知哪种情况才是相对常见的,我个人的话会选择第一种。

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

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

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

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

© 2021 V2EX