简介
之前在公司用的数据库是mongdb,碰到了一个业务场景。
具体的业务是:有一个聊天界面,互相发送消息,对方读过后会记录积分。上限是五条。实现的思路是,前端读到消息后请求接口,记录积分。本来这样的场景,如果单独一条读,单独一条发,是没有问题的。但是如果一次性发送数十条,一次性读数十条,也就会一次性请求数十次接口。
实现思路
对于这种并发操作,最好的办法是什么呢?
有人该想到了,加锁。源代码确实也加锁了,但是操作的是mongo,进行的是update。
boolean lockResult = userCoreRedis.getLockResult(MINUTE_STOCK, 3L, 30l, userId);
if (lockResult) {
HashMap<String, Object> hashMap1 = new HashMap<>();
hashMap1.put("userPoints", user.getUserPoints() + integralConfig.getUserIntegral());//每次加100
userCoreDao.updateUser(userId, hashMap1);
userCoreRedis.unLock(userCoreRedis.buildRedisKey(MINUTE_STOCK, userId));//释放锁
}
这里就不贴完整代码了,贴了部分。看着确实没错,但值得注意的是
user.getUserPoints() + integralConfig.getUserIntegral()
这行。
这行的user.getUserPoints()就是从数据查询出来的。而且是修改后查的。
造成什么问题呢,mongodb的修改会慢那么几毫秒。所以,当前代码执行完成后,释放了锁,然后,虽然代码执行完了,但是提交mongo的命令,mongo没有执行完,在mongo那边出现了并发。
也就是说,user.getUserPoints()其实拿到的是修改前的值。
这样当然会造成积分错乱了。
本来呢,这块本来就不该这么请求,但是毕竟代码也已经写了,再改也费工时,那怎么办呢?
经过多次尝试,发现,mongo的添加,是没有任何延迟的,所以,最终是使用了添加,解决这个问题。
总结
这个问题很小,但是很多时候我们不注意就会引起各种各样的问题。而mongo为什么修改会延迟,也需要进一步去探索。编程的路很长,我们一起进步。