redis redisson 集合的使用案例(RList、Rset、RMap)
作者:o_瓜田李下_o 发布时间:2023-11-13 13:50:21
redis redisson 集合操作
相关类及接口
Rlist:链表
public interface RList<V> extends List<V>, RExpirable, RListAsync<V>, RSortable<List<V>>, RandomAccess {
List<V> get(int... var1); //获取指定的节点值
int addAfter(V var1, V var2); //在var1前添加var2
int addBefore(V var1, V var2); //在var1后添加var2
void fastSet(int var1, V var2); //修改var1处的只为var2
List<V> readAll(); //获取链表的所有值
RList<V> subList(int var1, int var2); //获取var1到var2的子链表
List<V> range(int var1); //返回var1往后的链表
List<V> range(int var1, int var2); //返回var1到var2的链表
void trim(int var1, int var2); //保留var1到var2处的链表,其余删除
void fastRemove(int var1); //删除var1处的值
boolean remove(Object var1, int var2); //判断元素是否删除
<KOut, VOut> RCollectionMapReduce<V, KOut, VOut> mapReduce(); //mapreduce操作
}
RSet:无序集合
public interface RSet<V> extends Set<V>, RExpirable, RSetAsync<V>, RSortable<Set<V>> {
V removeRandom();
Set<V> removeRandom(int var1); //删除对象
V random();
Set<V> random(int var1); //随机返回对象
boolean move(String var1, V var2); //判断集合var1中是否存在var2,类似contains()方法
Set<V> readAll(); //获取所有对象
int union(String... var1); //集合并集对象个数
Set<V> readUnion(String... var1); //集合并集
int diff(String... var1); //集合差集对象个数
Set<V> readDiff(String... var1); //集合差集
int intersection(String... var1); //集合交集的对象个数
Set<V> readIntersection(String... var1); //集合交集
Iterator<V> iterator(int var1);
Iterator<V> iterator(String var1, int var2);
Iterator<V> iterator(String var1); //遍历集合
<KOut, VOut> RCollectionMapReduce<V, KOut, VOut> mapReduce();
RSemaphore getSemaphore(V var1);
RCountDownLatch getCountDownLatch(V var1);
RPermitExpirableSemaphore getPermitExpirableSemaphore(V var1); //信号量
RLock getLock(V var1);
RLock getFairLock(V var1);
RReadWriteLock getReadWriteLock(V var1); //锁操作
Stream<V> stream(int var1);
Stream<V> stream(String var1, int var2);
Stream<V> stream(String var1); //流操作
}
RMap:键值对
public interface RMap<K, V> extends ConcurrentMap<K, V>, RExpirable, RMapAsync<K, V> {
void loadAll(boolean var1, int var2);
void loadAll(Set<? extends K> var1, boolean var2, int var3);
V get(Object var1); //获取var1的值
V put(K var1, V var2); //添加对象
V putIfAbsent(K var1, V var2); //对象不存在则设置
V replace(K var1, V var2); //替换对象
boolean replace(K var1, V var2, V var3); //替换对象
V remove(Object var1); //移除对象
boolean remove(Object var1, Object var2); //移除对象
void putAll(Map<? extends K, ? extends V> var1);
void putAll(Map<? extends K, ? extends V> var1, int var2); //添加对象
Map<K, V> getAll(Set<K> var1); //获取key在集合var1中的键值对
int valueSize(K var1); //key为var1的value大小
V addAndGet(K var1, Number var2); //key为var1的value加var2
long fastRemove(K... var1); //移除对象
boolean fastPut(K var1, V var2); //添加对象
boolean fastReplace(K var1, V var2); //替换key为var1的值为var2
boolean fastPutIfAbsent(K var1, V var2); //如果不存在则设置
Set<K> readAllKeySet(); //获取所有key,以set形式返回
Collection<V> readAllValues(); //获取所有value,以collection返回
Set<Entry<K, V>> readAllEntrySet(); //遍历键值对
Map<K, V> readAllMap(); //集合形式转换为map类型
Set<K> keySet();
Set<K> keySet(int var1);
Set<K> keySet(String var1, int var2);
Set<K> keySet(String var1); //获取key集合
Collection<V> values();
Collection<V> values(String var1);
Collection<V> values(String var1, int var2);
Collection<V> values(int var1); //获取所有value
Set<Entry<K, V>> entrySet();
Set<Entry<K, V>> entrySet(String var1);
Set<Entry<K, V>> entrySet(String var1, int var2);
Set<Entry<K, V>> entrySet(int var1); //遍历键值对
<KOut, VOut> RMapReduce<K, V, KOut, VOut> mapReduce();
RSemaphore getSemaphore(K var1);
RCountDownLatch getCountDownLatch(K var1);
RPermitExpirableSemaphore getPermitExpirableSemaphore(K var1); //信号量操作
RLock getLock(K var1);
RLock getFairLock(K var1);
RReadWriteLock getReadWriteLock(K var1); //锁操作
}
使用示例
public class MyTest {
public static void main(String[] args){
Config config=new Config();
config.useSingleServer().setAddress("redis://******:6379").setPassword("123456");
RedissonClient client= Redisson.create(config);
RList<String> list=client.getList("list");
for (int i=0;i<10;i++){
list.add("瓜田李下 "+i);
}
list.readAll().forEach(System.out::println);
System.out.println("list的数量为:"+list.size()+"\n");
RSet<String> set=client.getSet("set");
for (int i=0;i<10;i++){
set.add("瓜田李下 "+i);
}
for (String s : set) {
System.out.println(s);
}
System.out.println("set的大小为:"+set.size()+"\n");
RMap<Integer,String> map=client.getMap("map");
for (int i=0;i<10;i++){
map.put(i,"瓜田李下 "+i);
}
for (Map.Entry<Integer,String> entry:map.entrySet()){
System.out.println(entry.getKey()+" ==> "+entry.getValue());
}
System.out.println("map的大小为:"+map.size());
}
}
控制台输出
瓜田李下 0
瓜田李下 1
瓜田李下 2
瓜田李下 3
瓜田李下 4
瓜田李下 5
瓜田李下 6
瓜田李下 7
瓜田李下 8
瓜田李下 9
list的数量为:10
瓜田李下 0
瓜田李下 1
瓜田李下 7
瓜田李下 3
瓜田李下 5
瓜田李下 4
瓜田李下 9
瓜田李下 8
瓜田李下 6
瓜田李下 2
set的大小为:10
0 ==> 瓜田李下 0
1 ==> 瓜田李下 1
2 ==> 瓜田李下 2
3 ==> 瓜田李下 3
4 ==> 瓜田李下 4
5 ==> 瓜田李下 5
6 ==> 瓜田李下 6
7 ==> 瓜田李下 7
8 ==> 瓜田李下 8
9 ==> 瓜田李下 9
map的大小为:10
Redisson使用注意事项
Redisson 是一个在 Redis 的基础上实现的 Java 驻内存数据网格,相较于暴露底层操作的Jedis,Redisson提供了一系列的分布式的 Java 常用对象,还提供了许多分布式服务。
特性 & 功能:
支持 Redis 单节点(single)模式、哨兵(sentinel)模式、主从(Master/Slave)模式以及集群(Redis Cluster)模式
程序接口调用方式采用异步执行和异步流执行两种方式
数据序列化,Redisson 的对象编码类是用于将对象进行序列化和反序列化,以实现对该对象在 Redis 里的读取和存储
单个集合数据分片,在集群模式下,Redisson 为单个 Redis 集合类型提供了自动分片的功能
提供多种分布式对象,如:Object Bucket,Bitset,AtomicLong,Bloom Filter 和 HyperLogLog 等
提供丰富的分布式集合,如:Map,Multimap,Set,SortedSet,List,Deque,Queue 等
分布式锁和同步器的实现,可重入锁(Reentrant Lock),公平锁(Fair Lock),联锁(MultiLock),红锁(Red Lock),信号量(Semaphonre),可过期性信号锁(PermitExpirableSemaphore)等
提供先进的分布式服务,如分布式远程服务(Remote Service),分布式实时对象(Live Object)服务,分布式执行服务(Executor Service),分布式调度任务服务(Schedule Service)和分布式映射归纳服务(MapReduce)
更多特性和功能,请关注官网:http://redisson.org
实现原理
redis本身是不支持上述的分布式对象和集合,Redisson是通过利用redis的特性在客户端实现了高级数据结构和特性,例如优先队列的实现,是通过客户端排序整理后再存入redis。
客户端实现,意味着当没有任何客户端在线时,这些所有的数据结构和特性都不会保留,也不会自动生效,例如过期事件的触发或原来优先队列的元素增加。
注意事项
实时性
RMap中有一个功能是可以设置键值对的过期时间的,并可以注册键值对的事件 *
元素淘汰功能(Eviction)
Redisson的分布式的RMapCache Java对象在基于RMap的前提下实现了针对单个元素的淘汰机制。同时仍然保留了元素的插入顺序。由于RMapCache是基于RMap实现的,使它同时继承了java.util.concurrent.ConcurrentMap接口和java.util.Map接口。Redisson提供的Spring Cache整合以及JCache正是基于这样的功能来实现的。
目前的Redis自身并不支持散列(Hash)当中的元素淘汰,因此所有过期元素都是通过org.redisson.EvictionScheduler实例来实现定期清理的。为了保证资源的有效利用,每次运行最多清理300个过期元素。任务的启动时间将根据上次实际清理数量自动调整,间隔时间趋于1秒到1小时之间。比如该次清理时删除了300条元素,那么下次执行清理的时间将在1秒以后(最小间隔时间)。一旦该次清理数量少于上次清理数量,时间间隔将增加1.5倍。
正如官方wiki所述,这个功能是通过后台线程定时去清理的, 所以这个是非实时的(issue-1234:on expired event is not executed in real-time.),延迟在5秒到2小时之间,因此对实时性要求比较高的场景就得自己衡量了。
由于过期时间的非实时性,所以导致过期事件的发生也是非实时的,相应的 * 可能会延迟了一会儿才收到通知,在我的测试中,ttl设置在秒级误差是比较大的,分钟级别的ttl倒还好(左侧设置值,右侧实际耗时):
1s _ 5s
3s _ 5s
4s _ 5s
5s _ 9s
6s _ 10s
10s _ 15s
1m _ 1m11s
序列化
由Redisson默认的编码器为JsonJacksonCodec,JsonJackson在序列化有双向引用的对象时,会出现无限循环异常。而fastjson在检查出双向引用后会自动用引用符$ref替换,终止循环。
在我的情况中,我序列化了一个service,这个service已被spring托管,而且和另一个service之间也相互注入了,用fastjson能 正常序列化到redis,而JsonJackson则抛出无限循环异常。
为了序列化后的内容可见,所以不用redission其他自带的二进制编码器,自行实现编码器:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import org.redisson.client.codec.BaseCodec;
import org.redisson.client.protocol.Decoder;
import org.redisson.client.protocol.Encoder;
import java.io.IOException;
public class FastjsonCodec extends BaseCodec {
private final Encoder encoder = in -> {
ByteBuf out = ByteBufAllocator.DEFAULT.buffer();
try {
ByteBufOutputStream os = new ByteBufOutputStream(out);
JSON.writeJSONString(os, in,SerializerFeature.WriteClassName);
return os.buffer();
} catch (IOException e) {
out.release();
throw e;
} catch (Exception e) {
out.release();
throw new IOException(e);
}
};
private final Decoder<Object> decoder = (buf, state) ->
JSON.parseObject(new ByteBufInputStream(buf), Object.class);
@Override
public Decoder<Object> getValueDecoder() {
return decoder;
}
@Override
public Encoder getValueEncoder() {
return encoder;
}
}
订阅发布
Redisson对订阅发布的封装是RTopic,这也是Redisson中很多事件监听的实现原理(例如键值对的事件监听)。
使用单元测试时发现,在事件发布后,订阅方需要延时一下才能收到事件。具体原因待查
来源:https://blog.csdn.net/weixin_43931625/article/details/103221622
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- 一、前言(吐槽+煽情+简介) &n
- 您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序、电影应用程序和体育相关的应用程序。您是否想知道如何将视频内容添加到您的
- 接收JSON浏览器传来的参数,可以是 key/value 形式的,也可以是一个 JSON 字符串。在 Jsp/Servlet 中,我们接收
- 在基于Mybatis-plus实现多租户架构中,介绍了在多租户项目中如果要开启一个子线程,那么需要手动进行RequestAttributes
- 在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java
- 前言最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Sc
- 首先引入pom <!--SpringBoot 2.1.0--> <parent>  
- reduce()简介Reduce 原意:减少,缩小根据指定的计算模型将Stream中的值计算得到一个最终结果解释:reduce 操
- mybatis-plus自动配置mapper.xml与java接口映射本来没有mybatis-plus的话,这个工作是通过mybatis-s
- WPF实现一个简单的多运算符表达式计算器,供大家参考,具体内容如下1.先看下效果图首先外围给了一个grid 把他分成了两行 第一行用来显示文
- Zookeeper和Eureka哪个更好?1、CAP理论一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求C:数据一致性
- 机器学习 机器学习的目的是把数据转换成信息。 机器学习通过从数据里提取规则或模式来把数据转成信息。 人脸识别 人脸识别通过级联分类器对特征的
- 一、Flutter代码的启动起点我们在多数的业务场景下,使用的都是FlutterActivity、FlutterFragment。在在背后,
- 1:@Qualifier@Qualifier 注释指定注入 Bean 的名称,这样歧义就消除了。所以@Auto
- 其他的不多说了!我们来看看效果吧 一、实现方式一:直接引入compile方式A
- /** * 三角数字: * 比达哥斯拉领导下的古希腊数学家发现了一个有趣的数字序列1, 3, 6, 10, 15, 21,... *
- 本文实例为大家分享了Android自定义View之组合控件,仿电商app顶部栏的相关代码,供大家参考,具体内容如下效果图:分析:左右两边可以
- 1.try-catch异常处理说明Java提供try和catch块来处理异常,try块用于包含可能出错的代码。catch块用于处理try块中
- 咱们废话不多说进入主题、系统主页展示:用户登录后进行系统首页:主要功能模块如下、分角色管理、超级管理员拥有最高权限、可以进行菜单灵活控制、用
- 背景实际开发中,常常需要将比较复杂的 JSON 字符串转换为对应的 Java 对象。这里记录下解决方案。如下所示,是入侵事件检测得到的 JS