news 2026/4/16 14:19:55

MySQL 分布式锁实现方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL 分布式锁实现方案

一、基于数据库表的方案

  1. 悲观锁实现(行锁)
-- 1. 创建锁表CREATETABLE`distributed_lock`(`id`int(11)NOTNULLAUTO_INCREMENT,`lock_key`varchar(64)NOTNULLCOMMENT'锁标识',`business_id`varchar(255)DEFAULTNULLCOMMENT'业务标识',`expire_time`datetimeDEFAULTNULLCOMMENT'过期时间',`create_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMP,PRIMARYKEY(`id`),UNIQUEKEY`uk_lock_key`(`lock_key`))ENGINE=InnoDBDEFAULTCHARSET=utf8;-- 2. 获取锁BEGIN;SELECT*FROMdistributed_lockWHERElock_key='order_lock_123'FORUPDATE;-- 检查锁是否过期-- 如果无记录或已过期,插入或更新INSERTINTOdistributed_lock(lock_key,business_id,expire_time)VALUES('order_lock_123','order_001',DATE_ADD(NOW(),INTERVAL30SECOND))ONDUPLICATEKEYUPDATEbusiness_id=VALUES(business_id),expire_time=VALUES(expire_time);COMMIT;-- 3. 释放锁DELETEFROMdistributed_lockWHERElock_key='order_lock_123'ANDbusiness_id='order_001';
  1. 乐观锁实现(版本号)
-- 创建带版本号的锁表CREATETABLE`optimistic_lock`(`id`int(11)NOTNULLAUTO_INCREMENT,`resource_name`varchar(64)NOTNULLCOMMENT'资源名',`version`int(11)NOTNULLDEFAULT'0'COMMENT'版本号',`owner`varchar(64)DEFAULTNULLCOMMENT'持有者',PRIMARYKEY(`id`),UNIQUEKEY`uk_resource`(`resource_name`))ENGINE=InnoDBDEFAULTCHARSET=utf8;-- 获取锁(CAS操作)UPDATEoptimistic_lockSETversion=version+1,owner='service_A'WHEREresource_name='resource_1'ANDversion=#{oldVersion};

二、基于GET_LOCK()函数的方案

-- 1. 获取锁(会话级)SELECTGET_LOCK('my_lock',10);-- 等待10秒-- 2. 检查是否获取成功SELECTIS_FREE_LOCK('my_lock');SELECTIS_USED_LOCK('my_lock');-- 3. 释放锁SELECTRELEASE_LOCK('my_lock');-- 4. 释放所有锁SELECTRELEASE_ALL_LOCKS();

三、完整实现示例

Java 实现类

importjavax.sql.DataSource;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.util.concurrent.TimeUnit;publicclassMySQLDistributedLock{privateDataSourcedataSource;privateStringlockKey;privatelongexpireMillis=30000;privateStringownerId;publicMySQLDistributedLock(DataSourcedataSource,StringlockKey){this.dataSource=dataSource;this.lockKey=lockKey;this.ownerId=generateOwnerId();}publicbooleantryLock(longwaitTime,TimeUnitunit)throwsSQLException{longstart=System.currentTimeMillis();longtimeout=unit.toMillis(waitTime);while(System.currentTimeMillis()-start<timeout){if(acquireLock()){returntrue;}try{Thread.sleep(100);// 重试间隔}catch(InterruptedExceptione){Thread.currentThread().interrupt();returnfalse;}}returnfalse;}privatebooleanacquireLock()throwsSQLException{Connectionconn=null;try{conn=dataSource.getConnection();conn.setAutoCommit(false);// 使用行级锁StringcheckSql="SELECT id, expire_time FROM distributed_lock "+"WHERE lock_key = ? FOR UPDATE";try(PreparedStatementps=conn.prepareStatement(checkSql)){ps.setString(1,lockKey);ResultSetrs=ps.executeQuery();if(rs.next()){// 检查是否过期java.sql.TimestampexpireTime=rs.getTimestamp("expire_time");if(expireTime!=null&&expireTime.after(newjava.util.Date())){// 锁被其他进程持有且未过期conn.rollback();returnfalse;}}// 获取或更新锁StringupsertSql="INSERT INTO distributed_lock "+"(lock_key, owner_id, expire_time) VALUES (?, ?, ?) "+"ON DUPLICATE KEY UPDATE "+"owner_id = VALUES(owner_id), "+"expire_time = VALUES(expire_time)";try(PreparedStatementupsertPs=conn.prepareStatement(upsertSql)){upsertPs.setString(1,lockKey);upsertPs.setString(2,ownerId);upsertPs.setTimestamp(3,newjava.sql.Timestamp(System.currentTimeMillis()+expireMillis));introws=upsertPs.executeUpdate();conn.commit();returnrows>0;}}}catch(SQLExceptione){if(conn!=null){conn.rollback();}throwe;}finally{if(conn!=null){conn.setAutoCommit(true);conn.close();}}}publicvoidunlock()throwsSQLException{Stringsql="DELETE FROM distributed_lock "+"WHERE lock_key = ? AND owner_id = ?";try(Connectionconn=dataSource.getConnection();PreparedStatementps=conn.prepareStatement(sql)){ps.setString(1,lockKey);ps.setString(2,ownerId);ps.executeUpdate();}}privateStringgenerateOwnerId(){returnThread.currentThread().getName()+"_"+System.currentTimeMillis()+"_"+Math.random();}}

Spring Boot 集成

@ComponentpublicclassDistributedLockService{@AutowiredprivateJdbcTemplatejdbcTemplate;public<T>TexecuteWithLock(StringlockKey,longwaitTime,TimeUnitunit,Supplier<T>supplier){MySQLDistributedLocklock=newMySQLDistributedLock(jdbcTemplate.getDataSource(),lockKey);try{if(lock.tryLock(waitTime,unit)){try{returnsupplier.get();}finally{lock.unlock();}}else{thrownewRuntimeException("获取分布式锁失败: "+lockKey);}}catch(SQLExceptione){thrownewRuntimeException("分布式锁异常",e);}}// 使用示例publicvoidprocessOrder(StringorderId){StringlockKey="order_lock_"+orderId;executeWithLock(lockKey,5,TimeUnit.SECONDS,()->{// 业务逻辑updateOrderStatus(orderId);returnnull;});}}

四、进阶优化方案

  1. 可重入锁实现
-- 支持可重入的锁表结构CREATETABLE`reentrant_lock`(`id`int(11)NOTNULLAUTO_INCREMENT,`lock_key`varchar(64)NOTNULL,`owner_id`varchar(128)NOTNULL,`count`int(11)NOTNULLDEFAULT'0',`expire_time`datetimeDEFAULTNULL,PRIMARYKEY(`id`),UNIQUEKEY`uk_lock_key`(`lock_key`));
  1. 锁续期机制
publicclassLockRenewalTaskimplementsRunnable{privateMySQLDistributedLocklock;privatevolatilebooleanrunning=true;@Overridepublicvoidrun(){while(running){try{Thread.sleep(10000);// 每10秒续期一次renewLock();}catch(Exceptione){// 处理异常}}}privatevoidrenewLock()throwsSQLException{Stringsql="UPDATE distributed_lock "+"SET expire_time = DATE_ADD(NOW(), INTERVAL 30 SECOND) "+"WHERE lock_key = ? AND owner_id = ?";// 执行更新}}

五、各方案对比

方案 优点 缺点 适用场景
基于行锁 实现简单,强一致 性能较低,可能死锁 低并发,强一致性要求
乐观锁 并发性好 需要重试机制 并发冲突少的场景
GET_LOCK() MySQL原生支持 会话级别,连接断开自动释放 简单同步需求

六、最佳实践建议

  1. 锁粒度控制:尽量缩小锁的范围,使用细粒度锁
  2. 超时设置:必须设置锁超时时间,防止死锁
  3. 锁清理:定期清理过期锁记录
  4. 监控报警:监控锁等待时间和死锁情况
  5. 降级方案:考虑锁获取失败时的降级策略

七、注意事项

  1. 数据库性能:高并发场景下,数据库锁可能成为瓶颈
  2. 死锁风险:注意事务执行顺序,避免死锁
  3. 连接池配置:确保数据库连接足够
  4. 时钟同步:多节点服务器时间需要同步
  5. 错误处理:妥善处理网络异常和数据库异常

对于高性能要求的场景,建议考虑 Redis 或 ZooKeeper 作为分布式锁的实现方案。MySQL 分布式锁更适合于:

· 已有 MySQL 基础设施
· 并发量不高(QPS < 1000)
· 需要强一致性保证
· 系统简单,不希望引入额外中间件

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 15:49:57

VSCode日志分析插件开发实战:3天打造支持TB级日志实时流式过滤、智能上下文关联与AI异常标注的插件(含GitHub私有仓库访问权限)

第一章&#xff1a;VSCode 2026日志分析插件开发全景概览VSCode 2026 版本引入了全新设计的日志分析扩展框架&#xff08;Log Analysis Extension Framework, LAF&#xff09;&#xff0c;专为高吞吐、多源异构日志的实时解析与可视化而构建。该框架深度集成 Language Server P…

作者头像 李华
网站建设 2026/4/8 22:20:59

Git版本控制在深度学习项目中的高级应用

Git版本控制在深度学习项目中的高级应用 1. 为什么深度学习项目特别需要Git高级用法 在日常的深度学习开发中&#xff0c;很多人把Git当作简单的代码备份工具——改完代码就git add . && git commit -m "update"&#xff0c;训练完模型随手保存成model_v2.…

作者头像 李华
网站建设 2026/4/11 13:48:06

ChatGLM3-6B算力适配:GPU利用率提升300%的技术解析

ChatGLM3-6B算力适配&#xff1a;GPU利用率提升300%的技术解析 1. 为什么“零延迟”不是口号&#xff0c;而是可量化的工程结果&#xff1f; 很多人第一次听说“本地部署ChatGLM3-6B实现零延迟”&#xff0c;第一反应是&#xff1a;这可能吗&#xff1f;毕竟6B参数模型在消费…

作者头像 李华
网站建设 2026/4/16 11:06:33

GTE+SeqGPT多场景应用:技术文档智能问答、HR政策检索、产品FAQ自动生成

GTESeqGPT多场景应用&#xff1a;技术文档智能问答、HR政策检索、产品FAQ自动生成 你有没有遇到过这些情况&#xff1a;新员工入职后反复问“年假怎么休”&#xff0c;客服每天回答上百遍“退货流程是什么”&#xff0c;或者研发同事花两小时翻遍Wiki才找到某个API的调用限制&…

作者头像 李华
网站建设 2026/4/16 9:02:17

CLAP特征可视化解析:音频语义空间的奥秘

CLAP特征可视化解析&#xff1a;音频语义空间的奥秘 1. 听得见的语义世界 你有没有想过&#xff0c;当模型"听"到一段狗叫声时&#xff0c;它在想什么&#xff1f;不是简单地匹配"狗"这个字&#xff0c;而是真正理解那种短促、高频、略带兴奋的声波模式&…

作者头像 李华
网站建设 2026/4/16 11:12:53

DeepSeek-OCR-2从零开始:3步完成OCR服务本地化部署(GPU优化版)

DeepSeek-OCR-2从零开始&#xff1a;3步完成OCR服务本地化部署&#xff08;GPU优化版&#xff09; 你是不是也遇到过这些情况&#xff1a; 手里有一堆扫描版PDF合同、发票、教材&#xff0c;想快速提取文字却卡在识别不准、排版错乱、公式丢失上&#xff1f;用在线OCR工具担心…

作者头像 李华