(1). 概述

在前面源码分析过Redsson,昨晚,刷到:RedisLockRegistry,比较好奇,起床第一件事就是尝试一把,结果出乎我的意料,总结下缺点:
1) Redis不能是集群模式,否则,会抛错(Redsson不会有这情况).
2) LockRegistry为key配置的过期时间默认为60s,如果业务执行80秒,在key到达60秒时会消失,LockRegistry并不会自动续锁,有点恐怖哈.

(2). 添加依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
</dependency>

<!-- redis-lock -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.integration</groupId>
   <artifactId>spring-integration-redis</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

(3). RedisConnectionFactoryConfig

// 1. 配置锁
@Bean
public LockRegistry lockRegistry(RedisConnectionFactory redisConnectionFactory) {
	// test          : 为key的前缀
	// expireAfter   : 过期时间(注意:默认是60秒)
	// 问题来了,如果我业务执行有80秒,会不会帮我自动续锁?
	RedisLockRegistry redisLockRegistry = new RedisLockRegistry(redisConnectionFactory, "test");
	return redisLockRegistry;
}

// 2. 配置连接池工厂
@Bean
public RedisConnectionFactory redisConnectionFactory() {
	JedisShardInfo jedisShardInfo = new JedisShardInfo("127.0.0.1", 6379);
	return new JedisConnectionFactory(jedisShardInfo);
}

(4). HelloService

@Service
public class HelloService implements IHelloService {
	private Logger logger = LoggerFactory.getLogger(HelloService.class);

	@Autowired
	private LockRegistry lockRegistry;

	public List<User> findByTenantId(Long tenantId) {
		List<User> results = new ArrayList<User>();
		
		Lock lock = lockRegistry.obtain("users");
		try {
			// 加锁
			lock.lock();
			
			System.out.println("lock start");
			// 休息80秒,看Redis中KEY的状态.
			TimeUnit.SECONDS.sleep(80);
			// ... ...
			System.out.println("lock end");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			// 释放锁
			lock.unlock();
		}
		return results;
	} // end findByTenantId
}// end 

(5). 测试结果

127.0.0.1:6379> keys *
1) "test:users"
127.0.0.1:6379> TTL "test:users"
(integer) 49
127.0.0.1:6379> TTL "test:users"
(integer) 47

// 60秒后....

127.0.0.1:6379> TTL "test:users"
(integer) 0
127.0.0.1:6379> TTL "test:users"
(integer) -2
127.0.0.1:6379> keys *
(empty list or set)

(6). 缺陷

# 在Redis集群模式下,LockRegistry报错如下:
# 集群模式下不支持evalSha函数.
org.springframework.dao.InvalidDataAccessApiUsageException: EvalSha is not supported in cluster environment.