当前位置: 首页 > article >正文

分布式锁:实现原理与最佳实践

分布式锁实现原理与最佳实践核心概念分布式锁是分布式系统中用于协调多个节点访问共享资源的机制。在分布式环境下传统的单机锁如 synchronized、ReentrantLock无法跨进程工作需要使用分布式锁来保证数据一致性。分布式锁的特性互斥性同一时刻只有一个客户端持有锁高可用锁服务本身必须高可用容错性即使客户端崩溃锁也能自动释放性能获取和释放锁的操作应该快速Redis 分布式锁// Redis 分布式锁实现 Component public class RedisDistributedLock { private final StringRedisTemplate redisTemplate; private static final String LOCK_PREFIX lock:; private static final long DEFAULT_EXPIRE_TIME 30000; // 30秒 public RedisDistributedLock(StringRedisTemplate redisTemplate) { this.redisTemplate redisTemplate; } public boolean tryLock(String key) { return tryLock(key, DEFAULT_EXPIRE_TIME); } public boolean tryLock(String key, long expireTime) { String lockKey LOCK_PREFIX key; String value UUID.randomUUID().toString(); Boolean success redisTemplate.opsForValue() .setIfAbsent(lockKey, value, expireTime, TimeUnit.MILLISECONDS); return Boolean.TRUE.equals(success); } public boolean tryLock(String key, long waitTime, long expireTime) throws InterruptedException { String lockKey LOCK_PREFIX key; String value UUID.randomUUID().toString(); long startTime System.currentTimeMillis(); while (System.currentTimeMillis() - startTime waitTime) { Boolean success redisTemplate.opsForValue() .setIfAbsent(lockKey, value, expireTime, TimeUnit.MILLISECONDS); if (Boolean.TRUE.equals(success)) { return true; } Thread.sleep(100); } return false; } public void unlock(String key) { String lockKey LOCK_PREFIX key; redisTemplate.delete(lockKey); } public void unlock(String key, String value) { String lockKey LOCK_PREFIX key; redisTemplate.execute((RedisCallbackObject) connection - { byte[] keyBytes lockKey.getBytes(StandardCharsets.UTF_8); byte[] valueBytes value.getBytes(StandardCharsets.UTF_8); if (Arrays.equals(connection.get(keyBytes), valueBytes)) { connection.del(keyBytes); } return null; }); } } // 使用 Redis 分布式锁 Service public class OrderService { private final RedisDistributedLock distributedLock; private final OrderRepository orderRepository; public OrderService(RedisDistributedLock distributedLock, OrderRepository orderRepository) { this.distributedLock distributedLock; this.orderRepository orderRepository; } public Order createOrder(Long userId, Long productId) { String lockKey order:create: userId : productId; try { if (distributedLock.tryLock(lockKey, 5000, 30000)) { // 执行业务逻辑 return createOrderInternal(userId, productId); } else { throw new RuntimeException(Too many requests, please try again later); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(Lock acquisition interrupted); } finally { distributedLock.unlock(lockKey); } } private Order createOrderInternal(Long userId, Long productId) { // 检查库存、创建订单等业务逻辑 Order order new Order(); order.setUserId(userId); order.setProductId(productId); return orderRepository.save(order); } }Redlock 算法// Redlock 分布式锁实现 Component public class RedlockDistributedLock { private final ListStringRedisTemplate redisTemplates; private static final int QUORUM 3; private static final long DEFAULT_EXPIRE_TIME 30000; public RedlockDistributedLock(ListStringRedisTemplate redisTemplates) { this.redisTemplates redisTemplates; } public boolean tryLock(String key) { return tryLock(key, DEFAULT_EXPIRE_TIME); } public boolean tryLock(String key, long expireTime) { String lockKey redlock: key; String value UUID.randomUUID().toString(); int successCount 0; long startTime System.currentTimeMillis(); for (StringRedisTemplate template : redisTemplates) { try { Boolean success template.opsForValue() .setIfAbsent(lockKey, value, expireTime, TimeUnit.MILLISECONDS); if (Boolean.TRUE.equals(success)) { successCount; } } catch (Exception e) { // 忽略单个节点的故障 } } long elapsedTime System.currentTimeMillis() - startTime; long remainingTime expireTime - elapsedTime; // 满足 quorum 且剩余时间足够 return successCount QUORUM remainingTime 0; } public void unlock(String key) { String lockKey redlock: key; for (StringRedisTemplate template : redisTemplates) { try { template.delete(lockKey); } catch (Exception e) { // 忽略单个节点的故障 } } } }ZooKeeper 分布式锁// ZooKeeper 分布式锁实现 Component public class ZkDistributedLock { private final CuratorFramework client; private static final String LOCK_PATH /locks; public ZkDistributedLock(CuratorFramework client) { this.client client; ensurePathExists(); } private void ensurePathExists() { try { if (client.checkExists().forPath(LOCK_PATH) null) { client.create().creatingParentsIfNeeded().forPath(LOCK_PATH); } } catch (Exception e) { throw new RuntimeException(Failed to create lock path, e); } } public void lock(String key) throws Exception { String lockPath LOCK_PATH / key; String nodePath client.create() .creatingParentsIfNeeded() .withMode(CreateMode.EPHEMERAL_SEQUENTIAL) .forPath(lockPath); ListString children client.getChildren().forPath(LOCK_PATH); Collections.sort(children); String currentNode nodePath.substring(LOCK_PATH.length() 1); int index children.indexOf(currentNode); while (index ! 0) { String watchPath LOCK_PATH / children.get(index - 1); CountDownLatch latch new CountDownLatch(1); Watcher watcher event - { if (event.getType() Watcher.Event.EventType.NodeDeleted) { latch.countDown(); } }; client.getData().usingWatcher(watcher).forPath(watchPath); latch.await(); children client.getChildren().forPath(LOCK_PATH); Collections.sort(children); index children.indexOf(currentNode); } } public void unlock(String key) throws Exception { String lockPath LOCK_PATH / key; ListString children client.getChildren().forPath(LOCK_PATH); for (String child : children) { if (child.startsWith(key)) { client.delete().forPath(LOCK_PATH / child); } } } } // 使用 ZooKeeper 分布式锁 Service public class InventoryService { private final ZkDistributedLock zkLock; private final InventoryRepository inventoryRepository; public InventoryService(ZkDistributedLock zkLock, InventoryRepository inventoryRepository) { this.zkLock zkLock; this.inventoryRepository inventoryRepository; } public boolean decreaseStock(Long productId, int quantity) { String lockKey inventory: productId; try { zkLock.lock(lockKey); Inventory inventory inventoryRepository.findByProductId(productId) .orElseThrow(() - new RuntimeException(Inventory not found)); if (inventory.getStock() quantity) { inventory.setStock(inventory.getStock() - quantity); inventoryRepository.save(inventory); return true; } return false; } catch (Exception e) { throw new RuntimeException(Failed to decrease stock, e); } finally { try { zkLock.unlock(lockKey); } catch (Exception e) { // 忽略解锁异常 } } } }MySQL 分布式锁// MySQL 分布式锁实现 Component public class MysqlDistributedLock { private final JdbcTemplate jdbcTemplate; public MysqlDistributedLock(JdbcTemplate jdbcTemplate) { this.jdbcTemplate jdbcTemplate; } public boolean tryLock(String key, long expireTime) { String sql INSERT INTO distributed_locks (lock_key, lock_value, expire_time) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE lock_value IF(expire_time NOW(), VALUES(lock_value), lock_value), expire_time IF(expire_time NOW(), VALUES(expire_time), expire_time) ; String value UUID.randomUUID().toString(); LocalDateTime expireTime LocalDateTime.now().plusNanos(expireTime * 1_000_000); int affectedRows jdbcTemplate.update(sql, key, value, expireTime); return affectedRows 0; } public void unlock(String key) { String sql DELETE FROM distributed_locks WHERE lock_key ?; jdbcTemplate.update(sql, key); } } // MySQL 锁表结构 // CREATE TABLE distributed_locks ( // lock_key VARCHAR(255) PRIMARY KEY, // lock_value VARCHAR(255) NOT NULL, // expire_time DATETIME NOT NULL, // created_at DATETIME DEFAULT CURRENT_TIMESTAMP // );分布式锁的优化// 带看门狗的分布式锁 Component public class WatchdogDistributedLock { private final StringRedisTemplate redisTemplate; private final ScheduledExecutorService scheduler Executors.newScheduledThreadPool(4); private static final String LOCK_PREFIX watchdog:lock:; public WatchdogDistributedLock(StringRedisTemplate redisTemplate) { this.redisTemplate redisTemplate; } public boolean tryLock(String key, long expireTime) { String lockKey LOCK_PREFIX key; String value UUID.randomUUID().toString(); Boolean success redisTemplate.opsForValue() .setIfAbsent(lockKey, value, expireTime, TimeUnit.MILLISECONDS); if (Boolean.TRUE.equals(success)) { // 启动看门狗定时续期 scheduleWatchdog(key, value, expireTime); } return Boolean.TRUE.equals(success); } private void scheduleWatchdog(String key, String value, long expireTime) { scheduler.scheduleAtFixedRate(() - { String lockKey LOCK_PREFIX key; redisTemplate.execute((RedisCallbackObject) connection - { byte[] keyBytes lockKey.getBytes(StandardCharsets.UTF_8); byte[] valueBytes value.getBytes(StandardCharsets.UTF_8); if (Arrays.equals(connection.get(keyBytes), valueBytes)) { connection.expire(keyBytes, expireTime / 1000); } return null; }); }, expireTime / 3, expireTime / 3, TimeUnit.MILLISECONDS); } public void unlock(String key) { String lockKey LOCK_PREFIX key; redisTemplate.delete(lockKey); } } // 可重入分布式锁 Component public class ReentrantDistributedLock { private final StringRedisTemplate redisTemplate; private static final String LOCK_PREFIX reentrant:lock:; private static final String COUNTER_PREFIX reentrant:counter:; public ReentrantDistributedLock(StringRedisTemplate redisTemplate) { this.redisTemplate redisTemplate; } public boolean tryLock(String key, String ownerId) { String lockKey LOCK_PREFIX key; String counterKey COUNTER_PREFIX key : ownerId; Boolean lockAcquired redisTemplate.opsForValue() .setIfAbsent(lockKey, ownerId, 30000, TimeUnit.MILLISECONDS); if (Boolean.TRUE.equals(lockAcquired)) { redisTemplate.opsForValue().set(counterKey, 1); return true; } // 检查是否是同一个持有者 String currentOwner redisTemplate.opsForValue().get(lockKey); if (ownerId.equals(currentOwner)) { redisTemplate.opsForValue().increment(counterKey); return true; } return false; } public void unlock(String key, String ownerId) { String counterKey COUNTER_PREFIX key : ownerId; String countStr redisTemplate.opsForValue().get(counterKey); if (countStr ! null) { int count Integer.parseInt(countStr); if (count 1) { redisTemplate.opsForValue().decrement(counterKey); } else { String lockKey LOCK_PREFIX key; redisTemplate.delete(lockKey); redisTemplate.delete(counterKey); } } } }最佳实践设置合理的过期时间根据业务执行时间设置过期时间使用唯一标识使用 UUID 等唯一标识作为锁的值防止误删看门狗机制对于长时间运行的任务使用看门狗自动续期异常处理确保在异常情况下也能释放锁选择合适的实现根据业务场景选择 Redis、ZooKeeper 或数据库实现监控告警监控锁的获取和释放情况设置告警优雅降级在锁获取失败时提供降级方案对比与选择特性RedisZooKeeperMySQL性能高中低可靠性中高高实现复杂度低高低适用场景高并发、短锁分布式协调、长锁低并发、简单场景总结分布式锁是分布式系统中不可或缺的组件。选择合适的分布式锁实现需要综合考虑性能、可靠性和实现复杂度。在实际应用中需要根据业务场景选择合适的方案并做好异常处理和监控。别叫我大神叫我 Alex 就好。这其实可以更优雅一点合理的分布式锁设计让系统变得更加可靠和高效。

相关文章:

分布式锁:实现原理与最佳实践

分布式锁:实现原理与最佳实践 核心概念 分布式锁是分布式系统中用于协调多个节点访问共享资源的机制。在分布式环境下,传统的单机锁(如 synchronized、ReentrantLock)无法跨进程工作,需要使用分布式锁来保证数据一致性…...

前端动画实战:基于Vite构建打字机、光标与粒子特效网页应用

1. 项目概述与核心思路最近在整理个人作品集时,想做一个能让人眼前一亮的“关于我”页面。静态的文字介绍太乏味,直接放视频又显得有点“重”。于是,我琢磨着能不能把那种老式打字机“咔哒咔哒”敲出文字的感觉搬到网页上,再配上一…...

数据库分库分表:策略设计与实现

数据库分库分表:策略设计与实现 核心概念 随着业务增长,单库单表会成为性能瓶颈。分库分表是一种水平扩展方案,通过将数据分散到多个数据库或表中,提高系统的吞吐量和可用性。 分库分表策略 1. 垂直分库 // 垂直分库&#xf…...

Java 响应式编程:Reactor 框架深度解析

Java 响应式编程:Reactor 框架深度解析 核心概念 响应式编程是一种编程范式,关注数据的异步流和变化传播。在 Java 中,Reactor 框架提供了强大的响应式编程支持,基于 Reactive Streams 规范实现。 Reactor 核心组件 Mono&#xff…...

ComfyUI-Manager终极指南:轻松管理您的AI绘画工作流节点

ComfyUI-Manager终极指南:轻松管理您的AI绘画工作流节点 【免费下载链接】ComfyUI-Manager ComfyUI-Manager is an extension designed to enhance the usability of ComfyUI. It offers management functions to install, remove, disable, and enable various cus…...

基于LLM与向量数据库构建个人知识管理智能代理:从原理到实践

1. 项目概述:一个面向个人知识管理的智能代理 最近在折腾个人知识管理(PKM)系统,发现了一个挺有意思的开源项目: lessthanno/engram-agent 。简单来说,这是一个“记忆代理”,它旨在成为你数字…...

为什么选择QtScrcpy?3大突破性特性让Android投屏焕然一新

为什么选择QtScrcpy?3大突破性特性让Android投屏焕然一新 【免费下载链接】QtScrcpy Android real-time display control software 项目地址: https://gitcode.com/GitHub_Trending/qt/QtScrcpy QtScrcpy是一款基于Qt框架开发的Android设备实时投屏控制软件&…...

基于Tauri+React+TS构建跨平台开发者效率工具:集成AI编程与Git Worktree

1. 项目概述:一个为现代开发者打造的桌面效率工具 如果你和我一样,每天的工作流都离不开终端、代码编辑器和各种AI助手,那你一定也经历过这种场景:在多个项目间频繁切换,终端里塞满了十几个标签页,想找个昨…...

一文扫盲人工智能全体系,从入门到进阶,新手也能不迷路

文章目录前言一、先搞懂:AI到底是个啥?别再把大模型当AI全部了1.1 从“假智能”到“真智能”:神经网络的革命1.2 AI的三大发展阶段:从弱人工智能到超人工智能二、AI核心技术栈拆解:从基础到进阶,一层一层讲…...

CANN/atvoss Muls算子样例

Muls算子样例 【免费下载链接】atvoss ATVOSS(Ascend C Templates for Vector Operator Subroutines)是一套基于Ascend C开发的Vector算子库,致力于为昇腾硬件上的Vector类融合算子提供极简、高效、高性能、高拓展的编程方式。 项目地址: h…...

为OpenClaw智能体工作流配置Taotoken作为可靠模型供应商

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为OpenClaw智能体工作流配置Taotoken作为可靠模型供应商 在构建基于OpenClaw的智能体工作流时,一个稳定、可管理的模型…...

大模型API聚合服务:一站式解决多模型接入难题

1. 项目概述:一站式大模型API聚合服务如果你正在开发一个需要集成多种大语言模型的应用,比如一个智能客服系统、一个内容创作工具,或者一个AI研究平台,那么你大概率会遇到一个非常现实的问题:对接不同厂商的API&#x…...

CANN/triton-ge-backend性能调优方法论

性能调优方法论 【免费下载链接】triton-inference-server-ge-backend ge-backend基于triton inference server框架实现对接NPU生态,快速实现传统CV\NLP等模型的服务化。 项目地址: https://gitcode.com/cann/triton-inference-server-ge-backend 模型优化有…...

AI算法在多市场环境下的合谋机制与市场分配策略研究

1. 项目概述:当AI成为市场中的“隐形玩家”最近几年,我身边不少做量化交易、电商定价或者供应链优化的朋友,都开始频繁地讨论一个话题:我们部署的AI优化算法,会不会在不知不觉中“串通”起来,形成一种新型的…...

开源项目赞助管理平台Sponsio:自托管部署与核心架构解析

1. 项目概述:SponsioLabs/Sponsio 是什么?如果你在开源社区里泡过一段时间,肯定对“用爱发电”这个词不陌生。开发者们投入大量时间、精力,甚至金钱,维护一个项目,却常常面临一个现实问题:如何获…...

Animal-AI环境:用AI复现动物认知实验的虚拟实验室

1. 项目概述:当AI遇见动物智能最近几年,AI领域最激动人心的进展之一,就是智能体(Agent)在复杂环境中的决策与学习能力。从AlphaGo到AlphaStar,再到各种游戏AI,我们见证了算法在特定规则下的卓越…...

数字孪生如何破解AI预测性维护的可解释性与泛化难题

1. 项目概述:当数字孪生遇见AI预测性维护在工业界摸爬滚打十几年,我亲眼见证了维护策略从“坏了再修”到“定期保养”,再到如今炙手可热的“预测性维护”的演进。预测性维护(Predictive Maintenance, PMx)的核心愿景很…...

10x-Agent-Loop:突破AI编程助手配额限制的智能缓存与调度方案

1. 项目概述与核心价值最近在开发者社区里,一个名为“10x-Agent-Loop”的工具讨论热度挺高。简单来说,它瞄准了一个非常具体的痛点:当你深度依赖像Cursor或Windsurf这类AI编程助手时,经常会遇到一个天花板——请求配额限制。无论是…...

ATB RingMLA C++示例

加速库RingMLA C Demo 【免费下载链接】ascend-transformer-boost 本项目是CANN提供的是一款高效、可靠的Transformer加速库,基于华为Ascend AI处理器,提供Transformer定制化场景的高性能融合算子。 项目地址: https://gitcode.com/cann/ascend-transf…...

Python 爬虫高级实战:网盘资源信息批量爬虫开发

前言 在互联网资源分发场景中,网盘已成为文档、教程、软件、影视、学习资料等资源的核心存储与分发载体。海量公开网盘资源分散在各类资源站点、论坛、分享页面中,依靠人工逐条检索、整理链接效率极低,且难以实现批量汇总、分类归档与失效链接筛查。依托 Python 开发网盘资…...

艺术史视角下的生成式AI审美:从风格谱系到技术认知的深度解析

1. 项目概述:当艺术史遇见生成式AI最近和几位做艺术策展的朋友聊天,他们都在抱怨同一个问题:现在用AI生成的“艺术品”越来越多,但很多作品看起来就是一堆流行元素的拼贴,缺乏真正的“灵魂”。这让我开始思考一个更深层…...

泊松分布实战指南:从原理到异常检测的工程落地

1. 什么是泊松分布?——一个数据从业者每天都在用、却未必真正吃透的概率工具你有没有算过,过去一小时里你的邮箱收到了几封新邮件?上个月车间里产线上出现了几个次品?过去24小时网站服务器收到了多少次API请求?这些数…...

Fortran学习笔记

这是我之前学习Fortran时做到笔记,分享出来当个备份!Fortran是一门非常古老的编程语言,但是至今依然有人在使用。建议利用闲暇时间学习!1、编译命令: g95 –c a.f90:将a.f90编译为名为a.o的目标文件。 g95 h.f90&#…...

AI跨学科扩散62年文献计量分析:从计算机科学到生物医学、社会科学的融合路径与未来趋势

1. 项目概述:从海量文献中洞察AI的融合之路最近几年,AI(人工智能)这个词几乎无处不在,从写代码到画图,从自动驾驶到药物研发,它像水银泻地一样渗透进各个角落。但你是否想过,这种“渗…...

网络异质性如何影响AI竞赛中的安全与创新平衡

1. 项目概述:一场关于“网络生态”的AI竞赛 最近和几个做AI安全的朋友聊天,大家不约而同地提到了一个现象:现在很多AI竞赛,无论是安全攻防赛还是创新应用赛,参赛团队的背景越来越“杂”。你可能会遇到一支队伍&#xf…...

Poetry依赖管理:用SAT求解器终结Python版本冲突

1. 为什么我三年前就停用 pip venv,转而把 Poetry 当成 Python 项目的“呼吸系统”你有没有经历过这样的深夜:凌晨两点,服务器上一个本该稳如老狗的 Flask API 突然报ImportError: cannot import name AsyncGenerator;你翻遍代码…...

深度学习超分辨率技术加速SEM材料表征:原理、实践与16倍效率提升

1. 项目概述:当深度学习遇见扫描电镜在材料科学的研究一线,尤其是金属微观结构分析领域,扫描电子显微镜(SEM)是我们观察材料“内在世界”的得力工具。然而,一个长期困扰我们的矛盾是:高分辨率与…...

OpenClaw安全审计:AI驱动的自动化配置检查与隐私保护实践

1. 项目概述与核心价值 最近在折腾我的 OpenClaw 机器人,这玩意儿功能是越来越强大了,能接各种消息渠道,还能调用五花八门的工具。但功能一多,配置就复杂,安全问题也跟着冒头。比如,你是不是也担心过 API 密…...

基于MCP协议构建AI与Telegram的智能连接桥梁

1. 项目概述:一个连接AI与即时通讯的桥梁 最近在折腾AI应用开发,特别是想让大语言模型(LLM)能直接操作外部工具,比如发个消息、查个天气。这让我接触到了 Model Context Protocol ,也就是MCP。简单来说&…...

Claude Code用户如何配置Taotoken解决密钥不稳定与额度不足问题

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Claude Code用户如何配置Taotoken解决密钥不稳定与额度不足问题 1. 理解Claude Code的API配置机制 Claude Code作为一款编程辅助工…...