🔒 从单机到分布式:三大锁机制深度剖析与实战指南
在当今高并发和分布式系统架构中,锁机制是确保数据一致性和系统稳定性的核心技术。本文将深入解析三种重要的锁技术,带你从底层原理到实战应用,全面掌握并发控制的精髓。
🎯 技术选型速览
| 锁类型 | 适用场景 | 性能特点 | 一致性强度 | 学习成本 |
|---|---|---|---|---|
| Synchronized | 单机应用并发控制 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐ |
| MySQL FOR UPDATE | 数据库事务操作 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| Redisson | 分布式系统协调 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
1. 🔥 Java Synchronized:单机高并发的最优解
1.1 🏗️ 底层架构深度解析
对象内存布局与锁状态:
java
// 对象头结构详解(64位JVM)
public class ObjectHeader {
// Mark Word (64位) 结构
// |--------------------------------------------------------------------|
// | unused:25 | identity_hashcode:31 | unused:1 | age:4 | lock:2 |
// |--------------------------------------------------------------------|
// 锁状态标志位
static class LockState {
static final int UNLOCKED = 0b001; // 无锁
static final int LIGHTWEIGHT = 0b000; // 轻量级锁
static final int HEAVYWEIGHT = 0b010; // 重量级锁
static final int BIASED = 0b101; // 偏向锁
}
}
锁升级的完整历程:
java
public class LockUpgradeProcess {
// 偏向锁获取流程
public void biasedLockAcquisition(Object obj, Thread currentThread) {
// 检查对象是否可偏向
if (!obj.isBiasedLockable()) return;
// CAS操作:将线程ID写入对象头
while (true) {
long expectedMarkWord = obj.getMarkWord();
if (isBiasedLocked(expectedMarkWord)) {
// 已偏向,检查是否为当前线程
if (getThreadId(expectedMarkWord) == currentThread.getId()) {
return; // 重入成功
} else {
// 存在竞争,开始撤销偏向锁
revokeBiasedLock(obj);
break;
}
} else {
// 尝试获取偏向锁
long newMarkWord = setBiasedLock(expectedMarkWord, currentThread);
if (CAS(obj.markWord, expectedMarkWord, newMarkWord)) {
return; // 偏向锁获取成功
}
}
}
}
// 轻量级锁竞争机制
public void lightweightLockCompetition(Object obj, Thread currentThread) {
// 在当前线程栈中创建Lock Record
LockRecord lockRecord = currentThread.createLockRecord();
// 复制对象头到Lock Record(用于解锁时恢复)
lockRecord.displacedHeader = obj.getMarkWord();
// CAS竞争:将对象头指向Lock Record
while (true) {
if (CAS(obj.markWord, lockRecord.displacedHeader,
encodeLockRecord(lockRecord))) {
return; // 轻量级锁获取成功
} else {
// 竞争失败,检查是否锁膨胀
if (isLockInflated(obj)) {
// 已升级为重量级锁,进入等待队列
enterWaitingQueue(obj, currentThread);
return;
}
}
}
}
}
1.2 💼 实战场景与代码实现
场景1:高性能缓存系统
java
/**
* 🚀 高性能线程安全缓存实现
* 适用场景:本地缓存、配置信息缓存、热点数据缓存
*/
public class HighPerformanceCache {
private final Map<String, CacheEntry> cache = new HashMap<>();
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
// 缓存条目定义
private static class CacheEntry {
private final Object value;
private final long expireTime;
private final AtomicInteger accessCount = new AtomicInteger(0);
public CacheEntry(Object value, long ttl) {
this.value = value;
this.expireTime = System.currentTimeMillis() + ttl;
}
public boolean isExpired() {
return System.currentTimeMillis() > expireTime;
}
}
/**
* 🔒 使用synchronized保证缓存更新的强一致性
*/
public synchronized Object get(String key) {
CacheEntry entry = cache.get(key);
// 双重检查:防止缓存击穿
if (entry == null || entry.isExpired()) {
synchronized (this) {
// 再次检查,避免重复加载
entry = cache.get(key);
if (entry == null || entry.isExpired()) {
// 🎯 缓存未命中,从数据源加载
Object value = loadFromDataSource(key);
entry = new CacheEntry(value, TimeUnit.MINUTES.toMillis(30));
cache.put(key, entry);
log.info("缓存加载完成: {}", key);
}
}
}
// 记录访问统计
entry.accessCount.incrementAndGet();
return entry.value;
}
/**
* 📊 批量缓存预热 - 保证原子性
*/
public synchronized void batchPut(Map<String, Object> data, long ttl) {
long startTime = System.currentTimeMillis();
for (Map.Entry<String, Object> entry : data.entrySet()) {
CacheEntry cacheEntry = new CacheEntry(entry.getValue(), ttl);
cache.put(entry.getKey(), cacheEntry);
}
log.info("批量缓存预热完成,数量: {},耗时: {}ms",
data.size(), System.currentTimeMillis() - startTime);
}
/**
* 🧹 缓存清理机制
*/
public synchronized void cleanup() {
int initialSize = cache.size();
cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
log.info("缓存清理完成,清理前: {},清理后: {}", initialSize, cache.size());
}
private Object loadFromDataSource(String key) {
// 模拟从数据库或远程服务加载数据
try {
Thread.sleep(100); // 模拟网络延迟
return "data_for_" + key + "_" + System.currentTimeMillis();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("数据加载被中断", e);
}
}
}
场景2:电商订单状态管理
java
/**
* 🛒 电商订单状态机管理
* 适用场景:订单流程控制、状态转换验证、并发状态更新
*/
public class OrderStateManager {
private final Map<Long, Order> orderRepository = new ConcurrentHashMap<>();
private final AtomicLong sequenceGenerator = new AtomicLong(1000);
// 订单状态定义
public enum OrderStatus {
PENDING, // 待支付
PAID, // 已支付
SHIPPED, // 已发货
DELIVERED, // 已送达
COMPLETED, // 已完成
CANCELLED // 已取消
}
// 订单实体
@Data
public static class Order {
private Long id;
private OrderStatus status;
private String userId;
private BigDecimal amount;
private Date createTime;
private Date updateTime;
private List<StatusTransition> transitionHistory = new ArrayList<>();
}
// 状态转换记录
@Data
public static class StatusTransition {
private OrderStatus fromStatus;
private OrderStatus toStatus;
private Date transitionTime;
private String operator;
private String remark;
}
/**
* 🔄 安全的订单状态转换
* 使用synchronized保证状态转换的原子性和一致性
*/
public synchronized boolean transitionOrderStatus(Long orderId,
OrderStatus fromStatus, OrderStatus toStatus, String operator) {
Order order = orderRepository.get(orderId);
if (order == null) {
log.warn("订单不存在: {}", orderId);
return false;
}
// 验证当前状态是否符合预期
if (order.getStatus() != fromStatus) {
log.warn("订单状态不匹配,期望: {},实际: {}", fromStatus, order.getStatus());
return false;
}
// 验证状态转换是否合法
if (!isValidTransition(fromStatus, toStatus)) {
log.warn("非法的状态转换: {} -> {}", fromStatus, toStatus);
return false;
}
// 执行状态转换
OrderStatus oldStatus = order.getStatus();
order.setStatus(toStatus);
order.setUpdateTime(new Date());
// 记录状态转换历史
StatusTransition transition = new StatusTransition();
transition.setFromStatus(oldStatus);
transition.setToStatus(toStatus);
transition.setTransitionTime(new Date());
transition.setOperator(operator);
transition.setRemark("系统自动转换");
order.getTransitionHistory().add(transition);
log.info("订单状态转换成功: {} [{} -> {}]", orderId, oldStatus, toStatus);
return true;
}
/**
* 🎯 批量订单状态更新
* 适用于:批量确认收货、批量取消订单等场景
*/
public synchronized BatchResult batchUpdateStatus(List<Long> orderIds,
OrderStatus newStatus, String operator) {
BatchResult result = new BatchResult();
for (Long orderId : orderIds) {
try {
Order order = orderRepository.get(orderId);
if (order != null) {
OrderStatus oldStatus = order.getStatus();
if (transitionOrderStatus(orderId, oldStatus, newStatus, operator)) {
result.addSuccess(orderId);
} else {
result.addFailure(orderId, "状态转换失败");
}
} else {
result.addFailure(orderId, "订单不存在");
}
} catch (Exception e) {
log.error("批量更新订单状态异常: {}", orderId, e);
result.addFailure(orderId, "系统异常: " + e.getMessage());
}
}
log.info("批量状态更新完成: 成功={}, 失败={}",
result.getSuccessCount(), result.getFailureCount());
return result;
}
// 状态转换验证规则
private boolean isValidTransition(OrderStatus from, OrderStatus to) {
Map<OrderStatus, Set<OrderStatus>> validTransitions = Map.of(
OrderStatus.PENDING, Set.of(OrderStatus.PAID, OrderStatus.CANCELLED),
OrderStatus.PAID, Set.of(OrderStatus.SHIPPED, OrderStatus.CANCELLED),
OrderStatus.SHIPPED, Set.of(OrderStatus.DELIVERED),
OrderStatus.DELIVERED, Set.of(OrderStatus.COMPLETED)
);
return validTransitions.getOrDefault(from, Collections.emptySet())
.contains(to);
}
// 批量处理结果
@Data
public static class BatchResult {
private List<Long> successOrders = new ArrayList<>();
private Map<Long, String> failureOrders = new HashMap<>();
public void addSuccess(Long orderId) {
successOrders.add(orderId);
}
public void addFailure(Long orderId, String reason) {
failureOrders.put(orderId, reason);
}
public int getSuccessCount() {
return successOrders.size();
}
public int getFailureCount() {
return failureOrders.size();
}
}
}
2. 💾 MySQL FOR UPDATE:数据库层面的强一致性守护者
2.1 🏛️ 架构原理深度探索
InnoDB锁系统核心架构:
sql
-- InnoDB锁内存结构伪代码表示
-- 锁表结构
CREATE TABLE `innodb_lock_struct` (
`lock_trx` BIGINT, -- 事务ID
`lock_type` ENUM('RECORD','TABLE','GAP','NEXT_KEY'), -- 锁类型
`lock_mode` ENUM('S','X','IS','IX'), -- 锁模式
`lock_space` INT, -- 表空间ID
`lock_page` BIGINT, -- 页号
`lock_rec` BIGINT, -- 记录号
`lock_data` VARCHAR(255) -- 锁定数据
);
锁兼容性矩阵详解:
java
public class LockCompatibilityMatrix {
/**
* 🎯 MySQL锁兼容性矩阵
*
* 锁模式说明:
* - IS: 意向共享锁
* - IX: 意向排他锁
* - S: 共享锁
* - X: 排他锁
*
* 兼容性矩阵:
* | IS | IX | S | X
* ------|----|----|----|----
* IS | ✅ | ✅ | ✅ | ❌
* IX | ✅ | ✅ | ❌ | ❌
* S | ✅ | ❌ | ✅ | ❌
* X | ❌ | ❌ | ❌ | ❌
*/
public boolean isCompatible(LockMode existing, LockMode requested) {
boolean[][] compatibility = {
// IS, IX, S, X
{true, true, true, false}, // IS
{true, true, false, false}, // IX
{true, false, true, false}, // S
{false, false, false, false} // X
};
return compatibility[existing.ordinal()][requested.ordinal()];
}
}
2.2 🏪 电商库存管理实战
场景1:秒杀库存控制
java
/**
* 🎯 高并发库存管理系统
* 适用场景:秒杀活动、限时抢购、库存扣减
*/
@Service
@Transactional
public class InventoryManagementService {
private static final int MAX_RETRY_TIMES = 3;
@Autowired
private InventoryMapper inventoryMapper;
@Autowired
private InventoryOperationLogMapper logMapper;
/**
* 🔥 秒杀库存扣减 - 解决超卖问题
* 使用FOR UPDATE保证库存扣减的强一致性
*/
public boolean seckillInventory(Long productId, Integer quantity, String userId) {
// 重试机制应对死锁
for (int retry = 0; retry < MAX_RETRY_TIMES; retry++) {
try {
// 🎯 锁定商品库存记录
Inventory inventory = inventoryMapper.selectForUpdate(productId);
if (inventory == null) {
throw new BusinessException("商品不存在: " + productId);
}
// 检查库存是否充足
if (inventory.getAvailableStock() < quantity) {
log.warn("库存不足,商品: {},需求: {},可用: {}",
productId, quantity, inventory.getAvailableStock());
return false;
}
// 执行库存扣减
int updateCount = inventoryMapper.deductStock(productId, quantity);
if (updateCount == 0) {
log.warn("库存扣减失败,可能已被其他事务修改");
continue; // 重试
}
// 记录库存操作日志
saveInventoryLog(inventory, quantity, "SECKILL", userId);
log.info("秒杀库存扣减成功,商品: {},数量: {},用户: {}",
productId, quantity, userId);
return true;
} catch (DeadlockLoserDataAccessException e) {
log.warn("检测到死锁,重试次数: {}", retry + 1);
if (retry == MAX_RETRY_TIMES - 1) {
throw new BusinessException("系统繁忙,请稍后重试");
}
// 指数退避
sleepExponentially(retry);
}
}
return false;
}
/**
* 📦 安全库存调整
* 防止并发调整导致的安全库存数据错误
*/
@Transactional(rollbackFor = Exception.class)
public boolean adjustSafeStock(Long productId, Integer newSafeStock, String operator) {
// 🎯 锁定库存记录
Inventory inventory = inventoryMapper.selectForUpdate(productId);
if (inventory == null) {
throw new BusinessException("库存记录不存在: " + productId);
}
// 验证当前库存是否满足新的安全库存要求
if (inventory.getCurrentStock() < newSafeStock) {
throw new BusinessException(
String.format("当前库存%d低于安全库存要求%d",
inventory.getCurrentStock(), newSafeStock)
);
}
// 记录原始值
Integer oldSafeStock = inventory.getSafeStock();
// 更新安全库存
inventory.setSafeStock(newSafeStock);
inventory.setUpdateTime(new Date());
inventoryMapper.updateSafeStock(inventory);
// 记录调整日志
saveSafeStockAdjustLog(productId, oldSafeStock, newSafeStock, operator);
log.info("安全库存调整成功,商品: {},{} -> {}",
productId, oldSafeStock, newSafeStock);
return true;
}
/**
* 🔄 批量库存锁定
* 适用于:预占库存、购物车下单等场景
*/
@Transactional(rollbackFor = Exception.class)
public boolean batchLockInventory(List<InventoryLockItem> lockItems, String orderNo) {
// 🎯 按照商品ID排序,避免死锁
lockItems.sort(Comparator.comparing(InventoryLockItem::getProductId));
for (InventoryLockItem item : lockItems) {
// 锁定单个商品库存
Inventory inventory = inventoryMapper.selectForUpdate(item.getProductId());
if (inventory.getAvailableStock() < item.getQuantity()) {
throw new BusinessException(
String.format("商品%s库存不足,需求: %d,可用: %d",
item.getProductId(), item.getQuantity(), inventory.getAvailableStock())
);
}
// 锁定库存
inventoryMapper.lockStock(item.getProductId(), item.getQuantity());
saveInventoryLockLog(inventory, item.getQuantity(), orderNo);
}
log.info("批量库存锁定成功,订单: {},商品数量: {}", orderNo, lockItems.size());
return true;
}
private void sleepExponentially(int retryCount) {
try {
Thread.sleep((long) (Math.pow(2, retryCount) * 1000));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void saveInventoryLog(Inventory inventory, Integer quantity,
String operation, String userId) {
InventoryOperationLog log = new InventoryOperationLog();
log.setProductId(inventory.getProductId());
log.setOperationType(operation);
log.setQuantity(quantity);
log.setBeforeStock(inventory.getAvailableStock() + quantity);
log.setAfterStock(inventory.getAvailableStock());
log.setOperator(userId);
log.setOperationTime(new Date());
logMapper.insert(log);
}
// 省略其他日志记录方法...
}
/**
* 📊 库存操作记录
*/
@Data
public class InventoryOperationLog {
private Long id;
private Long productId;
private String operationType; // SECKILL, PURCHASE, ADJUST, etc.
private Integer quantity;
private Integer beforeStock;
private Integer afterStock;
private String operator;
private Date operationTime;
}
/**
* 🔒 库存锁定项
*/
@Data
public class InventoryLockItem {
private Long productId;
private Integer quantity;
private Date expireTime; // 锁定过期时间
}
对应的Mapper实现:
java
@Mapper
public interface InventoryMapper {
/**
* 🎯 使用FOR UPDATE锁定库存记录
*/
@Select("SELECT * FROM inventory WHERE product_id = #{productId} FOR UPDATE")
Inventory selectForUpdate(Long productId);
/**
* 📉 库存扣减
*/
@Update("UPDATE inventory SET available_stock = available_stock - #{quantity}, " +
"locked_stock = locked_stock + #{quantity}, update_time = NOW() " +
"WHERE product_id = #{productId} AND available_stock >= #{quantity}")
int deductStock(@Param("productId") Long productId, @Param("quantity") Integer quantity);
/**
* 🔒 库存锁定
*/
@Update("UPDATE inventory SET available_stock = available_stock - #{quantity}, " +
"locked_stock = locked_stock + #{quantity} " +
"WHERE product_id = #{productId} AND available_stock >= #{quantity}")
int lockStock(@Param("productId") Long productId, @Param("quantity") Integer quantity);
/**
* 🛡️ 安全库存更新
*/
@Update("UPDATE inventory SET safe_stock = #{safeStock}, update_time = NOW() " +
"WHERE product_id = #{productId}")
int updateSafeStock(Inventory inventory);
}
3. 🌐 Redisson分布式锁:跨JVM的协调大师
3.1 🏗️ 分布式架构深度解析
Redisson锁核心算法:
lua
-- 🎯 Redisson加锁Lua脚本(完整版)
-- KEYS[1]: 锁的key
-- ARGV[1]: 锁超时时间(毫秒)
-- ARGV[2]: 客户端标识(UUID:threadId)
-- 检查锁是否存在
if (redis.call('exists', KEYS[1]) == 0) then
-- 创建锁:设置Hash字段和过期时间
redis.call('hset', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]);
return nil;
end;
-- 检查是否为重入锁
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then
-- 重入计数+1,刷新过期时间
redis.call('hincrby', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]);
return nil;
end;
-- 返回锁的剩余生存时间
return redis.call('pttl', KEYS[1]);
看门狗自动续期机制:
java
/**
* 🐕 Redisson看门狗机制实现
* 功能:自动续期分布式锁,防止业务执行时间超过锁过期时间
*/
public class WatchdogMechanism implements Runnable {
private static final long DEFAULT_WATCHDOG_TIMEOUT = 30 * 1000L; // 30秒
private static final long RENEWAL_INTERVAL = DEFAULT_WATCHDOG_TIMEOUT / 3;
private final String lockKey;
private final String lockValue;
private final RedissonClient redisson;
private volatile boolean running = true;
@Override
public void run() {
while (running && !Thread.currentThread().isInterrupted()) {
try {
// 🕒 等待续期间隔
Thread.sleep(RENEWAL_INTERVAL);
if (!running) break;
// 🔄 执行锁续期
boolean renewed = renewLock();
if (!renewed) {
log.warn("锁续期失败,锁可能已被释放: {}", lockKey);
break;
}
log.debug("锁续期成功: {}", lockKey);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
} catch (Exception e) {
log.error("看门狗执行异常", e);
// 继续尝试,不中断循环
}
}
log.info("看门狗线程结束: {}", lockKey);
}
/**
* 🎯 锁续期Lua脚本
*/
private boolean renewLock() {
String script =
"if (redis.call('hexists', KEYS[1], ARGV[1]) == 1) then " +
" redis.call('pexpire', KEYS[1], ARGV[2]); " +
" return 1; " +
"end; " +
"return 0;";
List<Object> result = redisson.getScript().eval(
script,
RScript.ReturnType.INTEGER,
Collections.singletonList(lockKey),
lockValue, DEFAULT_WATCHDOG_TIMEOUT
);
return Long.valueOf(1).equals(result.get(0));
}
public void stop() {
this.running = false;
}
}
3.2 🚀 分布式系统实战场景
场景1:分布式任务调度中心
java
/**
* 🎯 分布式任务调度系统
* 适用场景:集群任务调度、定时任务执行、分布式作业协调
*/
@Service
@Slf4j
public class DistributedTaskScheduler {
private static final String TASK_LOCK_PREFIX = "distributed:task:";
private static final String TASK_STATUS_PREFIX = "distributed:task:status:";
@Autowired
private RedissonClient redissonClient;
@Autowired
private TaskExecutionRecorder taskRecorder;
/**
* 🚀 执行分布式定时任务
* 确保在集群环境中同一时刻只有一个实例执行任务
*/
public TaskResult executeScheduledTask(String taskId, TaskExecutor executor) {
String lockKey = TASK_LOCK_PREFIX + taskId;
RLock lock = redissonClient.getLock(lockKey);
TaskResult result = new TaskResult(taskId);
long startTime = System.currentTimeMillis();
try {
// 🎯 尝试获取分布式锁
// waitTime: 最大等待时间5秒
// leaseTime: 锁持有时间30秒,启用看门狗自动续期
boolean acquired = lock.tryLock(5, 30, TimeUnit.SECONDS);
if (!acquired) {
log.warn("任务执行跳过,无法获取分布式锁: {}", taskId);
result.setStatus(TaskStatus.SKIPPED);
result.setMessage("无法获取执行锁");
return result;
}
try {
log.info("开始执行分布式任务: {}", taskId);
result.setStartTime(new Date(startTime));
// 检查任务是否正在执行(双重保险)
if (isTaskRunning(taskId)) {
log.warn("任务正在执行中,跳过本次执行: {}", taskId);
result.setStatus(TaskStatus.SKIPPED);
result.setMessage("任务正在执行中");
return result;
}
// 标记任务开始执行
markTaskRunning(taskId, true);
// 🎯 执行实际任务
Object taskResult = executor.execute();
long endTime = System.currentTimeMillis();
result.setEndTime(new Date(endTime));
result.setExecutionTime(endTime - startTime);
result.setStatus(TaskStatus.SUCCESS);
result.setData(taskResult);
log.info("分布式任务执行成功: {},耗时: {}ms",
taskId, endTime - startTime);
} finally {
// 清理任务执行状态
markTaskRunning(taskId, false);
if (lock.isHeldByCurrentThread()) {
lock.unlock();
log.debug("分布式锁释放: {}", taskId);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
result.setStatus(TaskStatus.INTERRUPTED);
result.setMessage("任务执行被中断");
log.warn("任务执行被中断: {}", taskId);
} catch (Exception e) {
result.setStatus(TaskStatus.FAILED);
result.setMessage("任务执行失败: " + e.getMessage());
log.error("任务执行失败: {}", taskId, e);
} finally {
// 记录任务执行结果
taskRecorder.recordTaskExecution(result);
}
return result;
}
/**
* 🔥 长时间任务执行支持
* 启用看门狗机制,自动续期锁
*/
public TaskResult executeLongRunningTask(String taskId, LongRunningTaskExecutor executor) {
String lockKey = TASK_LOCK_PREFIX + taskId;
RLock lock = redissonClient.getLock(lockKey);
TaskResult result = new TaskResult(taskId);
try {
// 🐕 不指定leaseTime,启用看门狗自动续期
lock.lock();
log.info("开始执行长时间任务: {}", taskId);
result.setStartTime(new Date());
// 执行长时间任务
Object taskResult = executor.execute();
result.setEndTime(new Date());
result.setStatus(TaskStatus.SUCCESS);
result.setData(taskResult);
log.info("长时间任务执行完成: {}", taskId);
} catch (Exception e) {
result.setStatus(TaskStatus.FAILED);
result.setMessage("长时间任务执行失败: " + e.getMessage());
log.error("长时间任务执行失败: {}", taskId, e);
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
return result;
}
/**
* 📊 获取任务执行状态
*/
public boolean isTaskRunning(String taskId) {
RAtomicLong status = redissonClient.getAtomicLong(TASK_STATUS_PREFIX + taskId);
return status.get() > System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(5);
}
private void markTaskRunning(String taskId, boolean running) {
RAtomicLong status = redissonClient.getAtomicLong(TASK_STATUS_PREFIX + taskId);
if (running) {
status.set(System.currentTimeMillis());
} else {
status.set(0L);
}
}
// 任务执行器接口
@FunctionalInterface
public interface TaskExecutor {
Object execute() throws Exception;
}
@FunctionalInterface
public interface LongRunningTaskExecutor {
Object execute() throws Exception;
}
// 任务执行结果
@Data
public static class TaskResult {
private final String taskId;
private TaskStatus status;
private String message;
private Object data;
private Date startTime;
private Date endTime;
private Long executionTime;
public TaskResult(String taskId) {
this.taskId = taskId;
}
}
// 任务状态枚举
public enum TaskStatus {
SUCCESS, FAILED, SKIPPED, INTERRUPTED
}
}
场景2:分布式资源协调器
java
/**
* 🌐 分布式资源协调服务
* 适用场景:多资源分配、读写分离控制、分布式配置管理
*/
@Service
@Slf4j
public class DistributedResourceCoordinator {
private static final String RESOURCE_LOCK_PREFIX = "resource:lock:";
private static final String RESOURCE_GROUP_PREFIX = "resource:group:";
private static final String RESOURCE_READWRITE_PREFIX = "resource:rw:";
@Autowired
private RedissonClient redissonClient;
/**
* 🎯 多资源原子分配
* 使用联锁(RedissonMultiLock)保证多个资源同时分配或全部不分配
*/
public ResourceAllocationResult allocateResources(List<String> resourceIds,
String requester,
Duration holdDuration) {
// 🎯 按照资源ID排序,避免死锁
List<String> sortedResourceIds = resourceIds.stream()
.sorted()
.collect(Collectors.toList());
// 创建联锁
List<RLock> locks = sortedResourceIds.stream()
.map(id -> redissonClient.getLock(RESOURCE_LOCK_PREFIX + id))
.collect(Collectors.toList());
RLock multiLock = redissonClient.getMultiLock(locks.toArray(new RLock[0]));
ResourceAllocationResult result = new ResourceAllocationResult(requester);
long startTime = System.currentTimeMillis();
try {
// 🎯 尝试获取所有资源的锁
boolean acquired = multiLock.tryLock(10, holdDuration.toMillis(), TimeUnit.MILLISECONDS);
if (!acquired) {
log.warn("资源分配失败,无法获取所有资源锁: {}", sortedResourceIds);
result.setStatus(AllocationStatus.FAILED);
result.setMessage("资源锁定超时");
return result;
}
try {
log.info("开始分配资源: {},请求者: {}", sortedResourceIds, requester);
// 检查所有资源是否可用
List<ResourceAvailability> availabilityList = checkResourcesAvailability(sortedResourceIds);
List<String> unavailableResources = availabilityList.stream()
.filter(avail -> !avail.isAvailable())
.map(ResourceAvailability::getResourceId)
.collect(Collectors.toList());
if (!unavailableResources.isEmpty()) {
result.setStatus(AllocationStatus.PARTIAL);
result.setAllocatedResources(
availabilityList.stream()
.filter(ResourceAvailability::isAvailable)
.map(ResourceAvailability::getResourceId)
.collect(Collectors.toList())
);
result.setUnavailableResources(unavailableResources);
result.setMessage("部分资源不可用: " + unavailableResources);
log.warn("资源部分分配成功: {}", result.getAllocatedResources());
return result;
}
// 🎯 执行资源分配
boolean allocationSuccess = doResourceAllocation(sortedResourceIds, requester, holdDuration);
if (allocationSuccess) {
result.setStatus(AllocationStatus.SUCCESS);
result.setAllocatedResources(sortedResourceIds);
result.setHoldDuration(holdDuration);
result.setMessage("资源分配成功");
log.info("资源全部分配成功: {},持有时间: {}", sortedResourceIds, holdDuration);
} else {
result.setStatus(AllocationStatus.FAILED);
result.setMessage("资源分配执行失败");
}
} finally {
if (multiLock.isHeldByCurrentThread()) {
multiLock.unlock();
log.debug("资源锁释放: {}", sortedResourceIds);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
result.setStatus(AllocationStatus.INTERRUPTED);
result.setMessage("资源分配被中断");
log.warn("资源分配被中断: {}", sortedResourceIds);
} catch (Exception e) {
result.setStatus(AllocationStatus.FAILED);
result.setMessage("资源分配异常: " + e.getMessage());
log.error("资源分配异常: {}", sortedResourceIds, e);
} finally {
result.setExecutionTime(System.currentTimeMillis() - startTime);
}
return result;
}
/**
* 📖 读写分离控制
* 使用读写锁实现读多写少的并发控制
*/
public Object readResourceWithLock(String resourceId, ResourceReader reader) {
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(
RESOURCE_READWRITE_PREFIX + resourceId
);
RLock readLock = readWriteLock.readLock();
readLock.lock();
try {
log.debug("获取读锁成功,资源: {}", resourceId);
return reader.read();
} finally {
if (readLock.isHeldByCurrentThread()) {
readLock.unlock();
log.debug("读锁释放,资源: {}", resourceId);
}
}
}
public boolean updateResourceWithLock(String resourceId, Object newData, ResourceWriter writer) {
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(
RESOURCE_READWRITE_PREFIX + resourceId
);
RLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
log.debug("获取写锁成功,资源: {}", resourceId);
return writer.write(newData);
} finally {
if (writeLock.isHeldByCurrentThread()) {
writeLock.unlock();
log.debug("写锁释放,资源: {}", resourceId);
}
}
}
/**
* 🔄 分布式配置管理
* 使用红锁(RedLock)实现跨Redis节点的配置更新
*/
public boolean updateDistributedConfig(String configKey, String configValue) {
// 创建红锁(需要多个独立的Redis实例)
RLock redLock = createRedLock("config:" + configKey);
try {
// 红锁获取,需要在多数节点上获取成功
boolean acquired = redLock.tryLock(5, 30, TimeUnit.SECONDS);
if (!acquired) {
log.warn("配置更新失败,无法获取红锁: {}", configKey);
return false;
}
try {
log.info("开始更新分布式配置: {}", configKey);
// 执行配置更新
updateConfigInAllStores(configKey, configValue);
log.info("分布式配置更新成功: {}", configKey);
return true;
} finally {
if (redLock.isHeldByCurrentThread()) {
redLock.unlock();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("配置更新被中断: {}", configKey);
return false;
}
}
private List<ResourceAvailability> checkResourcesAvailability(List<String> resourceIds) {
return resourceIds.stream()
.map(id -> new ResourceAvailability(id, checkSingleResourceAvailable(id)))
.collect(Collectors.toList());
}
private boolean checkSingleResourceAvailable(String resourceId) {
// 检查资源可用性的具体实现
// 这里可以查询数据库、调用其他服务等
return true;
}
private boolean doResourceAllocation(List<String> resourceIds, String requester, Duration holdDuration) {
// 执行资源分配的具体实现
// 更新资源状态、记录分配日志等
return true;
}
private RLock createRedLock(String lockKey) {
// 创建红锁,需要配置多个Redis连接
// 这里简化为使用单个锁,实际生产环境需要多个独立Redis实例
return redissonClient.getLock(lockKey);
}
private void updateConfigInAllStores(String configKey, String configValue) {
// 在所有配置存储中更新配置
}
// 资源可用性信息
@Data
public static class ResourceAvailability {
private final String resourceId;
private final boolean available;
private String reason;
public ResourceAvailability(String resourceId, boolean available) {
this.resourceId = resourceId;
this.available = available;
}
}
// 资源分配结果
@Data
public static class ResourceAllocationResult {
private final String requester;
private AllocationStatus status;
private List<String> allocatedResources = new ArrayList<>();
private List<String> unavailableResources = new ArrayList<>();
private String message;
private Duration holdDuration;
private Long executionTime;
public ResourceAllocationResult(String requester) {
this.requester = requester;
}
}
// 分配状态枚举
public enum AllocationStatus {
SUCCESS, PARTIAL, FAILED, INTERRUPTED
}
// 资源读写接口
@FunctionalInterface
public interface ResourceReader {
Object read() throws Exception;
}
@FunctionalInterface
public interface ResourceWriter {
boolean write(Object data) throws Exception;
}
}
4. 📊 技术对比与选型指南
4.1 🎯 全方位特性对比
| 特性维度 | Synchronized | MySQL FOR UPDATE | Redisson |
|---|---|---|---|
| 🔗 作用范围 | JVM进程内 | 数据库连接级别 | 跨JVM分布式 |
| 🎯 锁粒度 | 对象/类级别 | 行/表级别 | Key级别 |
| ⚡ 性能影响 | 低(JVM优化) | 中(数据库IO) | 中(网络IO) |
| 🔄 死锁处理 | JVM自动检测 | 数据库死锁检测 | 超时自动释放 |
| 💾 事务支持 | 无内置支持 | 完整ACID事务 | 弱事务语义 |
| 🛡️ 容错能力 | 进程崩溃自动释放 | 连接断开自动释放 | 看门狗机制保障 |
| 📈 可扩展性 | 单机扩展 | 数据库集群扩展 | Redis集群扩展 |
4.2 🎯 场景化选型决策树
4.3 🚀 混合架构实战模式
java
/**
* 🎯 多层次混合锁架构
* 结合三种锁技术,构建全方位的并发控制体系
*/
@Service
public class HybridLockArchitecture {
@Autowired
private RedissonClient redissonClient;
// 本地缓存使用synchronized
private final Map<String, CacheEntry> localCache = new HashMap<>();
private final Object cacheLock = new Object();
/**
* 🔥 三级锁保护架构
* 1. 本地缓存锁 - 最高性能
* 2. 分布式锁 - 防止缓存击穿
* 3. 数据库行锁 - 强一致性保证
*/
@Transactional
public ProductInfo getProductWithFullProtection(Long productId) {
String cacheKey = "product:" + productId;
// 🎯 第一级:本地缓存锁(性能最优)
synchronized (cacheLock) {
CacheEntry cached = localCache.get(cacheKey);
if (cached != null && !cached.isExpired()) {
log.debug("本地缓存命中: {}", productId);
return (ProductInfo) cached.getValue();
}
}
// 🎯 第二级:分布式锁(防止缓存击穿)
String distributedLockKey = "product:lock:" + productId;
RLock distributedLock = redissonClient.getLock(distributedLockKey);
try {
if (distributedLock.tryLock(3, 30, TimeUnit.SECONDS)) {
// 🎯 双重检查
synchronized (cacheLock) {
CacheEntry cached = localCache.get(cacheKey);
if (cached != null && !cached.isExpired()) {
return (ProductInfo) cached.getValue();
}
}
// 🎯 第三级:数据库行锁(强一致性)
ProductInfo product = productMapper.selectByIdForUpdate(productId);
if (product != null) {
// 更新本地缓存
synchronized (cacheLock) {
localCache.put(cacheKey,
new CacheEntry(product, TimeUnit.MINUTES.toMillis(10)));
}
log.info("三级锁保护加载完成: {}", productId);
return product;
}
} else {
log.warn("获取分布式锁失败,降级处理: {}", productId);
// 降级策略:返回默认值或抛出异常
return getProductFallback(productId);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("数据加载被中断", e);
} finally {
if (distributedLock.isHeldByCurrentThread()) {
distributedLock.unlock();
}
}
return null;
}
/**
* 🛡️ 降级策略
*/
private ProductInfo getProductFallback(Long productId) {
// 返回默认产品信息
// 或根据业务需求抛出特定异常
ProductInfo fallback = new ProductInfo();
fallback.setId(productId);
fallback.setName("默认产品");
fallback.setPrice(BigDecimal.ZERO);
return fallback;
}
}
5. 🎯 总结与最佳实践
5.1 📚 核心技术要点回顾
- Synchronized:单机环境下性能最优,适合JVM内的线程同步控制
- MySQL FOR UPDATE:数据库层面强一致性保证,适合金融级数据操作
- Redisson:分布式系统协调利器,提供丰富的分布式锁功能
5.2 🚀 生产环境最佳实践
性能优化建议:
- 🔥 Synchronized:合理使用锁粒度,避免过度同步
- 💾 FOR UPDATE:确保查询使用索引,避免表锁
- 🌐 Redisson:合理设置超时时间,启用看门狗机制
容灾设计原则:
- 🛡️ 设置合理的锁超时时间
- 🔄 实现完善的降级策略
- 📊 建立锁监控和告警机制
架构演进路径:
text
单机应用 → Synchronized
↓
数据库集群 → FOR UPDATE
↓
分布式系统 → Redisson
↓
混合架构 → 多级锁保护
通过深入理解每种锁技术的底层原理和适用场景,结合实际的业务需求,我们可以在保证数据一致性的同时,最大限度地提升系统性能和可用性。希望本文能够为你在实际项目中的技术选型和架构设计提供有力的指导!