码迷,mamicode.com
首页 > 其他好文 > 详细

Redisson的简单使用

时间:2021-02-02 11:13:05      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:定时   package   rgba   roo   项目   redisson   map   its   filter   

  在之前的项目中分布式锁和限流是基于redis进行的,分布式锁基于setnx和expire命令实现,也可以基于lua脚本实现。限流是采用固定时间窗算法进行的。

  最近了解到redisson这个工具类,而且基于其分布式锁的实现是比较常见的,简单研究下其使用。

官网:wiki地址    https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95

1. 概述

  官网解释如下:Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

2.研究其分布式锁的用法

pom增加:

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.15.0</version>
        </dependency>

增加日志文件 logback.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="60000">
    <property name="LOG_HOME" value="/export/logs/cmdb/"/>
    <property name="APP_NAME" value="cmdb"/>
    <property name="LOG_FILE_EXPIRE_TIME" value="180"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | ${APP_NAME} - %p | %thread | %c | line:%L - %m%n</pattern>
        </encoder>
    </appender>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}${APP_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>${LOG_FILE_EXPIRE_TIME}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | ${APP_NAME} - %p | %thread | %c | line:%L - %m%n</pattern>
        </encoder>
    </appender>

    <root>
        <level value="ERROR"/>
        <appender-ref ref="STDOUT"/>
        <!--<appender-ref ref="FILE"/>-->
    </root>
    <!-- 不同包,设置不同的日志级别 -->
    <logger name="com.xm.ggn" level="INFO"/>
</configuration>

1. 简单的使用

package com.xm.ggn.test.redisson;

import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import java.util.concurrent.TimeUnit;

@Slf4j
public class Client {

    private static final Long TIME_LOCKED = 50 * 1000l;
    private static final String KEY_LOCKED = "myLock";
    private static RedissonClient redissonClient = null;

    public static void main(String[] args) {
        initRedissonClient();
        lock();
    }

    private static void initRedissonClient() {
        // 1. Create config object
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        // 2. Create Redisson instance
        Client.redissonClient = Redisson.create(config);
    }

    private static void lock() {
        RLock lock1 = redissonClient.getLock(KEY_LOCKED);
        log.error("lock1 clas: {}", lock1.getClass());
        lock1.lock();
        log.info("lock, ThreadName: {} id: {} locked, 重入次数: {}", Thread.currentThread().getName(), Thread.currentThread().getId(), lock1.getHoldCount());

        // 处理业务逻辑
        try {
            Thread.sleep(TIME_LOCKED);
            reLock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock1.unlock();
            log.info("lock, ThreadName: {} id: {} unlock, 重入次数: {}", Thread.currentThread().getName(), Thread.currentThread().getId(), lock1.getHoldCount());
        }
    }

    /**
     * 测试锁的重入
     */
    private static void reLock() {
        RLock lock1 = redissonClient.getLock(KEY_LOCKED);
        lock1.lock();
        log.info("reLock, ThreadName: {} id: {} locked, 重入次数: {}", Thread.currentThread().getName(), Thread.currentThread().getId(), lock1.getHoldCount());

        // 处理业务逻辑
        try {
            Thread.sleep(TIME_LOCKED);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock1.unlock();
            log.info("reLock, ThreadName: {} id: {} unlock, 重入次数: {}", Thread.currentThread().getName(), Thread.currentThread().getId(), lock1.getHoldCount());
        }
    }
}

结果:

2021-02-01 16:20:23.013 | cmdb - ERROR | main | com.xm.ggn.test.redisson.Client | line:35 - lock1 clas: class org.redisson.RedissonLock
2021-02-01 16:20:23.050 | cmdb - INFO | main | com.xm.ggn.test.redisson.Client | line:37 - lock, ThreadName: main id: 1 locked, 重入次数: 1
2021-02-01 16:21:13.056 | cmdb - INFO | main | com.xm.ggn.test.redisson.Client | line:57 - reLock, ThreadName: main id: 1 locked, 重入次数: 2
2021-02-01 16:22:03.059 | cmdb - INFO | main | com.xm.ggn.test.redisson.Client | line:66 - reLock, ThreadName: main id: 1 unlock, 重入次数: 1
2021-02-01 16:22:03.061 | cmdb - INFO | main | com.xm.ggn.test.redisson.Client | line:47 - lock, ThreadName: main id: 1 unlock, 重入次数: 0

注意:

(1)redis中是通过HASH来存储锁的,key是UUID+":"+ThreadId;value 是重入的层数,例如上面过程中查看redis数据如下:

127.0.0.1:6379> hgetall myLock
1) "c20d8714-89c6-485f-ad4f-8dbb54271ebf:1"
2) "1"
127.0.0.1:6379> hgetall myLock
1) "c20d8714-89c6-485f-ad4f-8dbb54271ebf:1"
2) "2"
127.0.0.1:6379> hgetall myLock
(empty list or set)

(2)也可以使用lock(long var1, TimeUnit var3); 方法自动释放锁

    private static void lock3() {
        RLock lock1 = redissonClient.getLock(KEY_LOCKED);
        log.error("lock1 clas: {}", lock1.getClass());
        // 500s 后自动释放锁
        lock1.lock(500, TimeUnit.SECONDS);
        try {
            Thread.sleep(TIME_LOCKED);
        } catch (InterruptedException ignore) {
            // ignore
        }
    }

测试查看日志如下:

127.0.0.1:6379> ttl myLock
(integer) 493
127.0.0.1:6379> hgetall myLock
1) "3cdf7b21-1e36-4f1f-b0ba-f0339286f416:1"
2) "1"

(3)tryLock(long time, TimeUnit unit)  可以尝试一定时间去获取锁,返回Boolean值

    private static void lock2() {
        for (int i = 0; i < 3; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    log.info(Thread.currentThread().getName() + " \t 运行");
                    RLock lock1 = redissonClient.getLock(KEY_LOCKED);
                    try {
                        // 尝试获取锁60s
                        boolean b = lock1.tryLock(7, TimeUnit.SECONDS);
                        if (!b) {
                            log.info(Thread.currentThread().getName() + " \t 获取锁失败");
                            return;
                        }
                    } catch (InterruptedException e) {
                    }

                    log.info(Thread.currentThread().getName() + " \t 获取锁");

                    try {
                        // 模拟处理逻辑用时50s
                        Thread.sleep(5 * 1000);
                    } catch (InterruptedException e) {

                    }

                    lock1.unlock();
                    log.info(Thread.currentThread().getName() + " \t 释放锁");
                }
            }).start();
        }
    }

结果:

2021-02-01 17:17:04.915 | cmdb - INFO | Thread-3 | com.xm.ggn.test.redisson.Client | line:121 - Thread-3 运行
2021-02-01 17:17:04.915 | cmdb - INFO | Thread-1 | com.xm.ggn.test.redisson.Client | line:121 - Thread-1 运行
2021-02-01 17:17:04.915 | cmdb - INFO | Thread-2 | com.xm.ggn.test.redisson.Client | line:121 - Thread-2 运行
2021-02-01 17:17:04.949 | cmdb - INFO | Thread-1 | com.xm.ggn.test.redisson.Client | line:133 - Thread-1 获取锁
2021-02-01 17:17:09.952 | cmdb - INFO | Thread-1 | com.xm.ggn.test.redisson.Client | line:143 - Thread-1 释放锁
2021-02-01 17:17:09.954 | cmdb - INFO | Thread-3 | com.xm.ggn.test.redisson.Client | line:133 - Thread-3 获取锁
2021-02-01 17:17:11.925 | cmdb - INFO | Thread-2 | com.xm.ggn.test.redisson.Client | line:127 - Thread-2 获取锁失败
2021-02-01 17:17:14.956 | cmdb - INFO | Thread-3 | com.xm.ggn.test.redisson.Client | line:143 - Thread-3 释放锁

(4) 查看RLock的继承关系如下

技术图片

 2. 公平锁的使用

默认使用的是非公平锁,不过一般情况使用的都是公平锁,也就是先到先得。

(1)默认非公平锁

    private static void lock1() {
        for (int i = 0; i < 5; i++) {
            // 休眠一下使线程按照顺序启动
            try {
                Thread.sleep(1 * 100);
            } catch (InterruptedException e) {
            }

            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    log.info(Thread.currentThread().getName() + " \t 运行");
                    // 下面方式获取到的是非公平锁
                    RLock lock1 = redissonClient.getLock(KEY_LOCKED);
//                    RLock lock1 = redissonClient.getFairLock(KEY_LOCKED);
                    log.error("lock1 clas: {}", lock1.getClass());
                    lock1.lock();

                    log.info(Thread.currentThread().getName() + " \t 获取锁");
                    try {
                        Thread.sleep(TIME_LOCKED);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    log.info(Thread.currentThread().getName() + " \t 释放锁");
                    lock1.unlock();
                }
            });
            thread.setName("MyThread: " + i);
            thread.start();
        }
    }

结果:

2021-02-01 17:34:02.226 | cmdb - INFO | MyThread: 0 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 0 运行
2021-02-01 17:34:02.233 | cmdb - ERROR | MyThread: 0 | com.xm.ggn.test.redisson.Client | line:100 - lock1 clas: class org.redisson.RedissonLock
2021-02-01 17:34:02.325 | cmdb - INFO | MyThread: 1 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 1 运行
2021-02-01 17:34:02.325 | cmdb - ERROR | MyThread: 1 | com.xm.ggn.test.redisson.Client | line:100 - lock1 clas: class org.redisson.RedissonLock
2021-02-01 17:34:02.426 | cmdb - INFO | MyThread: 2 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 2 运行
2021-02-01 17:34:02.426 | cmdb - ERROR | MyThread: 2 | com.xm.ggn.test.redisson.Client | line:100 - lock1 clas: class org.redisson.RedissonLock
2021-02-01 17:34:02.526 | cmdb - INFO | MyThread: 3 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 3 运行
2021-02-01 17:34:02.526 | cmdb - ERROR | MyThread: 3 | com.xm.ggn.test.redisson.Client | line:100 - lock1 clas: class org.redisson.RedissonLock
2021-02-01 17:34:02.627 | cmdb - INFO | MyThread: 4 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 4 运行
2021-02-01 17:34:02.627 | cmdb - ERROR | MyThread: 4 | com.xm.ggn.test.redisson.Client | line:100 - lock1 clas: class org.redisson.RedissonLock
2021-02-01 17:34:16.038 | cmdb - INFO | MyThread: 3 | com.xm.ggn.test.redisson.Client | line:103 - MyThread: 3 获取锁
2021-02-01 17:34:21.038 | cmdb - INFO | MyThread: 3 | com.xm.ggn.test.redisson.Client | line:110 - MyThread: 3 释放锁
2021-02-01 17:34:21.043 | cmdb - INFO | MyThread: 1 | com.xm.ggn.test.redisson.Client | line:103 - MyThread: 1 获取锁
2021-02-01 17:34:26.044 | cmdb - INFO | MyThread: 1 | com.xm.ggn.test.redisson.Client | line:110 - MyThread: 1 释放锁
2021-02-01 17:34:26.047 | cmdb - INFO | MyThread: 0 | com.xm.ggn.test.redisson.Client | line:103 - MyThread: 0 获取锁
2021-02-01 17:34:31.047 | cmdb - INFO | MyThread: 0 | com.xm.ggn.test.redisson.Client | line:110 - MyThread: 0 释放锁
2021-02-01 17:34:31.050 | cmdb - INFO | MyThread: 4 | com.xm.ggn.test.redisson.Client | line:103 - MyThread: 4 获取锁
2021-02-01 17:34:36.050 | cmdb - INFO | MyThread: 4 | com.xm.ggn.test.redisson.Client | line:110 - MyThread: 4 释放锁
2021-02-01 17:34:36.054 | cmdb - INFO | MyThread: 2 | com.xm.ggn.test.redisson.Client | line:103 - MyThread: 2 获取锁
2021-02-01 17:34:41.055 | cmdb - INFO | MyThread: 2 | com.xm.ggn.test.redisson.Client | line:110 - MyThread: 2 释放锁

(2)  公平锁的使用

主要代码同上,只是获取锁变为公平锁

RLock lock1 = redissonClient.getFairLock(KEY_LOCKED);

结果:

2021-02-01 17:38:04.689 | cmdb - INFO | MyThread: 0 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 0      运行
2021-02-01 17:38:04.696 | cmdb - ERROR | MyThread: 0 | com.xm.ggn.test.redisson.Client | line:98 - lock1 clas: class org.redisson.RedissonFairLock
2021-02-01 17:38:04.721 | cmdb - INFO | MyThread: 0 | com.xm.ggn.test.redisson.Client | line:101 - MyThread: 0      获取锁
2021-02-01 17:38:04.787 | cmdb - INFO | MyThread: 1 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 1      运行
2021-02-01 17:38:04.787 | cmdb - ERROR | MyThread: 1 | com.xm.ggn.test.redisson.Client | line:98 - lock1 clas: class org.redisson.RedissonFairLock
2021-02-01 17:38:04.888 | cmdb - INFO | MyThread: 2 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 2      运行
2021-02-01 17:38:04.888 | cmdb - ERROR | MyThread: 2 | com.xm.ggn.test.redisson.Client | line:98 - lock1 clas: class org.redisson.RedissonFairLock
2021-02-01 17:38:04.989 | cmdb - INFO | MyThread: 3 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 3      运行
2021-02-01 17:38:04.989 | cmdb - ERROR | MyThread: 3 | com.xm.ggn.test.redisson.Client | line:98 - lock1 clas: class org.redisson.RedissonFairLock
2021-02-01 17:38:05.089 | cmdb - INFO | MyThread: 4 | com.xm.ggn.test.redisson.Client | line:96 - MyThread: 4      运行
2021-02-01 17:38:05.089 | cmdb - ERROR | MyThread: 4 | com.xm.ggn.test.redisson.Client | line:98 - lock1 clas: class org.redisson.RedissonFairLock
2021-02-01 17:38:09.723 | cmdb - INFO | MyThread: 0 | com.xm.ggn.test.redisson.Client | line:108 - MyThread: 0      释放锁
2021-02-01 17:38:09.729 | cmdb - INFO | MyThread: 1 | com.xm.ggn.test.redisson.Client | line:101 - MyThread: 1      获取锁
2021-02-01 17:38:14.729 | cmdb - INFO | MyThread: 1 | com.xm.ggn.test.redisson.Client | line:108 - MyThread: 1      释放锁
2021-02-01 17:38:14.732 | cmdb - INFO | MyThread: 2 | com.xm.ggn.test.redisson.Client | line:101 - MyThread: 2      获取锁
2021-02-01 17:38:19.732 | cmdb - INFO | MyThread: 2 | com.xm.ggn.test.redisson.Client | line:108 - MyThread: 2      释放锁
2021-02-01 17:38:19.734 | cmdb - INFO | MyThread: 3 | com.xm.ggn.test.redisson.Client | line:101 - MyThread: 3      获取锁
2021-02-01 17:38:24.734 | cmdb - INFO | MyThread: 3 | com.xm.ggn.test.redisson.Client | line:108 - MyThread: 3      释放锁
2021-02-01 17:38:24.737 | cmdb - INFO | MyThread: 4 | com.xm.ggn.test.redisson.Client | line:101 - MyThread: 4      获取锁
2021-02-01 17:38:29.738 | cmdb - INFO | MyThread: 4 | com.xm.ggn.test.redisson.Client | line:108 - MyThread: 4      释放锁

 

  至此简单研究下redisson分布式锁使用。一般是基于AOP自定义注解实现分布式锁。

 

Redisson的简单使用

标签:定时   package   rgba   roo   项目   redisson   map   its   filter   

原文地址:https://www.cnblogs.com/qlqwjy/p/14354385.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!