天天看点

或许你想知道的使用mysql数据库行锁做分布式锁方案

作者:蜡笔小贤
或许你想知道的使用mysql数据库行锁做分布式锁方案

众所周知,在做高并发,多进程业务时,会有很多条请求到方法中,为了保证数据的准确性,我们需要给业务代码中上排他锁,保证同一时间只有一个线程能够处理业务。在分布式的系统中,传统的synchronized已经满足不了我们的需求,需要分布式锁,分布式锁实现的方式有多种,其中一种方案就是数据库分布式锁。在mysql中 for update可以为数据库中的行上一个排它锁。当一个事务的操作未完成时候,其他事务可以读取但是不能写入或更新。

或许你想知道的使用mysql数据库行锁做分布式锁方案

在这里我就简单实现一下该方案:

(1)定义一个lock工具类方法

@Component
public class DatabaseLock {

    @Autowired
    protected ApplicationContext applicationContext;

    private static String lockSql = "select * from lock where name= ? for update";

    public void lock(String serviceName, Runnable runnable) {
        Connection connection = null;
        Boolean autoComit = null;
        PreparedStatement preparedStatement = null;
        //获取数据库源
        DataSource dataSource = applicationContext.getBean(DataSource.class);
        try {
            connection = dataSource.getConnection();
            autoComit = connection.getAutoCommit();
            connection.setAutoCommit(false);
            preparedStatement = connection.prepareStatement(lockSql);
            preparedStatement.setString(1, serviceName);
            preparedStatement.execute();
            //执行业务逻辑
            runnable.run();

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (connection != null) {
                try {
                    connection.commit();
                } catch (SQLException throwables) {
                }
                try {
                    connection.setAutoCommit(autoComit);
                } catch (SQLException throwables) {
                }
                try {
                    connection.close();
                } catch (SQLException throwables) {
                }
            }
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException throwables) {
                }
            }
        }
    }
}           

(2)定义数据库,数据库脚本

DROP TABLE IF EXISTS `lock`;
CREATE TABLE `lock`  (
  `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;           

(3)数据库分布式锁使用

@Slf4j
@Component
public class DatabaseLockTest {

    @Autowired
    private DatabaseLock lock;

    public void test() {
        lock.lock("test",() -> {
            log.info("do something");
        });
    }
}           

好了,今天的方案就分享到这里。下次有机会给大家分享其他实现分布式锁的方案。

或许你想知道的使用mysql数据库行锁做分布式锁方案

继续阅读