Skip to content
On this page

分布式锁中间件集成组件

基于Redisson实现的Redis统一集成组件。

1. 集成说明

(1)在 pom.xml 配置文件中引入 :

xml
<dependency>
    <groupId>com.chinapost.mids</groupId>
    <artifactId>cpms-redisson-spring-boot-starter</artifactId>
    <version>1.0.1-RELEASE</version>
</dependency>

(2)在 application.yml 配置文件增加:

yaml
#单Redis节点模式
redisson:
  singleServerConfig:
    address: 127.0.0.1:6379

2. 使用说明

2.1. 如何使用分布式锁?

在方法增加 @Lock 注解

java
//1.支持spel表达式,keyConstant是常量(可选)
@Lock(keys = "#user.name",keyConstant = "常量"))
public String test(User user) {
    System.out.println("进来了test");
    return "test";
}

@Lock 注解参数介绍

java
/**
 * REENTRANT(可重入锁),FAIR(公平锁),MULTIPLE(联锁),REDLOCK(红锁),READ(读锁), WRITE(写锁), 
 * AUTO(自动模式,当参数只有一个.使用 REENTRANT 参数多个 MULTIPLE)
 */
LockModel lockModel() default LockModel.AUTO;
/**
 * 需要锁定的keys
 * @return
 */
String[] keys() default {};
/**
 * 锁超时时间,默认30000毫秒(可在配置文件全局设置)
 * @return
 */
long lockWatchdogTimeout() default 0;
/**
 * 等待加锁超时时间,默认10000毫秒 -1 则表示一直等待(可在配置文件全局设置)
 * @return
 */
long attemptTimeout() default 0;

2.2. 如何存储数据?

目前实现了三个对象模板:RedissonObject、RedissonBinary、RedissonCollection。

(1)RedissonObject

RedissonObject 这个是比较通用的模板,任何对象都可以存在这里面,在spring 容器中注入对象即可:

java
@Resource
private RedissonObject redissonObject;

完整示例:

java
@Controller
public class ObjectController {

    @Resource
    private RedissonObject redissonObject;

    /**
     * 设置值
     * @param user
     * @param request
     * @param response
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/object1")
    @ResponseBody
    public String object1(User user, HttpServletRequest request, HttpServletResponse response) throws InterruptedException {
        User user1 = new User();
        user1.setName("test");
        user1.setAge("123");
        redissonObject.setValue("object1", user1,-1L);
        return "";
    }

    /**
     * 获取值
     * @param user
     * @param request
     * @param response
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/object2")
    @ResponseBody
    public Object object2(User user, HttpServletRequest request, HttpServletResponse response) throws InterruptedException {
        return redissonObject.getValue("object1");
    }

    /**
     * 如果对象不存在则设置,否则不设置
     * @param user
     * @param request
     * @param response
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/object3")
    @ResponseBody
    public String object3(User user, HttpServletRequest request, HttpServletResponse response) throws InterruptedException {
        return redissonObject.trySetValue("object1","object1-2")+"";
    }
}

(2)RedissonBinary

RedissonBinary 这个是存储二进制的模板,可以存放图片之内的二进制文件,在spring 容器中注入对象即可:

java
@Resource
private RedissonBinary redissonBinary;

完整示例:

java
@Controller
public class BinaryController {

    @Resource
    private RedissonBinary redissonBinary;

    /**
     * 存放图片
     * @param user
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/binary1")
    @ResponseBody
    public String binary1(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
        redissonBinary.setValue("binary",new FileInputStream(new File("f:/1.png")));
        return "11";
    }

    /**
     * 获取图片
     * @param user
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("/binary2")
    public void binary2(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
        redissonBinary.getValue("binary",response.getOutputStream());

    }
}

(3)RedissonCollection

RedissonCollection这个是集合模板,可以存放 Map, List, Set 集合元素,在spring 容器中注入对象即可:

java
@Resource
private RedissonCollection redissonCollection;

完整示例:

java
@Controller
public class CollectionController {

    @Resource
    private RedissonCollection redissonCollection;

    /**
     * map操作
     * @param user
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/collection1")
    @ResponseBody
    public String collection1(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String,String> map=new HashMap<>();
        map.put("test1","test11");
        map.put("test2","test22");
        map.put("test3","test33");
        map.put("test4","test44");
        //设置值
        redissonCollection.setMapValues("test",map);

        //获取值
        RMap<String, String> test = redissonCollection.getMap("test");
        System.out.println(test);
        return "11";
    }

    /**
     * list操作
     * @param user
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/collection2")
    @ResponseBody
    public String collection2(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
        List<String> list=new ArrayList<>();
        list.add("test1");
        list.add("test2");
        list.add("test3");
        list.add("test4");
        list.add("test5");
        //设置值
        redissonCollection.setListValues("list",list);

        //获取值
        RList<Object> list1 = redissonCollection.getList("list");
        System.out.println(list1);
        return "11";
    }
    /**
     * set操作
     * @param user
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/collection3")
    @ResponseBody
    public String collection3(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Set<String> set=new HashSet<>();
        set.add("test1");
        set.add("test2");
        set.add("test3");
        set.add("test4");
        set.add("test5");
        //设置值
        redissonCollection.setSetValues("set",set);

        //获取值
        RSet<Object> set1 = redissonCollection.getSet("set");
        System.out.println(set1);
        return "11";
    }


}

2.3. 如何session集群?

在启动类标注 @EnableRedissonHttpSession 即可。

2.4. 如何使用 redisson 客户端实现自定义操作

只需要在spring 容器中注入redisson客户端就行,如下:

java
@Autowired
private RedissonClient redissonClient;

2.5. 如何集成 spring cache

启动类加上 @EnableCache(value = {"cache1","cache2"}) ,@Cacheable,@CachePut,@CacheEvict的value必须包含在这里面。


完整示例:

java
package com.chinapost.mids.redisson.starter.test.controller;

import com.chinapost.mids.redisson.starter.test.bean.User;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class CacheController {

    @RequestMapping("/cache1")
    @ResponseBody
    @Cacheable(value = "cache1",key = "'test1'")
    public String cache1(){
        return "test";
    }
    @RequestMapping("/cache2")
    @ResponseBody
    @Cacheable(value = "cache2",key = "'test2'")
    public User cache2(){
        User user=new User();
        user.setName("name");
        user.setAge("123");
        return user;
    }

}

2.6. 如何使用消息队列MQ.

两个注解即可完成操作。

消息队列分为 生产者 以及 消费者生产者 生产消息供 消费者 消费。

生产者 配置

发送消息有两种模式,二选一即可:

(1)代码模式

java
RTopic testMq = redissonClient.getTopic("testMq");
User message = new User();
message.setAge("12");
message.setName("的身份为");
testMq.publish(message);

(2)注解模式

java
@RequestMapping("testMq1")
@ResponseBody
@MQPublish(name = "test")
public User testMq1(){
    User user=new User();
    user.setName("garegarg");
    user.setAge("123");
    return user;
}

消费者 配置

(1)启动类加上 @EnableMQ 开启消费者

(2)使用注解@MQListener(name = "testMq")配置消费者

java
@MQListener(name = "testMq")
public void test1(CharSequence charSequence,User o,Object object){
    System.out.println("charSequence="+charSequence);
    System.out.println("收到消息2"+o);
}

完整示例:

生产者
java
import MQPublish;
import com.chinapost.mids.redisson.starter.test.bean.User;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

@Controller
public class MQController {

    @Resource
    private RedissonClient redissonClient;


    /**
     * 发送方式一: 使用代码发送消息
     */
    @RequestMapping("testMq")
    @ResponseBody
    public void testMq() {
        RTopic testMq = redissonClient.getTopic("testMq");
        User message = new User();
        message.setAge("12");
        message.setName("的身份为");
        testMq.publish(message);
    }

    /**
     * 发送方式二:使用注解发送消息, 返回值就是需要发送的消息
     * @return
     */
    @RequestMapping("testMq1")
    @ResponseBody
    @MQPublish(name = "test")
    public User testMq1() {
        User user = new User();
        user.setName("garegarg");
        user.setAge("123");
        return user;
    }

}
消费者
java
package com.chinapost.mids.redisson.starter.test.listener;

import MQListener;
import MQModel;
import com.chinapost.mids.redisson.starter.test.bean.User;
import org.springframework.stereotype.Component;

//注入到spring容器中
@Component
public class MQListeners {

    /**
     * 接受消息方式一:PRECISE精准的匹配 如:name="myTopic" 那么发送者的topic name也一定要等于myTopic (如果消息类型不明确,请使用Object 接收消息)
     * @param charSequence
     * @param o
     */
    @MQListener(name = "testMq")
    public void test1(CharSequence charSequence, User o, Object object) {
        System.out.println("charSequence=" + charSequence);
        System.out.println("收到消息2" + o);
    }

    /**
     *
     * 接收消息方式二: PATTERN模糊匹配 如: name="myTopic.*" 那么发送者的topic name 可以是 myTopic.name1 myTopic.name2.尾缀不限定
     * @param patten
     * @param charSequence
     * @param o
     */
    @MQListener(name = "test*", model = MQModel.PATTERN)
    public void test1(CharSequence patten, CharSequence charSequence, User o) {
        System.out.println("patten=" + patten);
        System.out.println("charSequence=" + charSequence);
        System.out.println("test*=" + o);
    }
}

2.7. 集群模式配置(也可以使用yml写法)

单例模式

单机版redis

yaml
#单Redis节点模式
redisson:
  singleServerConfig:
    address: 127.0.0.1:6379
集群模式

集群模式除了适用于Redis集群环境,也适用于任何云计算服务商提供的集群模式,例如AWS ElastiCache集群版、Azure Redis Cache和阿里云(Aliyun)的云数据库Redis版。

yaml
#集群模式
redisson:
  model: CLUSTER
  password: xxx
  multiple-server-config:
    #redis机器.一直累加下去
    node-addresses:
      - 127.0.0.1:6379
      - 127.0.0.1:6380
      - 127.0.0.1:6381
云托管模式

云托管模式适用于任何由云计算运营商提供的Redis云服务,包括:亚马逊云的AWS ElastiCache、微软云的Azure Redis 缓存和阿里云(Aliyun)的云数据库Redis版

yaml
#云托管模式
redisson:
  model: REPLICATED
  password: xxx
  multiple-server-config:
    #redis机器.一直累加下去
    node-addresses:
      - 127.0.0.1:6379
      - 127.0.0.1:6380
      - 127.0.0.1:6381
哨兵模式
yaml
redisson:
  model: SENTINEL
  password: xxx
  #主服务器的名称是哨兵进程中用来监测主从服务切换情况的。
  multiple-server-config:
    master-name: mymaster
    #redis机器.一直累加下去
    node-addresses:
      - 127.0.0.1:6379
      - 127.0.0.1:6380
      - 127.0.0.1:6381

只有一个代理地址的redis哨兵模式

yaml
redisson:
  model: SENTINEL
  password: xxx
  #主服务器的名称是哨兵进程中用来监测主从服务切换情况的。
  multiple-server-config:
    master-name: mymaster
    check-sentinels-list: false
    node-addresses: 127.0.0.1:6379
主从模式
yaml
redisson:
  model: MASTERSLAVE
  password: xxx
  multiple-server-config:
    #第一台机器就是主库.其他的为从库
    node-addresses:
      - 127.0.0.1:6379
      - 127.0.0.1:6380
      - 127.0.0.1:6381