首页 > 社交 > 科普中国

MongoDB高并发下的upsert问题

常驻编辑 科普中国 2022-06-13 额度   索引   冲突   异常   错误   消息   操作   文档   业务   日志

MongoDB高并发下的upsert问题

一、问题现象

运行中心同事报告生产环境日志每天0点附近都会出现几笔错误日志,日志内容截图如下:U3k拜客生活常识网

二、问题分析

系统采用MongoDB数据库,该表建有groupName+limitKey组合唯一索引,所以分析下来第一感觉就是重复执行insert报duplicate key错误了。U3k拜客生活常识网

找到对应的业务代码如下:U3k拜客生活常识网

        return mongoTemplate.findAndModify(
                new Query()
                        .addCriteria(Criteria.where("limitKey").is(limitKey))
                        .addCriteria(Criteria.where("groupName").is(groupName)),
                new Update()
                        .inc("cnt", delta)
                        .set("updateTime", LocalDateTime.now())
                        .setOnInsert("createTime", LocalDateTime.now())
                        .setOnInsert("expireTime", keepAliveDays == 0 ? null : LocalDateTime.now().plusDays(keepAliveDays)),
                new FindAndModifyOptions()
                        // 先查询,如果没有符合条件的,会执行插入,插入的值是查询值   更新值
                        .upsert(true)
                        // 返回当前最新值
                        .returnNew(true),
                LimitKeyStatEntity.class);

执行upsert操作,即首先查库里是否已存在记录,存在则执行update更新操作,否则执行insert插入操作。U3k拜客生活常识网

代码逻辑并未发现有啥问题,但是为啥就报insert冲突了呢?U3k拜客生活常识网

经上网查询发现,MongoDB本身是有文档级的写入锁的。也就是说,当一个进程开始修改一个文档时,该文档被锁定,其他文档不可以再对其进行写入甚至读取。这个写入锁的存在本身就是为了防止不同程序更新文档时产生的写入冲突。然而,update其实分为两步。首先是搜索文档位置,然后再执行文档更新。U3k拜客生活常识网

因此MongoDB在高并发的情况下,可能会出现以下问题:U3k拜客生活常识网

  • 两个线程t1,t2同时update一条记录时
  • t1读,记录不存在;t2读,记录不存在。
  • t1写,执行insert,插入成功
  • t2写,执行insert,由于唯一索引原因,重复插入失败。

再对应查到这几笔累计请求,确实系生产上某个大商户每天0点开始频繁发退货,而且退货间隔时间小到1ms导致的。U3k拜客生活常识网

三、解决方案

mongoTemplate的findAndModify()方法目前暂无好的办法来解决高并发下上述缺陷,只能从业务方案上来解决。U3k拜客生活常识网

由于该应用场景为消费订单MQ消息并执行额度累计,因此在写MongoDB异常导致业务上更新累计值失败时,认为消费MQ消息失败并抛出异常,利用RocketMQ消息失败重试机制,重新消费并执行额度累计。U3k拜客生活常识网

相关阅读:

  • 花呗取消分期了怎么突然降额
  • 怎么样提高花呗额度(怎么提升花呗额度到5000)
  • 哪个信用卡额度高(20万额度信用卡什么条件)
  • 信用卡哪个额度高(四大行信用卡哪个额度高)
  • 公积金贷款额度是多少(公积金取出来后悔了)
  • 信用卡额度多少(20岁办信用卡额度多少)
  • 花呗额度多少(花呗额度5000什么水平)
  • 白金卡额度多少(尊贵级白金卡额度)
  • 花呗解封后只有500了正常吗
  • 信用卡的有效期是多久(信用卡临时额度期限)
    • 网站地图 |
    • 声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不做权威认证,如若验证其真实性,请咨询相关权威专业人士。