package org.redisson;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Assert;
import org.junit.Test;
import io.netty.channel.nio.NioEventLoopGroup;
import org.redisson.RedisRunner.RedisProcess;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import static com.jayway.awaitility.Awaitility.await;
import static org.assertj.core.api.Assertions.assertThat;
public class RedissonRedLockTest {
@Test
public void testLockLeasetime() throws IOException, InterruptedException {
RedisProcess redis1 = redisTestMultilockInstance();
RedisProcess redis2 = redisTestMultilockInstance();
RedissonClient client1 = createClient(redis1.getRedisServerAddressAndPort());
RedissonClient client2 = createClient(redis2.getRedisServerAddressAndPort());
RLock lock1 = client1.getLock("lock1");
RLock lock2 = client1.getLock("lock2");
RLock lock3 = client2.getLock("lock3");
RLock lock4 = client2.getLock("lock4");
RLock lock5 = client2.getLock("lock5");
RLock lock6 = client2.getLock("lock6");
RLock lock7 = client2.getLock("lock7");
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3, lock4, lock5, lock6, lock7);
ExecutorService executor = Executors.newFixedThreadPool(10);
AtomicInteger counter = new AtomicInteger();
for (int i = 0; i < 10; i++) {
executor.submit(() -> {
for (int j = 0; j < 5; j++) {
try {
lock.lock(2, TimeUnit.SECONDS);
int nextValue = counter.get() + 1;
Thread.sleep(1000);
counter.set(nextValue);
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
executor.shutdown();
assertThat(executor.awaitTermination(2, TimeUnit.MINUTES)).isTrue();
assertThat(counter.get()).isEqualTo(50);
client1.shutdown();
client2.shutdown();
assertThat(redis1.stop()).isEqualTo(0);
assertThat(redis2.stop()).isEqualTo(0);
}
@Test
public void testTryLockLeasetime() throws IOException, InterruptedException {
RedisProcess redis1 = redisTestMultilockInstance();
RedisProcess redis2 = redisTestMultilockInstance();
RedissonClient client1 = createClient(redis1.getRedisServerAddressAndPort());
RedissonClient client2 = createClient(redis2.getRedisServerAddressAndPort());
RLock lock1 = client1.getLock("lock1");
RLock lock2 = client1.getLock("lock2");
RLock lock3 = client2.getLock("lock3");
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
ExecutorService executor = Executors.newFixedThreadPool(10);
AtomicInteger counter = new AtomicInteger();
for (int i = 0; i < 10; i++) {
executor.submit(() -> {
for (int j = 0; j < 5; j++) {
try {
if (lock.tryLock(4, 2, TimeUnit.SECONDS)) {
int nextValue = counter.get() + 1;
Thread.sleep(1000);
counter.set(nextValue);
lock.unlock();
} else {
j--;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
executor.shutdown();
assertThat(executor.awaitTermination(2, TimeUnit.MINUTES)).isTrue();
assertThat(counter.get()).isEqualTo(50);
client1.shutdown();
client2.shutdown();
assertThat(redis1.stop()).isEqualTo(0);
assertThat(redis2.stop()).isEqualTo(0);
}
@Test
public void testLockFailed() throws IOException, InterruptedException {
RedisProcess redis1 = redisTestMultilockInstance();
RedisProcess redis2 = redisTestMultilockInstance();
RedissonClient client1 = createClient(redis1.getRedisServerAddressAndPort());
RedissonClient client2 = createClient(redis2.getRedisServerAddressAndPort());
RLock lock1 = client1.getLock("lock1");
RLock lock2 = client1.getLock("lock2");
RLock lock3 = client2.getLock("lock3");
Thread t1 = new Thread() {
public void run() {
lock2.lock();
lock3.lock();
};
};
t1.start();
t1.join();
Thread t = new Thread() {
public void run() {
RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock();
};
};
t.start();
t.join(1000);
RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
Assert.assertFalse(lock.tryLock());
client1.shutdown();
client2.shutdown();
assertThat(redis1.stop()).isEqualTo(0);
assertThat(redis2.stop()).isEqualTo(0);
}
@Test
public void testLockSuccess() throws IOException, InterruptedException {
RedisProcess redis1 = redisTestMultilockInstance();
RedisProcess redis2 = redisTestMultilockInstance();
RedissonClient client1 = createClient(redis1.getRedisServerAddressAndPort());
RedissonClient client2 = createClient(redis2.getRedisServerAddressAndPort());
RLock lock1 = client1.getLock("lock1");
RLock lock2 = client1.getLock("lock2");
RLock lock3 = client2.getLock("lock3");
Thread t1 = new Thread() {
public void run() {
lock3.lock();
};
};
t1.start();
t1.join();
Thread t = new Thread() {
public void run() {
RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
lock.unlock();
};
};
t.start();
t.join(1000);
lock3.delete();
RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock();
lock.unlock();
client1.shutdown();
client2.shutdown();
assertThat(redis1.stop()).isEqualTo(0);
assertThat(redis2.stop()).isEqualTo(0);
}
@Test
public void testConnectionFailed() throws IOException, InterruptedException {
RedisProcess redis1 = redisTestMultilockInstance();
RedisProcess redis2 = redisTestMultilockInstance();
RedissonClient client1 = createClient(redis1.getRedisServerAddressAndPort());
RedissonClient client2 = createClient(redis2.getRedisServerAddressAndPort());
RLock lock1 = client1.getLock("lock1");
RLock lock2 = client1.getLock("lock2");
assertThat(redis2.stop()).isEqualTo(0);
RLock lock3 = client2.getLock("lock3");
Thread t = new Thread() {
public void run() {
RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
lock.unlock();
};
};
t.start();
t.join(1000);
RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock();
lock.unlock();
client1.shutdown();
client2.shutdown();
assertThat(redis1.stop()).isEqualTo(0);
}
// @Test
public void testMultiThreads() throws IOException, InterruptedException {
RedisProcess redis1 = redisTestMultilockInstance();
Config config1 = new Config();
config1.useSingleServer().setAddress(redis1.getRedisServerAddressAndPort());
RedissonClient client = Redisson.create(config1);
RLock lock1 = client.getLock("lock1");
RLock lock2 = client.getLock("lock2");
RLock lock3 = client.getLock("lock3");
Thread t = new Thread() {
public void run() {
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
lock.unlock();
};
};
t.start();
t.join(1000);
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
lock.unlock();
client.shutdown();
assertThat(redis1.stop()).isEqualTo(0);
}
// @Test
public void test() throws IOException, InterruptedException {
RedisProcess redis1 = redisTestMultilockInstance();
RedisProcess redis2 = redisTestMultilockInstance();
RedisProcess redis3 = redisTestMultilockInstance();
NioEventLoopGroup group = new NioEventLoopGroup();
RedissonClient client1 = createClient(group, redis1.getRedisServerAddressAndPort());
RedissonClient client2 = createClient(group, redis2.getRedisServerAddressAndPort());
RedissonClient client3 = createClient(group, redis3.getRedisServerAddressAndPort());
final RLock lock1 = client1.getLock("lock1");
final RLock lock2 = client2.getLock("lock2");
final RLock lock3 = client3.getLock("lock3");
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
final AtomicBoolean executed = new AtomicBoolean();
Thread t = new Thread() {
@Override
public void run() {
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
assertThat(lock.tryLock()).isFalse();
assertThat(lock.tryLock()).isFalse();
executed.set(true);
}
};
t.start();
t.join();
await().atMost(5, TimeUnit.SECONDS).until(() -> assertThat(executed.get()).isTrue());
lock.unlock();
assertThat(redis1.stop()).isEqualTo(0);
assertThat(redis2.stop()).isEqualTo(0);
assertThat(redis3.stop()).isEqualTo(0);
}
private RedissonClient createClient(String host) {
return createClient(null, host);
}
private RedissonClient createClient(NioEventLoopGroup group, String host) {
Config config1 = new Config();
config1.useSingleServer().setAddress(host);
config1.setEventLoopGroup(group);
RedissonClient client1 = Redisson.create(config1);
client1.getKeys().flushdb();
return client1;
}
private RedisProcess redisTestMultilockInstance() throws IOException, InterruptedException {
return new RedisRunner()
.nosave()
.randomDir()
.randomPort()
.run();
}
}