Skip to content

Commit

Permalink
update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
ponfee committed Oct 21, 2023
1 parent 795cc31 commit c95b267
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 51 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
```text
disjob # 主项目①
├── disjob-admin # 管理后台项目②(基于Ruoyi框架二次开发)
├── disjob-bom # Maven project bom module
├── disjob-bom # Maven项目bom模块
├── disjob-common # 公共的工具类模块
├── disjob-core # 任务调度相关的核心类(如数据模型、枚举类、抽象层接口等)
├── disjob-dispatch # 任务派发模块
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ <h2 tabindex="-1" id="user-content-architecture" dir="auto"><a class="heading-li
</ul>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="disjob # 主项目①
├── disjob-admin # 管理后台项目②(基于Ruoyi框架二次开发)
├── disjob-bom # Maven project bom module
├── disjob-bom # Maven项目bom模块
├── disjob-common # 公共的工具类模块
├── disjob-core # 任务调度相关的核心类(如数据模型、枚举类、抽象层接口等)
├── disjob-dispatch # 任务派发模块
Expand All @@ -139,7 +139,7 @@ <h2 tabindex="-1" id="user-content-architecture" dir="auto"><a class="heading-li
├── disjob-test # 用于辅助测试
└── disjob-worker # Worker代码"><pre lang="text" class="notranslate"><code>disjob # 主项目①
├── disjob-admin # 管理后台项目②(基于Ruoyi框架二次开发)
├── disjob-bom # Maven project bom module
├── disjob-bom # Maven项目bom模块
├── disjob-common # 公共的工具类模块
├── disjob-core # 任务调度相关的核心类(如数据模型、枚举类、抽象层接口等)
├── disjob-dispatch # 任务派发模块
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package cn.ponfee.disjob.common.lock;

import cn.ponfee.disjob.common.spring.RedisTemplateUtils;
import cn.ponfee.disjob.common.util.Bytes;
import cn.ponfee.disjob.common.util.ObjectUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
Expand All @@ -26,13 +27,20 @@
import static java.nio.charset.StandardCharsets.UTF_8;

/**
* <pre>
* Distributes lock based redis(unlock使用redis lua script)
* <p>可重入锁的一般场景:当前线程多次调用含有锁操作的函数、当前线程含有锁操作的函数自身调用
* 可重入锁的一般场景:当前线程多次调用含有锁操作的函数、当前线程含有锁操作的函数自身调用
* 待完善:
* 1、获取锁成功的线程 A 定时续期锁:WatchDog
* 2、获取锁失败的线程 B 阻塞等待并监听(订阅)队列:subscribe
* 3、线程 A 释放锁时发送消息通知等待锁的线程B:publish
*
* {@code
* RedisLockFactory factory = new RedisLockFactory(redisTemplate);
*
* <pre>
* class X {
* public void m() {
* Lock lock = new RedisLock(redisTemplate, "lockKey", 5000, 30);
* Lock lock = factory.create("lockKey", 3000);
* lock.lock(); // block until acquire lock or timeout
* try {
* // ... method body
Expand All @@ -44,7 +52,7 @@
*
* class Y {
* public void m() {
* Lock lock = new RedisLock(redisTemplate, "lockKey", 5000, 30);
* Lock lock = factory.create("lockKey", 3000);
* if (!lock.tryLock()) return;
* try {
* // ... method body
Expand All @@ -56,7 +64,7 @@
*
* class Z {
* public void m() {
* Lock lock = new RedisLock(redisTemplate, "lockKey", 5000, 30);
* Lock lock = factory.create("lockKey", 3000);
* // auto timeout release lock
* if (!lock.tryLock(100, TimeUnit.MILLISECONDS)) return;
* try {
Expand All @@ -66,7 +74,7 @@
* }
* }
* }
* </pre>
* }</pre>
*
* @author Ponfee
* @see <a href="https://redisson.org">better implementation: redisson</a>
Expand All @@ -77,15 +85,20 @@ public class RedisLock implements Lock {

/**
* <pre>
* Redis HSET data structure
* key: lock key
* field: lock value
* value: increment value, start 1
*
* Reentrant lock lua script
* KEYS[1]=key
* KEYS[1]=lock key
* ARGV[1]=pexpire milliseconds
* ARGV[2]=lock value
* </pre>
*/
private static final RedisScript<Long> LOCK_SCRIPT = RedisScript.of(
"if ( redis.call('exists', KEYS[1] )==0 \n" +
" or redis.call('hexists', KEYS[1], ARGV[2])==1 ) then \n" +
"if ( redis.call('exists', KEYS[1] )==0 \n" +
" or redis.call('hexists', KEYS[1], ARGV[2])==1 ) then \n" +
" redis.call('hincrby', KEYS[1], ARGV[2], 1); \n" +
" redis.call('pexpire', KEYS[1], ARGV[1]); \n" +
" return nil; \n" +
Expand All @@ -97,7 +110,7 @@ public class RedisLock implements Lock {
/**
* <pre>
* Unlock lua script
* KEYS[1]=key
* KEYS[1]=lock key
* ARGV[1]=pexpire milliseconds
* ARGV[2]=lock value
* </pre>
Expand All @@ -120,7 +133,7 @@ public class RedisLock implements Lock {
/**
* <pre>
* Renew lock lua script
* KEYS[1]=key
* KEYS[1]=lock key
* ARGV[1]=pexpire milliseconds
* ARGV[2]=lock value
* </pre>
Expand All @@ -147,7 +160,7 @@ public class RedisLock implements Lock {
/**
* Lock uuid value
*/
private final String lockUuid;
private final byte[] lockUuid;

/**
* Lock timeout, prevent deadlock.
Expand All @@ -173,7 +186,7 @@ public class RedisLock implements Lock {

this.redisTemplate = redisTemplate;
this.lockKey = ("lock:" + lockKey).getBytes(UTF_8);
this.lockUuid = ObjectUtils.uuid32() + ":";
this.lockUuid = ObjectUtils.uuid();
this.timeoutMillis = Long.toString(timeoutMillis).getBytes(UTF_8);
this.sleepMillis = Math.min(sleepMillis, timeoutMillis);
}
Expand Down Expand Up @@ -340,11 +353,11 @@ private boolean release() {
}

private byte[] getLockValue() {
return (lockUuid + Thread.currentThread().getId()).getBytes(UTF_8);
return Bytes.concat(lockUuid, Bytes.toBytes(Thread.currentThread().getId()));
}

private long computeSleepMillis(int round) {
return round < 10 ? sleepMillis : Math.min(sleepMillis * round, 200);
return round < 5 ? sleepMillis : Math.min(sleepMillis * (round - 3), 5000);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ public class RedisLockFactory {
private final long sleepMillis;

public RedisLockFactory(RedisTemplate<?, ?> redisTemplate) {
this(redisTemplate, 50);
this(redisTemplate, 100);
}

public RedisLockFactory(RedisTemplate<?, ?> redisTemplate, long sleepMillis) {
this.redisTemplate = redisTemplate;
this.sleepMillis = Math.max(10, sleepMillis);
this.sleepMillis = Math.max(50, sleepMillis);
}

public RedisLock getLock(String lockKey, int timeoutMillis) {
public RedisLock create(String lockKey, int timeoutMillis) {
return new RedisLock(redisTemplate, lockKey, timeoutMillis, sleepMillis);
}

Expand Down
37 changes: 13 additions & 24 deletions disjob-common/src/main/java/cn/ponfee/disjob/common/util/Bytes.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Objects;

/**
* byte array utilities
Expand Down Expand Up @@ -336,32 +334,23 @@ public static BigInteger toBigInteger(byte[] bytes) {
}

// ----------------------------------------------------------others

/**
* merge byte arrays
* @param first first byte array of args
* @param rest others byte array
* Concat many byte arrays
*
* @param arrays the byte arrays
* @return a new byte array of them
*/
public static byte[] concat(byte[] first, byte[]... rest) {
Objects.requireNonNull(first, "the first array arg cannot be null");
if (rest == null || rest.length == 0) {
return first;
public static byte[] concat(byte[]... arrays) {
int length = 0;
for (byte[] array : arrays) {
length += array.length;
}

int totalLength = first.length;
for (byte[] array : rest) {
if (array != null) {
totalLength += array.length;
}
}

byte[] result = Arrays.copyOf(first, totalLength);
int offset = first.length;
for (byte[] array : rest) {
if (array != null) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
byte[] result = new byte[length];
int pos = 0;
for (byte[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected void beforeEach() {
@Test
public void test0() throws InterruptedException {
String key = "test:" + ObjectUtils.uuid32();
RedisLock redisLock = factory.getLock(key, 10000);
RedisLock redisLock = factory.create(key, 10000);
Assertions.assertTrue(redisLock.tryLock());

Thread.sleep(55);
Expand Down Expand Up @@ -98,7 +98,7 @@ public void test0() throws InterruptedException {
@Test
public void test1() throws IOException, InterruptedException {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file())));
final Printer printer = new Printer(factory.getLock("test:lock:1", 30000));
final Printer printer = new Printer(factory.create("test:lock:1", 30000));
final AtomicInteger num = new AtomicInteger(0);
String line;
List<Thread> threads = new ArrayList<>();
Expand All @@ -122,7 +122,7 @@ public void test1() throws IOException, InterruptedException {
@Test
public void test2() throws IOException, InterruptedException {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file())));
final Lock lock = factory.getLock("test:lock:2", 30000);
final Lock lock = factory.create("test:lock:2", 30000);
final AtomicInteger num = new AtomicInteger(0);
String line;
List<Thread> threads = new ArrayList<>();
Expand Down Expand Up @@ -156,7 +156,7 @@ public void test3() throws IOException, InterruptedException {
final String line0 = line;
if (ThreadLocalRandom.current().nextInt(RATIO) == 0) {
threads.add(new Thread(
() -> new Printer(factory.getLock("test:lock:3", 30000)).output(NAME + "-" + num.getAndIncrement() + "\t" + line0 + "\n")
() -> new Printer(factory.create("test:lock:3", 30000)).output(NAME + "-" + num.getAndIncrement() + "\t" + line0 + "\n")
));
}
}
Expand All @@ -172,7 +172,7 @@ public void test3() throws IOException, InterruptedException {

@Test
public void test4() throws IOException {
Printer printer = new Printer(factory.getLock("test:lock:4", 30000));
Printer printer = new Printer(factory.create("test:lock:4", 30000));
AtomicInteger num = new AtomicInteger(RATIO);
System.out.println("\n=========================START========================");
List<Map<Integer, String>> lines = Files.readLines(file(), StandardCharsets.UTF_8)
Expand Down Expand Up @@ -201,7 +201,7 @@ public void testTryLockWithTimeout() throws InterruptedException {
String lockKey = "test:lock:" + ObjectUtils.uuid32();
String actualKey = "lock:" + lockKey;

RedisLock redisLock = factory.getLock(lockKey, expire);
RedisLock redisLock = factory.create(lockKey, expire);
Assertions.assertTrue(redisLock.tryLock());

Assertions.assertTrue(bean.hasKey(actualKey));
Expand Down

0 comments on commit c95b267

Please sign in to comment.