fix:主备切换测试

This commit is contained in:
waner
2025-05-30 16:21:39 +08:00
parent 085d71feb9
commit fbcbe79388
11 changed files with 543 additions and 157 deletions
@@ -0,0 +1,107 @@
package com.sunyard.util;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* IP锁工具类 - 高并发安全实现
*
* 为每个IP地址提供唯一的可重入锁,确保同一IP的操作顺序执行
*/
public class IpLockUtils {
private static final ConcurrentMap<String, ReentrantLock> LOCK_MAP = new ConcurrentHashMap<>();
private static final Object CREATION_LOCK = new Object();
/**
* 获取IP对应的锁(保证唯一性)
* @param ip IP地址
* @return 可重入锁实例
*/
public static ReentrantLock getLockForIp(String ip) {
ReentrantLock lock = LOCK_MAP.get(ip);
if (lock != null) {
return lock;
}
synchronized (CREATION_LOCK) {
// 双重检查
lock = LOCK_MAP.get(ip);
if (lock == null) {
lock = new ReentrantLock(true); // 公平锁
LOCK_MAP.put(ip, lock);
}
return lock;
}
}
/**
* 安全加锁(带超时机制)
* @param ip IP地址
* @param timeout 超时时间
* @param unit 时间单位
* @return 是否成功获取锁
* @throws InterruptedException
*/
public static boolean lockWithTimeout(String ip, long timeout, TimeUnit unit)
throws InterruptedException {
ReentrantLock lock = getLockForIp(ip);
return lock.tryLock(timeout, unit);
}
/**
* 解锁指定IP的锁
* @param ip IP地址
*/
public static void unlockForIp(String ip) {
ReentrantLock lock = LOCK_MAP.get(ip);
if (lock != null && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
/**
* 清理未使用的锁(可选)
*/
public static void cleanupUnusedLocks() {
LOCK_MAP.entrySet().removeIf(entry ->
!entry.getValue().isLocked() &&
entry.getValue().getQueueLength() == 0
);
}
/**
* 获取当前锁数量
*/
public static int getLockCount() {
return LOCK_MAP.size();
}
/**
* 获取IP锁状态
* @param ip IP地址
* @return 锁状态字符串
*/
public static String getLockStatus(String ip) {
ReentrantLock lock = LOCK_MAP.get(ip);
if (lock == null) {
return "No lock exists";
}
return String.format("Locked: %s, Queue: %d, HoldCount: %d",
lock.isLocked(), lock.getQueueLength(), lock.getHoldCount());
}
/**
* 重置所有锁
*/
public static void reset() {
synchronized (CREATION_LOCK) {
LOCK_MAP.clear();
}
}
}