English | ไธญๆ
ๅบไบ Spring Boot ็ๅๅธๅผ้ๆกๆถ๏ผ้่ฟ @Lock ๆณจ่งฃๅฎ็ฐๆฌๅฐ้ๅๅๅธๅผ้็ไธ้ฎๅ ้ใ
- ๐ ็ฎๅๆ็จ - ไธไธช
@Lockๆณจ่งฃๆๅฎๅๅธๅผ้ - ๐ง ๅคๅผๆๆฏๆ - RedissonใRedisTemplateใZookeeperใEtcdใๆฌๅฐ้
- ๐ ๆดพ็ๆณจ่งฃ -
@RedissonLockใ@RedisTemplateLockใ@ZookeeperLockใ@EtcdLockใ@LocalLock - ๐ SpEL ่กจ่พพๅผ - ็ตๆดป็ Key ๆๅปบ๏ผๆฏๆๆนๆณๅๆฐๅๅฏน่ฑกๅฑๆง
- ๐๏ธ ่ชๅฎไน KeyBuilder - ๅคๆๅบๆฏๅฏๆฉๅฑ
- ๐ ๅค็ง้็ฑปๅ - ๅฏ้ๅ ฅ้ใๅ ฌๅนณ้ใ่ฏปๅ้
- โฑ๏ธ Watchdog ่ชๅจ็ปญๆ - ้ฒๆญขไธๅกๆชๆง่กๅฎ้่ฟๆ
- ๐ฏ ๅคฑ่ดฅๅค็ - ๅฏ่ชๅฎไนๅ ้ๅคฑ่ดฅๅค็็ญ็ฅ
- ๐ ๆฆๆชๅจๆบๅถ - ๆต็จ้ฉๅญ๏ผๆฏๆ็ๆงใๆฅๅฟใ้พ่ทฏ่ฟฝ่ธช
- ๐ก ไบไปถ็ๅฌ - ้็ๅฝๅจๆไบไปถๅๅธ
- ๐ ๅค Key ๅ ้ - ๆฏๆๅๆถๅฏนๅคไธช Key ๅ ้
- ๐๏ธ Spring Boot ้ๆ - ่ชๅจ้ ็ฝฎ๏ผๅผ็ฎฑๅณ็จ
lock4j
โโโ lock4j-core # ๆ ธๅฟๆจกๅ๏ผๅฎไนๆฅๅฃๅๆฝ่ฑก็ฑป
โโโ lock4j-redisson # Redisson ๅฎ็ฐ (Redis)
โโโ lock4j-redis-template # RedisTemplate ๅฎ็ฐ (Redis)
โโโ lock4j-zookeeper # Zookeeper ๅฎ็ฐ (Curator 5.x)
โโโ lock4j-etcd # Etcd ๅฎ็ฐ (jetcd 0.7.x)
โโโ lock4j-local # ๆฌๅฐ้ๅฎ็ฐ
โโโ lock4j-spring-boot-starter # Spring Boot ่ชๅจ้
็ฝฎ
โโโ lock4j-examples # ไฝฟ็จ็คบไพ
Maven:
<dependency>
<groupId>com.geek.lock</groupId>
<artifactId>lock4j-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- ๆ นๆฎ้่ฆๆทปๅ ๅ
ทไฝ Provider ไพ่ต -->
<dependency>
<groupId>com.geek.lock</groupId>
<artifactId>lock4j-redisson</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>Gradle:
implementation 'com.geek.lock:lock4j-spring-boot-starter:1.0.0-SNAPSHOT'
implementation 'com.geek.lock:lock4j-redisson:1.0.0-SNAPSHOT'lock4j:
enabled: true
primary-provider: redissonLockProvider
redisson:
enabled: true
address: localhost:6379@Service
public class OrderService {
@Lock(keys = "#orderId")
public void processOrder(String orderId) {
// ไธๅก้ป่พ
}
}| Provider | ้็ฑปๅ | ๅฎ็ฐๆๆฏ | ่ฏดๆ |
|---|---|---|---|
| Redisson | ๅฏ้ๅ ฅใๅ ฌๅนณใ่ฏปๅ | Redisson 3.x | ๅ่ฝๆๅ จ๏ผๆจ่ไฝฟ็จ |
| RedisTemplate | ๅฏ้ๅ ฅ | Lua ่ๆฌ | ่ฝป้็บง๏ผไพ่ตๅฐ |
| Zookeeper | ๅฏ้ๅ ฅใ่ฏปๅ | Curator 5.x | CP ไธ่ดๆง |
| Etcd | ๅฏ้ๅ ฅใๅ ฌๅนณ | jetcd 0.7.x | ไบๅ็ๅบๆฏ |
| Local | ๅฏ้ๅ ฅใๅ ฌๅนณใ่ฏปๅ | JDK ReentrantLock | ๅ่ฟ็จไฝฟ็จ |
@Service
public class OrderService {
// ๆนๆณๅๆฐ
@Lock(keys = "#orderId")
public void processOrder(String orderId) {
// ไธๅก้ป่พ
}
// ๅฏน่ฑกๅฑๆง
@Lock(keys = "#order.id")
public void processOrder(Order order) {
// ไธๅก้ป่พ
}
// ๅตๅฅๅฑๆง
@Lock(keys = "#order.user.id")
public void processOrderByUser(Order order) {
// ไธๅก้ป่พ
}
// ๅคไธช Key
@Lock(keys = {"#productId", "#warehouseId"})
public void deductStock(String productId, String warehouseId) {
// ไธๅก้ป่พ
}
}@Service
public class PaymentService {
// ่ชๅฎไน็ญๅพ
ๆถ้ดๅ่ฟๆๆถ้ด
@Lock(keys = "#orderId", waitTime = 5000, leaseTime = 60000)
public void processPayment(String orderId) {
// ไธๅก้ป่พ
}
// ๆๅฎๆถ้ดๅไฝ
@Lock(keys = "#orderId", waitTime = 5, leaseTime = 60, timeUnit = TimeUnit.SECONDS)
public void processPaymentWithSeconds(String orderId) {
// ไธๅก้ป่พ
}
// ๆทปๅ Key ๅ็ผ
@Lock(keys = "#orderId", prefix = "order:lock:")
public void processOrderWithPrefix(String orderId) {
// ไธๅก้ป่พ
}
}@Service
public class ResourceService {
// ๅฏ้ๅ
ฅ้๏ผ้ป่ฎค๏ผ
@Lock(keys = "#resourceId", lockType = LockType.REENTRANT)
public void processResource(String resourceId) {
// ไธๅก้ป่พ
}
// ๅ
ฌๅนณ้
@Lock(keys = "#resourceId", lockType = LockType.FAIR)
public void processWithFairLock(String resourceId) {
// ไธๅก้ป่พ
}
// ่ฏป้๏ผๅ
ฑไบซ้๏ผ
@Lock(keys = "#resourceId", lockType = LockType.READ)
public String readResource(String resourceId) {
// ่ฏปๅ้ป่พ
return "data";
}
// ๅ้๏ผๆไป้๏ผ
@Lock(keys = "#resourceId", lockType = LockType.WRITE)
public void writeResource(String resourceId, String data) {
// ๅๅ
ฅ้ป่พ
}
}ๆฏไธช LockProvider ้ฝๆๅฏนๅบ็ๆดพ็ๆณจ่งฃ๏ผ่ชๅจๆๅฎ Provider๏ผ
@Service
public class LockService {
// Redisson ้
@RedissonLock(keys = "#id", lockType = LockType.FAIR)
public void processWithRedisson(String id) {
// ไธๅก้ป่พ
}
// RedisTemplate ้
@RedisTemplateLock(keys = "#id", waitTime = 3000, leaseTime = 30000)
public void processWithRedisTemplate(String id) {
// ไธๅก้ป่พ
}
// Zookeeper ้
@ZookeeperLock(keys = "#id", lockType = LockType.READ)
public String readWithZookeeper(String id) {
return "data";
}
// Etcd ้
@EtcdLock(keys = "#id", lockType = LockType.FAIR)
public void processWithEtcd(String id) {
// ไธๅก้ป่พ
}
// ๆฌๅฐ้
@LocalLock(keys = "#id")
public void processWithLocal(String id) {
// ไธๅก้ป่พ
}
}ๅฝ SpEL ่กจ่พพๅผๆ ๆณๆปก่ถณๅคๆๅบๆฏๆถ๏ผๅฏ่ชๅฎไน KeyBuilder๏ผ
// 1. ๅฎ็ฐ่ชๅฎไน KeyBuilder
@Component
public class OrderKeyBuilder extends AbstractKeyBuilder {
@Override
protected String[] doBuild(Method method, String[] parameterNames,
Object[] args, Lock annotation) {
Order order = (Order) args[0];
String userId = (String) args[1];
// ๆ นๆฎไธๅก้ป่พๆๅปบ Key
return new String[]{
"order:" + order.getId(),
"user:" + userId
};
}
}
// 2. ไฝฟ็จ่ชๅฎไน KeyBuilder
@Service
public class OrderService {
@Lock(keyBuilder = OrderKeyBuilder.class)
public void processOrder(Order order, String userId) {
// ไธๅก้ป่พ
}
}@Service
public class OrderService {
// ้ป่ฎค๏ผๆๅบ LockFailureException
@Lock(keys = "#orderId")
public void processOrder(String orderId) {
// ไธๅก้ป่พ
}
// ๆๅบ่ชๅฎไนๅผๅธธ
@Lock(keys = "#orderId", failFast = OrderLockException.class)
public void processOrderWithCustomException(String orderId) {
// ไธๅก้ป่พ
}
}// 1. ๅฎ็ฐ่ชๅฎไนๅคฑ่ดฅๅค็ๅจ
@Component
public class RetryFailureHandler implements FailureHandler {
private static final int MAX_RETRY = 3;
@Override
public Object handle(LockFailureContext context) {
String[] keys = context.getLockKeys();
Method method = context.getMethod();
Object[] args = context.getArgs();
log.warn("Lock failed for keys: {}, method: {}",
Arrays.toString(keys), method.getName());
// ่ฟๅ้ป่ฎคๅผ
return getDefaultValue(method.getReturnType());
}
private Object getDefaultValue(Class<?> returnType) {
if (returnType == boolean.class) return false;
if (returnType == int.class) return 0;
if (returnType == String.class) return "LOCK_FAILED";
return null;
}
}
// 2. ไฝฟ็จ่ชๅฎไนๅคฑ่ดฅๅค็ๅจ
@Service
public class OrderService {
@Lock(keys = "#orderId", failureHandler = RetryFailureHandler.class)
public Order getOrder(String orderId) {
// ไธๅก้ป่พ
return orderRepository.findById(orderId);
}
// ๅคฑ่ดฅๆถ่ฟๅ null ่ไธๆฏๆๅผๅธธ
@Lock(keys = "#orderId", failureHandler = RetryFailureHandler.class)
public String processOrder(String orderId) {
// ไธๅก้ป่พ
return "SUCCESS";
}
}ๆฆๆชๅจๆไพ้ๆง่กๆต็จๅ้ถๆฎต็้ฉๅญๆนๆณ๏ผๅฏ็จไบ็ๆงใๆฅๅฟใ้พ่ทฏ่ฟฝ่ธช็ญใ
@Component
public class LoggingLockInterceptor implements LockInterceptor {
@Override
public void beforeKeyBuild(Method method, Object[] args, Lock annotation) {
log.info("[Lock] ๅๅคๆๅปบ Key, ๆนๆณ: {}, ๅๆฐ: {}",
method.getName(), Arrays.toString(args));
}
@Override
public void afterKeyBuild(List<String> keys) {
log.info("[Lock] Key ๆๅปบๅฎๆ: {}", keys);
}
@Override
public void beforeLock(List<String> keys, LockOptions options) {
log.info("[Lock] ๅฐ่ฏๅ ้: {}, ็ญๅพ
ๆถ้ด: {}ms, ็งๆ: {}ms",
keys, options.getWaitTime(), options.getLeaseTime());
}
@Override
public void afterLock(List<String> keys) {
log.debug("[Lock] ๅไธช Key ๅ ้ๆไฝๅฎๆ: {}", keys);
}
@Override
public void onLockSuccess(List<String> keys, LockKey lockKey) {
log.info("[Lock] ๅ ้ๆๅ: {}", lockKey.getKey());
}
@Override
public void onLockFailure(List<String> keys) {
log.warn("[Lock] ๅ ้ๅคฑ่ดฅ: {}", keys);
}
@Override
public void onException(List<String> keys, Throwable exception) {
log.error("[Lock] ๆง่กๅผๅธธ: {}, keys: {}",
exception.getMessage(), keys, exception);
}
}@Service
public class OrderService {
@Lock(keys = "#orderId", interceptor = LoggingLockInterceptor.class)
public void processOrder(String orderId) {
// ไธๅก้ป่พ
}
// ็ปๅๅ
ถไปๅฑๆง
@Lock(keys = "#orderId",
interceptor = LoggingLockInterceptor.class,
waitTime = 5000,
leaseTime = 60000)
public Order processOrderWithLog(String orderId) {
// ไธๅก้ป่พ
return order;
}
}beforeKeyBuild(method, args, annotation)
โ
่งฃๆ Key
โ
afterKeyBuild(keys)
โ
beforeLock(keys, options)
โ
โโโโ ๅพช็ฏๆฏไธช Key โโโโ
โ โ
โ afterLock(key) โ
โ โ โ
โ ๅฐ่ฏๅ ้ โ
โ โ โ
โ ๆๅ โ onLockSuccess(key, lockKey)
โ ๅคฑ่ดฅ โ onLockFailure(keys) โ ๅคฑ่ดฅๅค็
โ โ
โโโโโโโโโโโโโโโโโโโโโโ
โ
ๆง่กไธๅกๆนๆณ
โ
ๆๅ โ ่ฟๅ็ปๆ
ๅผๅธธ โ onException(keys, exception)
้่ฟ Spring ไบไปถๆบๅถ็ๅฌ้็็ๅฝๅจๆไบไปถ๏ผ
@Component
public class LockEventListener {
@EventListener
public void onLockEvent(LockEvent event) {
LockEventType type = event.getType();
List<String> keys = event.getKeys();
switch (type) {
case BEFORE_LOCK:
log.info("ๅ ้ๅผๅง: {}", keys);
metrics.increment("lock.attempt");
break;
case AFTER_LOCK:
log.info("ๅ ้ๆๅ: {}", keys);
metrics.increment("lock.success");
break;
case LOCK_FAILED:
log.warn("ๅ ้ๅคฑ่ดฅ: {}", keys);
metrics.increment("lock.failed");
break;
case LOCK_ERROR:
log.error("ๅ ้้่ฏฏ: {}", keys);
metrics.increment("lock.error");
break;
case BEFORE_UNLOCK:
log.debug("ๅๅค่งฃ้: {}", keys);
break;
case AFTER_UNLOCK:
log.debug("่งฃ้ๅฎๆ: {}", keys);
break;
}
}
}ๅฝ keys ๅ keyBuilder ้ฝไธบ็ฉบๆถ็ๅค็็ญ็ฅ๏ผ
@Service
public class DefaultKeyService {
// ไฝฟ็จๆนๆณๅ
จ้ๅฎๅไฝไธบ Key๏ผ้ป่ฎค๏ผ
@Lock
public void processWithDefaultKey() {
// Key = "com.example.DefaultKeyService.processWithDefaultKey"
}
// ไฝฟ็จๆนๆณๅ
จ้ๅฎๅไฝไธบ Key๏ผ่ชๅฎไน่ถ
ๆถ
@Lock(leaseTime = 60000)
public void processWithLongLease() {
// ไธๅก้ป่พ
}
// Key ไธบ็ฉบๆถๆๅบๅผๅธธ
@Lock(keyAbsentPolicy = KeyAbsentPolicy.THROW_EXCEPTION)
public void processWithStrictKey() {
// ๅฆๆๆชๆๅฎ keys๏ผไผๆๅบ IllegalArgumentException
}
}ๅฝๅญๅจๅคไธช LockProvider ๆถ๏ผๅฏไปฅๆๅฎไฝฟ็จๅชไธช๏ผ
@Service
public class MultiProviderService {
// ไฝฟ็จ้ป่ฎค Provider๏ผprimary-provider ้
็ฝฎ๏ผ
@Lock(keys = "#id")
public void processWithDefault(String id) {
// ไธๅก้ป่พ
}
// ๆๅฎไฝฟ็จ Redisson
@Lock(keys = "#id", provider = RedissonLockProvider.class)
public void processWithRedisson(String id) {
// ไธๅก้ป่พ
}
// ๆๅฎไฝฟ็จ RedisTemplate
@Lock(keys = "#id", provider = RedisTemplateLockProvider.class)
public void processWithRedisTemplate(String id) {
// ไธๅก้ป่พ
}
// ๆๅฎไฝฟ็จ Zookeeper
@Lock(keys = "#id", provider = ZookeeperLockProvider.class)
public void processWithZookeeper(String id) {
// ไธๅก้ป่พ
}
// ๆๅฎไฝฟ็จๆฌๅฐ้
@Lock(keys = "#id", provider = LocalLockProvider.class)
public void processWithLocal(String id) {
// ไธๅก้ป่พ
}
}@Service
public class ComprehensiveOrderService {
private final OrderRepository orderRepository;
/**
* ๅฎๆด็้ไฝฟ็จ็คบไพ
* - ไฝฟ็จ SpEL ่กจ่พพๅผๆๅปบ Key
* - ๆทปๅ ๅ็ผ
* - ่ชๅฎไน็ญๅพ
ๆถ้ดๅ็งๆ
* - ไฝฟ็จๅ
ฌๅนณ้
* - ๆทปๅ ๆฆๆชๅจ
* - ่ชๅฎไนๅคฑ่ดฅๅค็
*/
@Lock(
keys = "#order.id",
prefix = "order:process:",
waitTime = 5000,
leaseTime = 60000,
lockType = LockType.FAIR,
interceptor = LoggingLockInterceptor.class,
failureHandler = RetryFailureHandler.class
)
public Order processOrder(Order order) {
// ไธๅก้ป่พ
return orderRepository.save(order);
}
/**
* ๅค Key ๅ ้็คบไพ
* ๅๆถ้ๅฎ็จๆทๅ่ฎขๅ
*/
@Lock(
keys = {"#userId", "#orderId"},
prefix = "deduct:",
interceptor = LoggingLockInterceptor.class
)
public void deductBalance(String userId, String orderId, BigDecimal amount) {
// ๆฃๅไฝ้ข้ป่พ
}
/**
* ่ฏปๅ้็คบไพ
*/
@Lock(
keys = "#productId",
lockType = LockType.READ,
provider = RedissonLockProvider.class
)
public Product getProduct(String productId) {
return orderRepository.findProductById(productId);
}
@Lock(
keys = "#product.id",
lockType = LockType.WRITE,
provider = RedissonLockProvider.class
)
public Product updateProduct(Product product) {
return orderRepository.saveProduct(product);
}
}| ๅฑๆง | ่ฏดๆ | ็ฑปๅ | ้ป่ฎคๅผ |
|---|---|---|---|
keys |
้ Key ๆฐ็ป๏ผๆฏๆ SpEL | String[] | {} |
keyBuilder |
่ชๅฎไน KeyBuilder ็ฑปๅ | Class<? extends KeyBuilder> | KeyBuilder.class |
keyAbsentPolicy |
Key ็ผบๅคฑ็ญ็ฅ | KeyAbsentPolicy | USE_METHOD_PATH |
prefix |
้ Key ๅ็ผ | String | "" |
waitTime |
็ญๅพ ่ทๅ้ๆถ้ด(ms) | long | 3000 |
leaseTime |
้่ฟๆๆถ้ด(ms) | long | 30000 |
timeUnit |
ๆถ้ดๅไฝ | TimeUnit | MILLISECONDS |
lockType |
้็ฑปๅ | LockType | REENTRANT |
failureHandler |
ๅ ้ๅคฑ่ดฅๅค็ๅจ | Class<? extends FailureHandler> | FailureHandler.Default.class |
failFast |
ๅคฑ่ดฅๅผๅธธ็ฑปๅ | Class<? extends RuntimeException> | LockFailureException.class |
provider |
ๆๅฎ LockProvider | Class<? extends LockProvider> | LockProvider.class |
interceptor |
ๆฆๆชๅจ | Class<? extends LockInterceptor> | LockInterceptor.class |
lock4j:
# ๅ
จๅฑ้
็ฝฎ
enabled: true
primary-provider: redissonLockProvider
default-wait-time: 3000
default-lease-time: 30000
# Redisson ้
็ฝฎ
redisson:
enabled: true
address: localhost:6379
password:
database: 0
connection-pool-size: 64
connection-minimum-idle-size: 10
timeout: 3000ms
# ๅๆบๆจกๅผ
# address: localhost:6379
# ้็พคๆจกๅผ
cluster:
node-addresses:
- redis://127.0.0.1:7000
- redis://127.0.0.1:7001
- redis://127.0.0.1:7002
# ๅจๅ
ตๆจกๅผ
sentinel:
master-name: mymaster
sentinel-addresses:
- redis://127.0.0.1:26379
- redis://127.0.0.1:26380
# RedisTemplate ้
็ฝฎ
redis:
enabled: true
host: localhost
port: 6379
password:
database: 0
connect-timeout: 3000ms
# Zookeeper ้
็ฝฎ
zookeeper:
enabled: false
connect-string: localhost:2181
session-timeout: 30000
connection-timeout: 10000
base-path: /lock4j
# Etcd ้
็ฝฎ
etcd:
enabled: false
endpoints:
- http://localhost:2379
user:
password:
connect-timeout: 5000
# ๆฌๅฐ้้
็ฝฎ
local:
enabled: trueโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ @Lock Annotation โ
โ (@RedissonLock, @RedisTemplateLock, @ZookeeperLock, ...) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ LockAspect โ
โ (AOP ๅ้ขๆฆๆช) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ LockExecutor โ
โ (SpEL่งฃๆ / KeyBuilder / Interceptor / ๅคฑ่ดฅๅค็) โ
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ SpEL Parser โ โ KeyBuilder โ โFailureHandlerโ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ LockInterceptor (ๆต็จ้ฉๅญ) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ LockProviderFactory โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโฌโโโโโโโโดโโโโโโโโฌโโโโโโโโโโโโโ
โผ โผ โผ โผ
โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ
โ Redisson โ โ Redis โ โZookeeper โ โ Etcd โ
โ Provider โ โTemplate โ โ Provider โ โ Provider โ
โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ
- JDK 17+
- Spring Boot 3.x
- Spring AOP
- Redisson 3.25.2
- Curator 5.5.0
- jetcd 0.7.6
- Lombok
- ้ Key ่ฎพ่ฎก - ๅปบ่ฎฎไฝฟ็จไธๅก็ธๅ ณ็ๅฏไธๆ ่ฏไฝไธบ Key
- ้่ถ
ๆถๆถ้ด -
leaseTimeๅบๅคงไบไธๅกๆง่กๆถ้ด - ็ญๅพ
ๆถ้ด -
waitTime้ๆ นๆฎไธๅกๅบๆฏๆ่กก - ๅค Key ๅ ้ - ้็จๅ จ้จๅ ้็ญ็ฅ๏ผๅฟ ้กป่ทๅๆๆ้ๆ็ฎๆๅ
- ๅผๅธธๅค็ - ไธๅกๆนๆณๆๅบๅผๅธธๆถ๏ผ้ไผ่ชๅจ้ๆพ
- Watchdog - ๅฏ็จๅ่ชๅจ็ปญๆ๏ผ้ฒๆญขไธๅกๆชๆง่กๅฎ้่ฟๆ
MIT License