ToB企服应用市场:ToB评测及商务社交产业平台

标题: Redisson 总结 [打印本页]

作者: 八卦阵    时间: 2024-9-19 16:03
标题: Redisson 总结
1. 底子使用

1.1 引入依赖

  1. <dependencies>
  2.         <dependency>
  3.             <groupId>org.redisson</groupId>
  4.             <artifactId>redisson-spring-boot-starter</artifactId>
  5.         </dependency>
  6. </dependencies>
复制代码
包含的依赖如下

1.2 配置文件

其实默认主机就是 127.0.0.1,默认端口是 6379,一致的话可以不用配置
  1. spring:
  2.   data:
  3.     redis:
  4.       host: 127.0.0.1
  5.       password: redis
复制代码
1.3 测试类

  1. import org.redisson.api.RBucket;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. public class DemoController {
  8.     private final RedissonClient redissonClient;
  9.     @Autowired
  10.     public DemoController(RedissonClient redissonClient) {
  11.         this.redissonClient = redissonClient;
  12.     }
  13.     @GetMapping("/test")
  14.     public void test() {
  15.         RBucket<String> bucket = redissonClient.getBucket("test");
  16.         bucket.set("hello");
  17.     }
  18.     @GetMapping("/get")
  19.     public String get() {
  20.         RBucket<String> bucket = redissonClient.getBucket("test");
  21.         return bucket.get();
  22.     }
  23. }
复制代码
1.4 测试

访问 /test 接口,利用 Redis 管理工具可以看到数据已经添加了进来

在访问 /get 接口,乐成获取到数据

2. 设置序列化

上面可以看到在 Redis 管理工具中查看数据是一串字符,并不直观,可以自界说数据序列化
2.1 配置类

  1. import org.redisson.Redisson;
  2. import org.redisson.api.RedissonClient;
  3. import org.redisson.codec.JsonJacksonCodec;
  4. import org.redisson.config.Config;
  5. import org.redisson.config.SingleServerConfig;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. @Configuration
  9. public class RedissonConfig {
  10.     @Bean
  11.     public RedissonClient redissonClient() {
  12.         Config config = new Config();
  13.         // 单机模式
  14.         SingleServerConfig singleServerConfig = config.useSingleServer();
  15.         singleServerConfig.setAddress("redis://127.0.0.1:6379");
  16.         singleServerConfig.setPassword("redis");
  17.         // JSON序列化
  18.         config.setCodec(new JsonJacksonCodec());
  19.         return Redisson.create(config);
  20.     }
  21. }
复制代码
这里已经配置了主机等相干信息,因此配置文件里的配置可以去除,或者这里直接取配置文件的值,具体根据情况选择,其他的序列化类如下
编码类名称说明org.redisson.codec.JsonJacksonCodecJackson JSON 编码org.redisson.codec.AvroJacksonCodecAvro 一种二进制的 JSON 编码org.redisson.codec.SmileJacksonCodecSmile一种 二进制的 JSON 编码org.redisson.codec.CborJacksonCodecCBOR 一种二进制的 JSON 编码org.redisson.codec.MsgPackJacksonCodecMsgPack 一种 二进制的 JSON 编码org.redisson.codec.IonJacksonCodecAmazon Ion 亚马逊的 Ion 编码,格式与 JSON 类似org.redisson.codec.KryoCodecKryo 二进制对象序列化编码org.redisson.codec.SerializationCodecJDK 序列化编码org.redisson.codec.FstCodecFST 10 倍于 JDK 序列化性能而且 100% 兼容的编码org.redisson.codec.LZ4CodecLZ4 压缩型序列化对象编码org.redisson.codec.SnappyCodecSnappy 另一个压缩型序列化对象编码org.redisson.client.codec.JsonJacksonMapCodec基于 Jackson 的映射类使用的编码,可用于避免序列化类的信息,以及用于办理使用byte[] 碰到的问题org.redisson.client.codec.StringCodec纯字符串编码(无转换)org.redisson.client.codec.LongCodec纯整长型数字编码(无转换)org.redisson.client.codec.ByteArrayCodec字节数组编码org.redisson.codec.CompositeCodec用来组合多种不同编码在一起 2.2 测试

访问 /test 接口,再查看数据可以看到已经序列化成 JSON 格式

3. 底子数据结构使用

3.1 String

其实上面的示例用的就是字符串操作,通过 RBucket 对象来操作字符串数据结构
创建一个实体类
  1. import lombok.Builder;
  2. import lombok.Data;
  3. import java.io.Serial;
  4. import java.io.Serializable;
  5. @Data
  6. @Builder
  7. public class Article implements Serializable {
  8.     @Serial
  9.     private static final long serialVersionUID = -8862397425409851538L;
  10.   
  11.     private String title;
  12.     private String content;
  13. }
复制代码
存储对象,简单示比方下:
  1. import org.redisson.api.RBucket;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. public class DemoController {
  8.     private final RedissonClient redissonClient;
  9.     @Autowired
  10.     public DemoController(RedissonClient redissonClient) {
  11.         this.redissonClient = redissonClient;
  12.     }
  13.     @GetMapping("/test")
  14.     public void test() {
  15.         RBucket<Object> bucket = redissonClient.getBucket("test");
  16.         bucket.set(Article.builder().title("demo").content("test redisson").build());
  17.     }
  18. }
复制代码
数据如下:

3.2 Hash

通过 RMap 对象来操作哈希数据结构,简单示比方下:
  1. import org.redisson.api.RMap;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. public class DemoController {
  8.     private final RedissonClient redissonClient;
  9.     @Autowired
  10.     public DemoController(RedissonClient redissonClient) {
  11.         this.redissonClient = redissonClient;
  12.     }
  13.     @GetMapping("/test")
  14.     public void test() {
  15.         RMap<String, Article> rMap = redissonClient.getMap("test");
  16.         rMap.put("k1", Article.builder().title("demo").content("test redisson").build());
  17.     }
  18. }
复制代码
数据如下:

3.3 List

3.3.1 无序

通过 RList 对象来操作列表数据结构,简单示比方下:
  1. import org.redisson.api.RList;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. public class DemoController {
  8.     private final RedissonClient redissonClient;
  9.     @Autowired
  10.     public DemoController(RedissonClient redissonClient) {
  11.         this.redissonClient = redissonClient;
  12.     }
  13.     @GetMapping("/test")
  14.     public void test() {
  15.         RList<Article> rList = redissonClient.getList("test");
  16.         rList.add(Article.builder().title("demo").content("test redisson").build());
  17.         rList.add(Article.builder().title("demo").content("test redisson").build());
  18.     }
  19. }
复制代码
数据如下:

3.3.2 有序

通过 RSortedSet 对象来操作有序集合数据结构
改造一下实体类,实现 Comparable 接口
  1. import lombok.Data;
  2. import java.io.Serial;
  3. import java.io.Serializable;
  4. @Data
  5. public class Article implements Serializable, Comparable<Article> {
  6.     @Serial
  7.     private static final long serialVersionUID = -8862397425409851538L;
  8.     private Long id;
  9.     private String title;
  10.     private String content;
  11.     @Override
  12.     public int compareTo(Article article) {
  13.         return this.getId().compareTo(article.getId());
  14.     }
  15. }
复制代码
简单示比方下:
  1. import org.redisson.api.RSortedSet;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. public class DemoController {
  8.     private final RedissonClient redissonClient;
  9.     @Autowired
  10.     public DemoController(RedissonClient redissonClient) {
  11.         this.redissonClient = redissonClient;
  12.     }
  13.     @GetMapping("/test")
  14.     public void test() {
  15.         RSortedSet<Article> rSortedSet = redissonClient.getSortedSet("test");
  16.         Article article1 = new Article();
  17.         article1.setId(22L);
  18.         article1.setTitle("demo");
  19.         article1.setContent("test redisson");
  20.         rSortedSet.add(article1);
  21.         Article article2 = new Article();
  22.         article2.setId(11L);
  23.         article2.setTitle("demo");
  24.         article2.setContent("test redisson");
  25.         rSortedSet.add(article2);
  26.     }
  27. }
复制代码
数据如下,可以看到数据根据 id 排序

3.4 Set

通过 RSet 对象来操作集合数据结构,简单示比方下:
  1. import org.redisson.api.RSet;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. public class DemoController {
  8.     private final RedissonClient redissonClient;
  9.     @Autowired
  10.     public DemoController(RedissonClient redissonClient) {
  11.         this.redissonClient = redissonClient;
  12.     }
  13.     @GetMapping("/test")
  14.     public void test() {
  15.         RSet<Article> rSet = redissonClient.getSet("test");
  16.         rSet.add(Article.builder().title("demo").content("test redisson").build());
  17.         rSet.add(Article.builder().title("demo").content("test redisson").build());
  18.     }
  19. }
复制代码
数据如下,可以看到重复数据被去除了

3.5 Zset

通过 RScoredSortedSet 来操作带分数的有序集合数据结构,简单示比方下:
  1. import org.redisson.api.*;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. @RestController
  6. public class DemoController {
  7.     private final RedissonClient redissonClient;
  8.     @Autowired
  9.     public DemoController(RedissonClient redissonClient) {
  10.         this.redissonClient = redissonClient;
  11.     }
  12.     @GetMapping("/test")
  13.     public void test() {
  14.         RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet("test");
  15.         rScoredSortedSet.add(600.1, "test1");
  16.         rScoredSortedSet.add(500.3, "test2");
  17.         rScoredSortedSet.add(900.3, "test3");
  18.         rScoredSortedSet.add(200.9, "test1");
  19.     }
  20. }
复制代码
数据如下,可以看到根据分数来排序,并且重复数据被排除了

4. 布隆过滤器

可以用于检索一个元素是否在一个集合中
  1. import org.redisson.api.RBloomFilter;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. import java.time.Duration;
  7. @RestController
  8. public class DemoController {
  9.     private final RedissonClient redissonClient;
  10.     @Autowired
  11.     public DemoController(RedissonClient redissonClient) {
  12.         this.redissonClient = redissonClient;
  13.     }
  14.     @GetMapping("/test")
  15.     public void test() {
  16.         RBloomFilter<String> rBloomFilter = redissonClient.getBloomFilter("test");
  17.         // 初始化预期插入的数据量为10000和期望误差率为0.01
  18.         rBloomFilter.tryInit(10000, 0.01);
  19.         // 插入部分数据
  20.         rBloomFilter.add("100");
  21.         rBloomFilter.add("200");
  22.         rBloomFilter.add("300");
  23.         // 设置过期时间
  24.         rBloomFilter.expire(Duration.ofSeconds(30));
  25.         // 判断是否存在
  26.         System.out.println(rBloomFilter.contains("300")); // true
  27.         System.out.println(rBloomFilter.contains("200")); // true
  28.         System.out.println(rBloomFilter.contains("999")); // false
  29.     }
  30. }
复制代码
5. 分布式自增 ID

参考代码如下:
  1. import org.redisson.api.RAtomicLong;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. public class DemoController {
  8.     private final RedissonClient redissonClient;
  9.     @Autowired
  10.     public DemoController(RedissonClient redissonClient) {
  11.         this.redissonClient = redissonClient;
  12.     }
  13.     @GetMapping("/test")
  14.     public void test() {
  15.         RAtomicLong rAtomicLong = redissonClient.getAtomicLong("test");
  16.         System.out.println(rAtomicLong.incrementAndGet());
  17.     }
  18. }
复制代码
6. 分布式锁

6.1 未加锁情况

模仿一个库存扣减操作
  1. import org.redisson.api.RBucket;
  2. import org.redisson.api.RedissonClient;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. public class DemoController {
  8.     private final RedissonClient redissonClient;
  9.     @Autowired
  10.     public DemoController(RedissonClient redissonClient) {
  11.         this.redissonClient = redissonClient;
  12.     }
  13.     @GetMapping("/test")
  14.     public void test() {
  15.         RBucket<Integer> bucket = redissonClient.getBucket("num");
  16.         Integer num = bucket.get();
  17.         if (num > 0) {
  18.             System.out.println("扣减库存, 当前库存: " + --num);
  19.             bucket.set(num);
  20.         } else {
  21.             System.out.println("库存不足");
  22.         }
  23.     }
  24. }
复制代码
使用 Jemter 模仿并发场景


点击运行后可以看到明显出现了并发问题

6.2 加锁情况

修改下库存扣减代码
  1. import org.redisson.api.RBucket;
  2. import org.redisson.api.RLock;
  3. import org.redisson.api.RedissonClient;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. @RestController
  8. public class DemoController {
  9.     private final RedissonClient redissonClient;
  10.     @Autowired
  11.     public DemoController(RedissonClient redissonClient) {
  12.         this.redissonClient = redissonClient;
  13.     }
  14.     @GetMapping("/test")
  15.     public void test() {
  16.         RLock rLock = redissonClient.getLock("test");
  17.         try {
  18.             rLock.lock();
  19.             RBucket<Integer> bucket = redissonClient.getBucket("num");
  20.             Integer num = bucket.get();
  21.             if (num > 0) {
  22.                 System.out.println("扣减库存, 当前库存: " + --num);
  23.                 bucket.set(num);
  24.             } else {
  25.                 System.out.println("库存不足");
  26.             }
  27.         } finally {
  28.             rLock.unlock();
  29.         }
  30.     }
  31. }
复制代码
再次模仿并发请求,可以看到问题已包办理

6.3 加锁操作耗时长

当加锁操作耗时较长时,假如多个请求进来,其他的请求会不停堵塞,可以使用 tryLock 来尝试获取锁,获取不到先返回相应
  1. import org.redisson.api.RBucket;
  2. import org.redisson.api.RLock;
  3. import org.redisson.api.RedissonClient;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. @RestController
  8. public class DemoController {
  9.     private final RedissonClient redissonClient;
  10.     @Autowired
  11.     public DemoController(RedissonClient redissonClient) {
  12.         this.redissonClient = redissonClient;
  13.     }
  14.     @GetMapping("/test")
  15.     public void test() {
  16.         RLock rLock = redissonClient.getLock("test");
  17.         try {
  18.             if (rLock.tryLock()) {
  19.                 RBucket<Integer> bucket = redissonClient.getBucket("num");
  20.                 Integer num = bucket.get();
  21.                 Thread.sleep(5000);
  22.                 if (num > 0) {
  23.                     System.out.println("扣减库存, 当前库存: " + --num);
  24.                     bucket.set(num);
  25.                 } else {
  26.                     System.out.println("库存不足");
  27.                 }
  28.             } else {
  29.                 System.out.println("请稍后再试");
  30.             }
  31.         } catch (InterruptedException e) {
  32.             System.out.println(e.getMessage());
  33.             Thread.currentThread().interrupt();
  34.         } finally {
  35.             // 是否是锁定状态且是当前执行线程的锁
  36.             if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
  37.                 rLock.unlock();
  38.             }
  39.         }
  40.     }
  41. }
复制代码
模仿并发请求,这里将时间设置长一点,可以看到获取到锁的请求则去举行库存扣减,获取不到先返回相应


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4