V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Jekins
V2EX  ›  Java

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

  •  
  •   Jekins · 104 天前 · 4099 次点击
    这是一个创建于 104 天前的主题,其中的信息可能已经有所发展或是发生改变。

    提交订单功能,判断当前用户有没有提交订单(订单创建成功会保存到 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   104 天前
    搜一下 setnx

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

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

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