• 35 设计优秀的分布式锁


    在之前业务的一次活动中,我发现在数据库操作日志中,出现最多的一个异常就是Interrupted Exception了,几乎所有的异常都是来自一个校验订单幂等性的SQL。

    因为校验订单幂等性是提交订单业务中第一个操作数据库的,所以幂等性校验也就承受了比较大的请求量,再加上我们还是基于一个数据库表来实现幂等性校验的,所以出现了一些请求事务超时,事务被中断的情况。其实基于数据库实现的幂等性校验就是一种分布式锁的实现。

    那什么是分布式锁呢,它又是用来解决哪些问题的呢?

    在JVM中,在多线程并发的情况下,我们可以使用同步锁或Lock锁,保证在同一时间内,只能有一个线程修改共享变量或执行代码块。但现在我们的服务基本都是基于分布式集群来实现部署的,对于一些共享资源,例如我们之前讨论过的库存,在分布式环境下使用Java锁的方式就失去作用了。

    这时,我们就需要实现分布式锁来保证共享资源的原子性。除此之外,分布式锁也经常用来避免分布式中的不同节点执行重复性的工作,例如一个定时发短信的任务,在分布式集群中,我们只需要保证一个服务节点发送短信即可,一定要避免多个节点重复发送短信给同一个用户。

    因为数据库实现一个分布式锁比较简单易懂,直接基于数据库实现就行了,不需要再引入第三方中间件,所以这是很多分布式业务实现分布式锁的首选。但是数据库实现的分布式锁在一定程度上,存在性能瓶颈。

    一 数据库实现分布式锁

    首先,我们应该创建一个锁表,通过创建和查询数据来保证一个数据的原子性

    1. CREATE TABLE `order` (
    2. `id` int(11) NOT NULL AUTO_INCREMENT,
    3. `order_no` int(11) DEFAULT NULL,
    4. `pay_money` decimal(10, 2) DEFAULT NULL,
    5. `status` int(4) DEFAULT NULL,
    6. `create_date` datetime(0) DEFAULT NULL,
    7. `delete_flag` int(4) DEFAULT NULL,
    8. PRIMARY KEY (`id`) USING BTREE,
    9. INDEX `idx_status`(`status`) USING BTREE,
    10. INDEX `idx_order`(`order_no`) USING BTREE
    11. ) ENGINE = InnoDB
    12. 复制代码

    其次,如果是校验订单的幂等性,就要先查询该记录是否存在数据库中,查询的时候要防止幻读,如果不存在,就插入到数据库,否则,放弃操作。

    1. select id from `order` where `order_no`= 'xxxx' for update
    2. 复制代码

    最后注意下,除了查询时防止幻读,我们还需要保证查询和插入是在同一个事务中,因此我们需要申明事务,具体的实现代码如下:

    1. @Transactional
    2. public int addOrderRecord(Order order) {
    3. if
  • 相关阅读:
    Chrome之解决DevTools: Failed to load data:No resource with given identifier found
    c 语言中的数组和指针
    《我在地球学Linux》-Linux环境搭建
    JUC并发编程——集合类不安全及Callable(基于狂神说的学习笔记)
    【解决方案】数据随机生成脚本
    layer.open再次渲染html,子页面调用在父页面打开弹出层,渲染html
    Kafka&陌陌案例,220903,,
    webmin远程命令执行漏洞(CVE-2019-15107)
    C_11微机原理
    【牛客刷题日记】— Javascript 通关秘籍
  • 原文地址:https://blog.csdn.net/zhaohuodian/article/details/126745455