Jekins
V2EX  ›  Java

项目中使用 redis,再高并发下竟然遇到了这种问题,一年开发经验解决不了,来个大神看看。。

  •  
  •   Jekins · Jun 6, 2021 · 6807 views
    This topic created in 1812 days ago, the information mentioned may be changed or developed.

    提交订单功能,判断当前用户有没有提交订单(订单创建成功会保存到 redis )。以下是伪代码,逻辑和提交订单是一样的,遇到的问题也是一样的,请求老牛解决!

    ConcurrencyTester tester = ThreadUtil.concurrencyTest(1000, () -> { Set<String> keys = redisTemplate.keys("key");//查询 redis 有没有这个 key,有就返回 key if (keys.size() > 0) { return; } System.out.println("我来插入到 redis"); //此处被执行多次 redisTemplate.opsForValue().set("key", "value"); });

    23 replies    2021-06-28 18:52:31 +08:00
    Jooooooooo
        1
    Jooooooooo  
       Jun 6, 2021
    搜一下 setnx

    当然用 redis 做锁当发生故障时极小概率保障不了唯一性, 看你的需求了
    swulling
        2
    swulling  
       Jun 6, 2021
    一年开发经验,特别是做高并发,首先需要了解一个概念叫做并发冲突。

    查询 Key 是否存在 + 设定 Key 的 Value,这两步在你的实现里不是原子的。解决办法就是使用原子操作替代两步操作。
    ccde8259
        3
    ccde8259  
       Jun 6, 2021 via iPhone   ❤️ 2
    为什么不用 SETNX
    为什么不用 MULTI WATCH
    为什么不用 LUA SCRIPT
    Hurriance
        4
    Hurriance  
       Jun 6, 2021
    不嫌麻烦的话可以用 lua + 2 楼的方法
    jones2000
        5
    jones2000  
       Jun 6, 2021
    直接插入不覆盖的模式, 如果插入成功就说明是新订单, 插入失败就说明订单已存在。
    Addup
        6
    Addup  
       Jun 6, 2021
    用 lua 注意定时清理下脚本缓存, 这里有两个坑: 不然不断累积导致内存爆满, 建有 dts 的话从机也需要执行命令清脚本缓存, 脚本缓存过多时, 清除命令耗时过长可能导致 dts 连接异常.
    fewok
        7
    fewok  
       Jun 6, 2021
    咱们先说人话,你们交易业务,下单最高峰,秒杀最高峰的 TPS 是多少???
    jorneyr
        8
    jorneyr  
       Jun 6, 2021
    redisTemplate.keys("key");
    Java 代码在这里并发了,多个线程执行到这里时 key 不存在,则进行了多条插入。

    Redis 的单线程保证的是自己内部,Java 端的并发 Redis 处理不了。
    limuyan44
        9
    limuyan44  
       Jun 6, 2021
    对于并发而言,这种问题过于常识了,建议先找点相关的文章看看,这还是涉及钱的下单功能,这么搞迟早把自己坑死。
    szzadkk
        10
    szzadkk  
       Jun 6, 2021
    这个操作不是原子性的,肯定有问题,用 setnx 或者 lua 脚本
    ttyn
        11
    ttyn  
       Jun 6, 2021
    猜测你本意是用 Redis 做并发锁,防止订单重复提交。
    要理解你失败的原因,需要先了解 Redis 的原子操作,作为一年的开发经验,有点为难你。
    Redis 有个现成的东西,叫 Redlock,参考: https://blog.csdn.net/hanchao5272/article/details/99695360
    Jekins
        12
    Jekins  
    OP
       Jun 6, 2021
    @ccde8259 感谢分享经验
    Jekins
        13
    Jekins  
    OP
       Jun 6, 2021
    @ttyn 谢谢老哥,我只干了一年都还不到,之前确实没有碰到过这种情况。。
    Jekins
        14
    Jekins  
    OP
       Jun 6, 2021
    感谢楼上各位老哥!
    Jekins
        15
    Jekins  
    OP
       Jun 6, 2021
    @fewok 当前这个项目新开发的,没有什么并发,但是遇到了这个并发下单问题,也是以后要面对的。。
    pydiff
        16
    pydiff  
       Jun 7, 2021
    有点好奇,究竟是什么样的公司,敢让一个新手来做这种关键业务,如果 boom 了算谁的呢
    shimianxiang
        17
    shimianxiang  
       Jun 7, 2021
    建议直接 lua,还好扩展
    vgbhfive
        18
    vgbhfive  
       Jun 7, 2021 via Android
    lua 脚本或者 setnx 保证原子性
    wunsch0106
        19
    wunsch0106  
       Jun 8, 2021
    @pydiff 敢叫他上就敢写呗,boom 了肯定领导负责啊
    neptuno
        20
    neptuno  
       Jun 11, 2021
    原子操作,lua+redis 分布式锁,网上随便找个例子模仿写
    OV0
        21
    OV0  
       Jun 16, 2021
    分布式锁的套路:本地锁+分布式锁 + 数据库业务。
    DreamSpace
        22
    DreamSpace  
       Jun 26, 2021 via Android
    楼上说得很明白了,这里在补充一点,如果用 redis.keys(key)做模糊匹配,效率极低,而且会阻塞其他请求!!
    siweipancc
        23
    siweipancc  
       Jun 28, 2021 via iPhone
    keys? 真让人头大
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1677 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 70ms · UTC 16:26 · PVG 00:26 · LAX 09:26 · JFK 12:26
    ♥ Do have faith in what you're doing.