业务上需要同时校验两种资源令牌,确保资源足够的情况下才会处理请求,否则会直接拒绝请求。
假设两个资源的 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 方案的话上一把大锁的话感觉开销过于高了。
1
rrfeng 2022-04-21 09:02:04 +08:00 via Android
肯定 1 啊,符合逻辑直觉。另外这点性能不用费劲考虑…属于过度优化了。
集群模式了解一下 redis cluster hash tags |
2
tangtj 2022-04-21 14:09:11 +08:00
集群版本下,使用 lua 的话. 会要求你所涉及到的所有 key 都需要在一个分片.
|
3
timethinker 2022-04-21 16:24:34 +08:00
看情况
如果大多数情况令牌都足够充裕,第二种实际上是更好的做法,因为直接写了,相比第一种,少了一个读的操作。 如果大多数情况下令牌不够充裕,那么第二种相比第一种多了一个写的操作。 但是很显然,我们大概率无法提前得知哪种情况才是相对常见的,我个人的话会选择第一种。 |