聊一聊Redis官方置顶推荐的Java客户端Redisson
写这篇的时候,相信有很多朋友还在用Jedis作为Redis的客户端,我不禁有很多问号,Jedis还香吗?如果你早些年说它香我信,但是都2020年了,它真的不那么香了。那为什么还继续使用它呢?大部分原因或多或少是因为一遗留代码没人敢大动,就这样吧;二新项目没人主导使用其它实现做替换。祖传代码不轻易大动,这个真理必须相信,且坚持相信;至于没人主导拍板做技术替换,可能是习惯了Jedis的用法,也可能是没人了解其它技术实现,当然还有其它原因,有兴趣分享的朋友可以在评论区聊一聊。咳咳,扯远了,来聊我们今天的话题-Redisson实战用法。
在Redis的官网([ Redis ]( Redis ))上可以看到Java语言的推荐客户端列表,除了我们都熟知的Jedis之外,Redisson也是官方推荐的客户端。从这我们了解到Redisson是一个Redis客户端,那它到底Redisson是什么呢?Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid),它充分利用了Redis键值数据库提供的一系列优势,基于Java实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类,让使用Redis更加简单、便捷,从而让使用者能够将更多精力集中到业务逻辑处理上。
也就是说Redisson不仅仅是一个Redis客户端,它还实现了很多具有分布式特性的常用工具类,例如分布式锁、布隆过滤器等,更多功能特性和开发文档说明请移步 https:// github.com/redisson/red isson/wiki/%E7%9B%AE%E5%BD%95 。接下来,我们一起聊一下Redisson中如何轻松操作Redis中的字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)和有序集合(sorted sets),以及如何使用Redisson实现的布隆过滤器和分布式锁,最后分析一下Redisson中分布式锁的解决方案。
创建RedissonClient
要使用Redisson,首先要创建RedissonClient对象实例。创建RedissonClient对象实例的方式多钟多样,可以直接通过在代码中设置Redis服务的相关参数创建,也可以通过加载JSON格式或YAML格式配置文件创建,还可以通过在Spring XML文件中使用Redisson标签配置创建,具体如何创建RedissonClient对象实例可根据需要选择,这里就不一一介绍了,有想法的可以移步Redisson官网。本文为了展示使用样例代码,使用了最简单的方式:在代码中设置单机Redis服务的相关参数创建RedissonClient对象实例,具体代码如下。
Config config = new Config();
// 使用单机Redis服务
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
// 创建Redisson客户端
RedissonClient redisson = Redisson.create(config);
字符串(strings)
Redisson将Redis中的字符串数据结构封装成了RBucket,通过RedissonClient的getBucket(key)方法获取一个RBucket对象实例,通过这个实例可以设置value或设置value和有效期,例如如下代码。
RBucket<String> nameRBucket = redisson.getBucket("name");
// 只设置value,key不过期
nameRBucket.set("四哥");
// 设置value和key的有效期
nameRBucket.set("四哥", 30, TimeUnit.SECONDS);
// 通过key获取value
redisson.getBucket("name").get();
有朋友可能发现了,上面的nameRBucket使用了String约定了value类型,也就是说这里的value可以是其它类型,例如value是一个对象,可以这么操作。
Student tom = new Student();
tom.setId(456L);
tom.setChineseName("刘能");
tom.setEnglishName("tom");
tom.setAge(52);
// 通过key获取RBucket对象实例
RBucket<Student> studentRBucket = redisson.getBucket("student");
// 设置value和有效期
studentRBucket.set(tom, 300, TimeUnit.SECONDS);
// 通过key获取value
redisson.getBucket("student").get();
哈希(hashes)
Redisson将Redis中的字符串数据结构封装成了RMap,操作示例代码如下。
// 通过key获取RMap
RMap<String, String> studentRMap = redisson.getMap("studentMap");
// 设置map中key-value
studentRMap.put("id", "123");
studentRMap.put("name", "赵四");
studentRMap.put("age", "50");
// 设置key有效期
studentRMap.expire(300, TimeUnit.SECONDS);
// 通过key获取value
redisson.getMap("studentMap").get("name");
列表(lists)
使用示例代码如下。
RList<Student> studentRList = redisson.getList("studentList");
studentRList.add(jack);
// 设置有效期
studentRList.expire(300, TimeUnit.SECONDS);
// 通过key获取value
redisson.getList("studentList").get(0);
集合(sets)
使用示例代码如下。
RSet<Student> studentRSet = redisson.getSet("studentSet");
studentRSet.add(jack);
studentRSet.add(tom);
// 设置有效期
studentRSet.expire(300, TimeUnit.SECONDS);
// 通过key获取value
redisson.getSet("studentSet");
有序集合(sorted sets)
使用示例代码如下。
RSortedSet<Student> studentSortedSet = redisson.getSortedSet("studentSortedSet");
studentSortedSet.add(jack);
studentSortedSet.add(tom);
// 通过key获取value
redisson.getSortedSet("studentSortedSet");
布隆过滤器
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。更多布隆过滤器的内容,请通过搜索引擎了解更多。
Redisson提供了布隆过滤器的实现,可以直接使用,示例代码如下。
RBloomFilter seqIdBloomFilter = redisson.getBloomFilter("seqId");
// 初始化预期插入的数据量为10000000和期望误差率为0.01
seqIdBloomFilter.tryInit(10000000, 0.01);
// 插入部分数据
seqIdBloomFilter.add("123");
seqIdBloomFilter.add("456");
seqIdBloomFilter.add("789");
// 判断是否存在
System.out.println(seqIdBloomFilter.contains("123"));
System.out.println(seqIdBloomFilter.contains("789"));
System.out.println(seqIdBloomFilter.contains("100"));
分布式锁
Redisson提供了强大的分布式锁实现,使用简单、安全。下面模拟多线程竞争分布式锁,示例代码如下。
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
final String lockKey = "abc";