首页 新闻 会员 周边 捐助

并发余额或积分如何避免少加少减

0
悬赏园豆:50 [已解决问题] 解决于 2019-06-04 14:38

高并发情况下,余额或积分如何避免少加少减?大家有什么方案吗?

chester·chen的主页 chester·chen | 小虾三级 | 园豆:507
提问于:2019-05-31 08:11
< >
分享
最佳答案
0

可以丢到queue里面,再一条条慢慢的消费

收获园豆:50
通信的搞程序 | 小虾三级 |园豆:1757 | 2019-06-03 20:45
其他回答(7)
0

使用redis原子操作

跨界农民工 | 园豆:114 (初学一级) | 2019-05-31 08:13

redis如果是分布式部署,也会有并发的情况

支持(0) 反对(0) 程序员修炼之旅 | 园豆:976 (小虾三级) | 2019-05-31 09:17
0

lock加锁

jqw2009 | 园豆:2341 (老鸟四级) | 2019-05-31 08:56

请求A获取lock之后,同一时刻的请求B,请求C.....获取不到lock,返回错误还是等待?

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 09:09

感觉我这个问题是逃不开锁的是吧?

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 09:25

@老六代码: 余额积分总是对应到一个唯一性的代码吧,lock住这个代码就行了,同一个代码会同步执行,不同的代码并行

支持(0) 反对(0) jqw2009 | 园豆:2341 (老鸟四级) | 2019-05-31 09:27

@jqw2009: lock之后,其他请求会等待吧?

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 09:31
0

如果用的是 C# ,可以使用Interlocked.Increment()

dudu | 园豆:30948 (高人七级) | 2019-05-31 09:15

分布式情况下有什么好的办法吗

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 09:21

感觉我这个问题是逃不开锁的是吧?

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 09:24

@老六代码: 你究竟要解决的是分布式并发问题还是最终一致性问题?
如果是并发问题,可以使用 redis 的分布式锁,园子里的参考博文:

支持(0) 反对(0) dudu | 园豆:30948 (高人七级) | 2019-05-31 09:44

@dudu: 并发问题

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 09:46

@老六代码: 那就用分布式锁

支持(0) 反对(0) dudu | 园豆:30948 (高人七级) | 2019-05-31 10:22

@dudu: 没有获取到锁的话直接返回错误吗?

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 10:24

@老六代码: 等待超时再返回错误

支持(0) 反对(0) dudu | 园豆:30948 (高人七级) | 2019-05-31 10:30
0

说说平时我们在项目中的使用方式:
第一种方式:在操作数据的时候,直接数库表中锁上需要操作的这条数据(注意只是锁一条数据,不要把这个表锁上了)
第二种方式:在执行语句的时候,加上一个条件,比如
update table set 积分=积分-需要扣除的积分 where id='' and 积分>=需要扣除的积分

我们在实际使用的时候,是将第一种和第二种结合起来使用

程序员修炼之旅 | 园豆:976 (小虾三级) | 2019-05-31 09:16

感觉我这个问题是逃不开锁的是吧?

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 09:24

@老六代码: 我想问你一个问题,你是避免多扣是什么意思?
是避免扣出来余额为负数了吗,还是什么情况?
如果是这样,你可以按照我的第二种方式处理,这样就是并发的修改余额也不会出现问题

支持(0) 反对(0) 程序员修炼之旅 | 园豆:976 (小虾三级) | 2019-05-31 09:26

@猴子哥: 问题问错了,应该是并发情况下少加少减

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 09:30

@老六代码: update table set 积分=积分-需要扣除的积分 where id=''
就这样操作,也不会少加少减啊,请求并发,数据库最终的执行语句应该也是有先后一个一个的执行的吧

支持(0) 反对(0) 程序员修炼之旅 | 园豆:976 (小虾三级) | 2019-05-31 09:47

@猴子哥: 您的意思是不用ef这类orm,直接用原生sql是吧?

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 09:48

@老六代码: 我是用SQL语句,好像ef更新都是更新的最后确定的数值,这样并发就会有问题
复杂或者关键的逻辑,最好还是用sql语句
我平时都是写原生的ADO,EF不也是很熟悉,只是一个建议

支持(0) 反对(0) 程序员修炼之旅 | 园豆:976 (小虾三级) | 2019-05-31 09:51
0

ef之类的orm可用使用乐观锁/悲观锁。
update table set field=value where id=id and version=orignversion

czd890 | 园豆:14488 (专家六级) | 2019-05-31 11:22

如果version已经被修改,更新失败之后应该怎么处理

支持(0) 反对(0) chester·chen | 园豆:507 (小虾三级) | 2019-05-31 11:53

@老六代码:
retry。指的是当前业务哈,不是单独的save到db这个动作。在进一步可以实现简单的api幂等性

支持(0) 反对(0) czd890 | 园豆:14488 (专家六级) | 2019-05-31 13:55

当然也可以把这一步拆出来,使用分布式锁来把这个lock的动作前置

支持(0) 反对(0) czd890 | 园豆:14488 (专家六级) | 2019-05-31 13:56
0

怎么样会少加多加呢.

吴瑞祥 | 园豆:29449 (高人七级) | 2019-05-31 14:03
0

余额和积分是每个用户都不同吧,加锁是解决同一个用户在不同pc端进行操作时的数据一致性问题,不同用户进行操作时是不会阻塞的啊。也就是按用户来加锁。
你这个又不是限量抢购那种活动。

海之殇 | 园豆:500 (菜鸟二级) | 2019-05-31 17:12
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册