Redissonベースの分散ロック


以前はビジネスで分散ロックが実現されていましたが、redisのカウンタで実現されていました.その方法では、サービスがダウンした場合、keyはredisに永続的に保存されます.
従って、redissonに切り込むと、redissonはロックを取得する際にデッドロック問題を解決し、下位層はluaスクリプトを呼び出すことによってkeyの書き込みと期限切れの設定の原子性を実現する.
詳細redissonの情報は、公式ドキュメントを参照してください.
https://yq.aliyun.com/articles/554765?spm=a2c4e.11155435.0.0.634056a3ail7EF
使用条件
jdk 1.6+, redis 2.8+
導入pom

	org.redisson
	redisson
	3.5.4

redissonクライアントサービスの登録
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;

/**
 * redis    
 *
 * @author Demon-HY
 * @date 2019-8-19
 */
@Service
public class RedissonClientService {

    @Value("${redis.host}")
    private String redisHost;

    @Value("${redis.port}")
    private String redisPort;

    @Value("${redis.auth}")
    private String redisAuth;

    @Value("${redis.timeout}")
    private Integer redisTimeout;

    private RedissonClient redissonClient;

    @PostConstruct
    public void afterCreation() {
        Config config = new Config();
        //      
        config.useSingleServer()
                .setAddress(String.format("redis://%s:%s", redisHost, redisPort))
                .setPassword(redisAuth)
                //                ,       ,  :10000
                .setConnectTimeout(30000)
                //             ,               ,       ,  :3000
                .setReconnectionTimeout(10000)
                //            ,               ,  :3000
                .setTimeout(10000)
                //        retryAttempts(        )                   ,     .
                //               ,      timeout(      )   ,   :3
                .setRetryAttempts(5)
                //            ,           ,       ,   :1500
                .setRetryInterval(3000);
        redissonClient = Redisson.create(config);
    }

    /**
     *    
     *
     * @param lockName    
     * @return
     */
    public RLock getLock(String lockName) {
        return redissonClient.getLock(lockName);
    }

    /**
     *   name       
     *
     * @param lockName    
     * @param timeout      ,       ,    ,  : 
     * @return
     */
    public void lock(String lockName, long timeout) {
        RLock lock = getLock(lockName);
        //lock   timeout  ,timeout      ,    
        lock.lock(timeout, TimeUnit.SECONDS);
    }

    /**
     *   name       ,redisson tryLock         ,          ,         boolean。      
     *
     * @param lockName    
     * @param waitTime     ,             ,  : 
     * @param timeout         ,        ,  : 
     */
    public boolean tryLock(String lockName, long waitTime, long timeout) throws InterruptedException {
        RLock lock = getLock(lockName);
        //tryLock,          ,5       ,     。       60 60      
        return lock.tryLock(waitTime, timeout, TimeUnit.SECONDS);
    }

    /**
     *   name       
     *
     * @param lockName    
     */
    public void unlock(String lockName) {
        RLock lock = getLock(lockName);
        lock.unlock();
    }
}

テストコード
@Autowired
private RedissonClientService redissonClientService;

public void testLock(String lockName) {
    RLock lock = redissonClientService.getLock(lockName);
    try {
        //tryLock,          ,0       ,     。        180      
        if (!lock.tryLock(0L, 180L, TimeUnit.SECONDS)) {//     ,    
            logger.warn("   :{}   ", lockName);
            return;
        }

        //     ,      
        // ...
    } catch (Exception e) {
        logger.error("        ");
    } finally {
        lock.unlock();
    }
}