项目中使用 redis,再高并发下竟然遇到了这种问题,一年开发经验解决不了,来个大神看看。。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Jekins
V2EX    Java

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

  •  
  •   Jekins 2021-06-06 00:31:41 +08:00 6452 次点击
    这是一个创建于 1655 天前的主题,其中的信息可能已经有所发展或是发生改变。

    提交订单功能,判断当前用户有没有提交订单(订单创建成功会保存到 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 条回复    2021-06-28 18:52:31 +08:00
    Jooooooooo
        1
    Jooooooooo  
       2021-06-06 00:39:00 +08:00
    搜一下 setnx

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

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

    Redis 的单线程保证的是自己内部,Java 端的并发 Redis 处理不了。
    limuyan44
        9
    limuyan44  
       2021-06-06 09:21:31 +08:00
    对于并发而言,这种问题过于常识了,建议先找点相关的文章看看,这还是涉及钱的下单功能,这么搞迟早把自己坑死。
    szzadkk
        10
    szzadkk  
       2021-06-06 10:00:17 +08:00
    这个操作不是原子性的,肯定有问题,用 setnx 或者 lua 脚本
    ttyn
        11
    ttyn  
       2021-06-06 11:00:49 +08:00
    猜测你本意是用 Redis 做并发锁,防止订单重复提交。
    要理解你失败的原因,需要先了解 Redis 的原子操作,作为一年的开发经验,有点为难你。
    Redis 有个现成的东西,叫 Redlock,参考: https://blog.csdn.net/hanchao5272/article/details/99695360
    Jekins
        12
    Jekins  
    OP
       2021-06-06 11:05:58 +08:00
    @ccde8259 感谢分享经验
    Jekins
        13
    Jekins  
    OP
       2021-06-06 11:06:36 +08:00
    @ttyn 谢谢老哥,我只干了一年都还不到,之前确实没有碰到过这种情况。。
    Jekins
        14
    Jekins  
    OP
       2021-06-06 11:07:02 +08:00
    感谢楼上各位老哥!
    Jekins
        15
    Jekins  
    OP
       2021-06-06 11:14:14 +08:00
    @fewok 当前这个项目新开发的,没有什么并发,但是遇到了这个并发下单问题,也是以后要面对的。。
    pydiff
        16
    pydiff  
       2021-06-07 10:52:38 +08:00
    有点好奇,究竟是什么样的公司,敢让一个新手来做这种关键业务,如果 boom 了算谁的呢
    shimianxiang
        17
    shimianxiang  
       2021-06-07 13:44:21 +08:00
    建议直接 lua,还好扩展
    vgbhfive
        18
    vgbhfive  
       2021-06-07 14:44:45 +08:00 via Android
    lua 脚本或者 setnx 保证原子性
    wunsch0106
        19
    wunsch0106  
       2021-06-08 11:45:16 +08:00
    @pydiff 敢叫他上就敢写呗,boom 了肯定领导负责啊
    neptuno
        20
    neptuno  
       2021-06-11 14:54:52 +08:00
    原子操作,lua+redis 分布式锁,网上随便找个例子模仿写
    OV0
        21
    OV0  
       2021-06-16 18:06:59 +08:00
    分布式锁的套路:本地锁+分布式锁 + 数据库业务。
    DreamSpace
        22
    DreamSpace  
       2021-06-26 00:15:28 +08:00 via Android
    楼上说得很明白了,这里在补充一点,如果用 redis.keys(key)做模糊匹配,效率极低,而且会阻塞其他请求!!
    siweipancc
        23
    siweipancc  
       2021-06-28 18:52:31 +08:00 via iPhone
    keys? 真让人头大
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4290 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 10:07 PVG 18:07 LAX 02:07 JFK 05:07
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86