提交订单功能,判断当前用户有没有提交订单(订单创建成功会保存到 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"); });
1
Jooooooooo 2021-06-06 00:39:00 +08:00
搜一下 setnx
当然用 redis 做锁当发生故障时极小概率保障不了唯一性, 看你的需求了 |
2
swulling 2021-06-06 00:52:41 +08:00
一年开发经验,特别是做高并发,首先需要了解一个概念叫做并发冲突。
查询 Key 是否存在 + 设定 Key 的 Value,这两步在你的实现里不是原子的。解决办法就是使用原子操作替代两步操作。 |
3
ccde8259 2021-06-06 01:01:13 +08:00 via iPhone 2
为什么不用 SETNX
为什么不用 MULTI WATCH 为什么不用 LUA SCRIPT |
4
Hurriance 2021-06-06 01:11:12 +08:00
不嫌麻烦的话可以用 lua + 2 楼的方法
|
5
jones2000 2021-06-06 03:12:44 +08:00
直接插入不覆盖的模式, 如果插入成功就说明是新订单, 插入失败就说明订单已存在。
|
6
Addup 2021-06-06 03:16:36 +08:00
用 lua 注意定时清理下脚本缓存, 这里有两个坑: 不然不断累积导致内存爆满, 建有 dts 的话从机也需要执行命令清脚本缓存, 脚本缓存过多时, 清除命令耗时过长可能导致 dts 连接异常.
|
7
fewok 2021-06-06 04:17:45 +08:00
咱们先说人话,你们交易业务,下单最高峰,秒杀最高峰的 TPS 是多少???
|
8
jorneyr 2021-06-06 08:27:00 +08:00
redisTemplate.keys("key");
Java 代码在这里并发了,多个线程执行到这里时 key 不存在,则进行了多条插入。 Redis 的单线程保证的是自己内部,Java 端的并发 Redis 处理不了。 |
9
limuyan44 2021-06-06 09:21:31 +08:00
对于并发而言,这种问题过于常识了,建议先找点相关的文章看看,这还是涉及钱的下单功能,这么搞迟早把自己坑死。
|
10
szzadkk 2021-06-06 10:00:17 +08:00
这个操作不是原子性的,肯定有问题,用 setnx 或者 lua 脚本
|
11
ttyn 2021-06-06 11:00:49 +08:00
猜测你本意是用 Redis 做并发锁,防止订单重复提交。
要理解你失败的原因,需要先了解 Redis 的原子操作,作为一年的开发经验,有点为难你。 Redis 有个现成的东西,叫 Redlock,参考: https://blog.csdn.net/hanchao5272/article/details/99695360 |
14
Jekins OP 感谢楼上各位老哥!
|
16
pydiff 2021-06-07 10:52:38 +08:00
有点好奇,究竟是什么样的公司,敢让一个新手来做这种关键业务,如果 boom 了算谁的呢
|
17
shimianxiang 2021-06-07 13:44:21 +08:00
建议直接 lua,还好扩展
|
18
vgbhfive 2021-06-07 14:44:45 +08:00 via Android
lua 脚本或者 setnx 保证原子性
|
19
wunsch0106 2021-06-08 11:45:16 +08:00
@pydiff 敢叫他上就敢写呗,boom 了肯定领导负责啊
|
20
neptuno 2021-06-11 14:54:52 +08:00
原子操作,lua+redis 分布式锁,网上随便找个例子模仿写
|
21
OV0 2021-06-16 18:06:59 +08:00
分布式锁的套路:本地锁+分布式锁 + 数据库业务。
|
22
DreamSpace 2021-06-26 00:15:28 +08:00 via Android
楼上说得很明白了,这里在补充一点,如果用 redis.keys(key)做模糊匹配,效率极低,而且会阻塞其他请求!!
|
23
siweipancc 2021-06-28 18:52:31 +08:00 via iPhone
keys? 真让人头大
|