Redisson 总结
1. 底子使用1.1 引入依赖
<dependencies>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
</dependencies>
包含的依赖如下
https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=http%3A%2F%2Fimg.fan223.cn%2F2024%2F05%2F20240509140934.png&pos_id=img-9QZmbgZT-1726626863452
1.2 配置文件
其实默认主机就是 127.0.0.1,默认端口是 6379,一致的话可以不用配置
spring:
data:
redis:
host: 127.0.0.1
password: redis
1.3 测试类
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RBucket<String> bucket = redissonClient.getBucket("test");
bucket.set("hello");
}
@GetMapping("/get")
public String get() {
RBucket<String> bucket = redissonClient.getBucket("test");
return bucket.get();
}
}
1.4 测试
访问 /test 接口,利用 Redis 管理工具可以看到数据已经添加了进来
https://img-blog.csdnimg.cn/img_convert/27c2a0edf30b14c182ff4f8a7cf16adf.png
在访问 /get 接口,乐成获取到数据
https://img-blog.csdnimg.cn/img_convert/6fbd56c28eb0767020b2cab179369c43.png
2. 设置序列化
上面可以看到在 Redis 管理工具中查看数据是一串字符,并不直观,可以自界说数据序列化
2.1 配置类
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
// 单机模式
SingleServerConfig singleServerConfig = config.useSingleServer();
singleServerConfig.setAddress("redis://127.0.0.1:6379");
singleServerConfig.setPassword("redis");
// JSON序列化
config.setCodec(new JsonJacksonCodec());
return Redisson.create(config);
}
}
这里已经配置了主机等相干信息,因此配置文件里的配置可以去除,或者这里直接取配置文件的值,具体根据情况选择,其他的序列化类如下
编码类名称说明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 格式
https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=http%3A%2F%2Fimg.fan223.cn%2F2024%2F05%2F20240509154909.png&pos_id=img-ru9557jX-1726626863453
3. 底子数据结构使用
3.1 String
其实上面的示例用的就是字符串操作,通过 RBucket 对象来操作字符串数据结构
创建一个实体类
import lombok.Builder;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
@Builder
public class Article implements Serializable {
@Serial
private static final long serialVersionUID = -8862397425409851538L;
private String title;
private String content;
}
存储对象,简单示比方下:
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RBucket<Object> bucket = redissonClient.getBucket("test");
bucket.set(Article.builder().title("demo").content("test redisson").build());
}
}
数据如下:
https://img-blog.csdnimg.cn/img_convert/39b72a5cb880f89ff6996652ba4553ae.png
3.2 Hash
通过 RMap 对象来操作哈希数据结构,简单示比方下:
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RMap<String, Article> rMap = redissonClient.getMap("test");
rMap.put("k1", Article.builder().title("demo").content("test redisson").build());
}
}
数据如下:
https://img-blog.csdnimg.cn/img_convert/5e5a9fd5d76068059745c9331632af83.png
3.3 List
3.3.1 无序
通过 RList 对象来操作列表数据结构,简单示比方下:
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RList<Article> rList = redissonClient.getList("test");
rList.add(Article.builder().title("demo").content("test redisson").build());
rList.add(Article.builder().title("demo").content("test redisson").build());
}
}
数据如下:
https://img-blog.csdnimg.cn/img_convert/a3439dc7757972eeb2db9322cf9d53c5.png
3.3.2 有序
通过 RSortedSet 对象来操作有序集合数据结构
改造一下实体类,实现 Comparable 接口
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class Article implements Serializable, Comparable<Article> {
@Serial
private static final long serialVersionUID = -8862397425409851538L;
private Long id;
private String title;
private String content;
@Override
public int compareTo(Article article) {
return this.getId().compareTo(article.getId());
}
}
简单示比方下:
import org.redisson.api.RSortedSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RSortedSet<Article> rSortedSet = redissonClient.getSortedSet("test");
Article article1 = new Article();
article1.setId(22L);
article1.setTitle("demo");
article1.setContent("test redisson");
rSortedSet.add(article1);
Article article2 = new Article();
article2.setId(11L);
article2.setTitle("demo");
article2.setContent("test redisson");
rSortedSet.add(article2);
}
}
数据如下,可以看到数据根据 id 排序
https://img-blog.csdnimg.cn/img_convert/96fdecef25d32b3cef29442819ed0999.png
3.4 Set
通过 RSet 对象来操作集合数据结构,简单示比方下:
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RSet<Article> rSet = redissonClient.getSet("test");
rSet.add(Article.builder().title("demo").content("test redisson").build());
rSet.add(Article.builder().title("demo").content("test redisson").build());
}
}
数据如下,可以看到重复数据被去除了
https://img-blog.csdnimg.cn/img_convert/fe4d0212fd776d6924da95d8019f0ed3.png
3.5 Zset
通过 RScoredSortedSet 来操作带分数的有序集合数据结构,简单示比方下:
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet("test");
rScoredSortedSet.add(600.1, "test1");
rScoredSortedSet.add(500.3, "test2");
rScoredSortedSet.add(900.3, "test3");
rScoredSortedSet.add(200.9, "test1");
}
}
数据如下,可以看到根据分数来排序,并且重复数据被排除了
https://img-blog.csdnimg.cn/img_convert/ce85f24a622461c3b2ab425d6628194b.png
4. 布隆过滤器
可以用于检索一个元素是否在一个集合中
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RBloomFilter<String> rBloomFilter = redissonClient.getBloomFilter("test");
// 初始化预期插入的数据量为10000和期望误差率为0.01
rBloomFilter.tryInit(10000, 0.01);
// 插入部分数据
rBloomFilter.add("100");
rBloomFilter.add("200");
rBloomFilter.add("300");
// 设置过期时间
rBloomFilter.expire(Duration.ofSeconds(30));
// 判断是否存在
System.out.println(rBloomFilter.contains("300")); // true
System.out.println(rBloomFilter.contains("200")); // true
System.out.println(rBloomFilter.contains("999")); // false
}
}
5. 分布式自增 ID
参考代码如下:
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RAtomicLong rAtomicLong = redissonClient.getAtomicLong("test");
System.out.println(rAtomicLong.incrementAndGet());
}
}
6. 分布式锁
6.1 未加锁情况
模仿一个库存扣减操作
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RBucket<Integer> bucket = redissonClient.getBucket("num");
Integer num = bucket.get();
if (num > 0) {
System.out.println("扣减库存, 当前库存: " + --num);
bucket.set(num);
} else {
System.out.println("库存不足");
}
}
}
使用 Jemter 模仿并发场景
https://img-blog.csdnimg.cn/img_convert/14f1ec6114d7c56352df8aafc864b131.png
https://img-blog.csdnimg.cn/img_convert/2005e72dbf338e05ae18e1c118b055c7.png
点击运行后可以看到明显出现了并发问题
https://img-blog.csdnimg.cn/img_convert/e32c2dfb475e2917ddec8d046c6124bd.png
6.2 加锁情况
修改下库存扣减代码
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RLock rLock = redissonClient.getLock("test");
try {
rLock.lock();
RBucket<Integer> bucket = redissonClient.getBucket("num");
Integer num = bucket.get();
if (num > 0) {
System.out.println("扣减库存, 当前库存: " + --num);
bucket.set(num);
} else {
System.out.println("库存不足");
}
} finally {
rLock.unlock();
}
}
}
再次模仿并发请求,可以看到问题已包办理
https://img-blog.csdnimg.cn/img_convert/1ca0efdbe65f7a71f58d85ce87c1b0b9.png
6.3 加锁操作耗时长
当加锁操作耗时较长时,假如多个请求进来,其他的请求会不停堵塞,可以使用 tryLock 来尝试获取锁,获取不到先返回相应
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
private final RedissonClient redissonClient;
@Autowired
public DemoController(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@GetMapping("/test")
public void test() {
RLock rLock = redissonClient.getLock("test");
try {
if (rLock.tryLock()) {
RBucket<Integer> bucket = redissonClient.getBucket("num");
Integer num = bucket.get();
Thread.sleep(5000);
if (num > 0) {
System.out.println("扣减库存, 当前库存: " + --num);
bucket.set(num);
} else {
System.out.println("库存不足");
}
} else {
System.out.println("请稍后再试");
}
} catch (InterruptedException e) {
System.out.println(e.getMessage());
Thread.currentThread().interrupt();
} finally {
// 是否是锁定状态且是当前执行线程的锁
if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
rLock.unlock();
}
}
}
}
模仿并发请求,这里将时间设置长一点,可以看到获取到锁的请求则去举行库存扣减,获取不到先返回相应
https://img-blog.csdnimg.cn/img_convert/89610a2c091483271915eb0a81fd43c2.png
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]