1
546L5LiK6ZOt 2023-03-11 19:01:12 +08:00
Redisson 分布式锁不可以吗,对商品进行加锁
|
2
hhjswf 2023-03-11 19:04:59 +08:00 via Android
搞不懂,就特么一个 sku 管理也要高并发吗。。很多个店铺管理员在疯狂添加 sku 吗。。
|
3
Chad0000 2023-03-11 19:10:36 +08:00 via iPhone
你都高并发时检测数据库了,那么就算 redis 挂也是在数据库之后。
所以多虑了。就用 redis 没什么的。 |
4
alexleee 2023-03-11 19:10:39 +08:00
用分布式缓存,以店铺 ID+SKU 为 key 弄个分布式锁,插入的时候先拿到锁,拿到锁的线程去 check()+save()?
|
5
kwh 2023-03-11 19:12:10 +08:00
redis 自增,通过校验就自增,首次自增会是 1 ,非首次自增就会大于 1 了。
而且商户保存操作,MySQL 行锁应该也行吧? |
6
mercurius OP @546L5LiK6ZOt 有考虑过,但要解决该问题,锁只能加在店铺维度,粒度有点大
@hhjswf 用爬虫爬别人商品,然后批量创建到自己店铺,那个内部服务直接用多线程打过来时发现的问题…… @Chad0000 但检测数据库那里只是一条 SQL ,而这里校验时连续调用 200 次 RSet.add ,这个性能会不会有点夸张?我对这块没啥概念…… @alexleee 有考虑过,但这个锁是 SKU 维度,那加锁次数是跟 SKU 数量一致的,而商品与 SKU 是一对多的整体关系,不能说一个个 SKU 单独校验和保存,所以单个商品可能加上几十甚至上百个锁…… @kwh 自增是商品通过校验,还是 SKU 通过校验?它们是一个整体的,并且是一对多的关系……MySQL 行锁应该不行吧,问题不是保存操作,而是校验操作那里的高并发 |
7
alexleee 2023-03-11 19:57:16 +08:00
@mercurius 你的外键约束是商品 id+SKU 这两个的组合呀,我理解你说的怕竞争条件下出问题的资源不就是店铺 id+sku 的创建权吗,你又怕不同线程创建太多锁...那你牺牲一点并发性能锁 sku 或者锁店铺吧...
|
8
leonshaw 2023-03-11 20:03:45 +08:00
要强一致就要加锁(或者等效于加锁的操作)。考虑到 IO RT ,可以按店铺分区,实现一个批量加锁的接口。不知道有没有现成的轮子。
|
9
mercurius OP |
10
546L5LiK6ZOt 2023-03-11 20:57:11 +08:00
几十、上百次 redis 请求不算高,腾讯云最低配的 redis 也能支持上万 qps
|
11
546L5LiK6ZOt 2023-03-11 20:59:38 +08:00
我觉得严谨的做法还是得在数据库用唯一键约束来做。原先的表不能加唯一键,那就新增一个表,商品和 sku 作为唯一键,在一个事务里插入。用分布式锁不能保证 100% 一致的。
|
12
k9982874 2023-03-11 21:04:13 +08:00 via Android
sku 生成规则制定好,根本不需要去考虑冲突问题。
例如商品 sku 由商铺 uid 为前缀+品类 uid+时间戳+用户自定义输入组成,基本上就很难重复 |
13
xwayway 2023-03-11 21:05:01 +08:00 via iPhone
那要不你扔 mq ?慢慢去保存就是咯
|
14
mercurius OP @546L5LiK6ZOt 是的,最纯粹的做法就是唯一索引,只是原先表的业务逻辑不支持……不过确实新增一个中间表就能解决,并且比起各种加锁要简单得多,操作只需要批量插入和删除,性能也只是多一两次 SQL 操作。非常感谢,这是新思路!
@k9982874 背景就是 sku 只能是商家自定义的,要原模原样,不能再在上面改东西…… @xwayway 这种操作是会同步返回结果的,从同步改成异步,这逻辑变化有点大了 |
15
k9982874 2023-03-11 21:50:06 +08:00 via Android
@mercurius 非要用锁,11 楼已经给答案了,建一张外键表,sku 加唯一约束,先插入这个表,成功后再插入商品表。
|
16
mercurius OP |
17
potatowish 2023-03-11 23:34:14 +08:00 via iPhone
加一个映射表,包含自增 ID 、商铺 UID 、商品品类 ID 、用户自定义 SKU 。自增 ID 作为实际的 SKU ,在业务中使用到 SKU 时只需要查询它对应的实际 SKU 。
|
18
xiaop1ng 2023-03-12 00:45:21 +08:00 via iPhone
@546L5LiK6ZOt 这个方法算是基于数据库的一种分布式锁吧,我认为和基于 redis 对商品 id+sku 上分布式锁的逻辑是一样的,流程变为 lock->check->save->unlock ,不明白为什么分布式锁不能保证 100%一致,想讨论一下
|
19
546L5LiK6ZOt 2023-03-12 01:18:17 +08:00
@xiaop1ng
参考这里 https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html GC 的 STW 可能会导致锁过期了,但是进程还认为占用锁。即使用没有 GC 的语言,操作系统的进程调度也可能会出现这种情况。理论上来说,分布式锁不可能保证完全一致的。还是得靠底层数据库 |
20
bushenx 2023-03-12 03:14:21 +08:00 via Android
如果 check 只是一条 sql 且场景需要强一致,不如直接上事务吧,select 语句直接上锁。
|
21
xiaop1ng 2023-03-12 15:07:15 +08:00
@546L5LiK6ZOt 了解,thanks~
|