V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Richard14
V2EX  ›  问与答

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

  •  
  •   Richard14 · 2022-04-21 03:03:16 +08:00 · 1060 次点击
    这是一个创建于 954 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    假设两个资源的 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 方案的话上一把大锁的话感觉开销过于高了。

    3 条回复    2022-04-21 16:24:34 +08:00
    rrfeng
        1
    rrfeng  
       2022-04-21 09:02:04 +08:00 via Android
    肯定 1 啊,符合逻辑直觉。另外这点性能不用费劲考虑…属于过度优化了。

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

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

    但是很显然,我们大概率无法提前得知哪种情况才是相对常见的,我个人的话会选择第一种。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2814 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 12:50 · PVG 20:50 · LAX 04:50 · JFK 07:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.