可以丢到queue里面,再一条条慢慢的消费
使用redis原子操作
redis如果是分布式部署,也会有并发的情况
lock加锁
请求A获取lock之后,同一时刻的请求B,请求C.....获取不到lock,返回错误还是等待?
感觉我这个问题是逃不开锁的是吧?
@老六代码: 余额积分总是对应到一个唯一性的代码吧,lock住这个代码就行了,同一个代码会同步执行,不同的代码并行
@jqw2009: lock之后,其他请求会等待吧?
如果用的是 C# ,可以使用Interlocked.Increment()
分布式情况下有什么好的办法吗
感觉我这个问题是逃不开锁的是吧?
@老六代码: 你究竟要解决的是分布式并发问题还是最终一致性问题?
如果是并发问题,可以使用 redis 的分布式锁,园子里的参考博文:
@dudu: 并发问题
@老六代码: 那就用分布式锁
@dudu: 没有获取到锁的话直接返回错误吗?
@老六代码: 等待超时再返回错误
说说平时我们在项目中的使用方式:
第一种方式:在操作数据的时候,直接数库表中锁上需要操作的这条数据(注意只是锁一条数据,不要把这个表锁上了)
第二种方式:在执行语句的时候,加上一个条件,比如
update table set 积分=积分-需要扣除的积分 where id='' and 积分>=需要扣除的积分
我们在实际使用的时候,是将第一种和第二种结合起来使用
感觉我这个问题是逃不开锁的是吧?
@老六代码: 我想问你一个问题,你是避免多扣是什么意思?
是避免扣出来余额为负数了吗,还是什么情况?
如果是这样,你可以按照我的第二种方式处理,这样就是并发的修改余额也不会出现问题
@猴子哥: 问题问错了,应该是并发情况下少加少减
@老六代码: update table set 积分=积分-需要扣除的积分 where id=''
就这样操作,也不会少加少减啊,请求并发,数据库最终的执行语句应该也是有先后一个一个的执行的吧
@猴子哥: 您的意思是不用ef这类orm,直接用原生sql是吧?
@老六代码: 我是用SQL语句,好像ef更新都是更新的最后确定的数值,这样并发就会有问题
复杂或者关键的逻辑,最好还是用sql语句
我平时都是写原生的ADO,EF不也是很熟悉,只是一个建议
ef之类的orm可用使用乐观锁/悲观锁。
update table set field=value where id=id and version=orignversion
如果version已经被修改,更新失败之后应该怎么处理
@老六代码:
retry。指的是当前业务哈,不是单独的save到db这个动作。在进一步可以实现简单的api幂等性
当然也可以把这一步拆出来,使用分布式锁来把这个lock的动作前置
怎么样会少加多加呢.
余额和积分是每个用户都不同吧,加锁是解决同一个用户在不同pc端进行操作时的数据一致性问题,不同用户进行操作时是不会阻塞的啊。也就是按用户来加锁。
你这个又不是限量抢购那种活动。