spring-boot-starter-data-redis
spring-boot-starter-data-redis是Spring对redis一系列操作进行的封装。它简化了很多redis的操作,
让开发的精力更多的投入在业务上面。
依赖的引入
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
参数配置
spring:
application:
name: redis
redis:
database: 0
host: 127.0.0.1
jedis:
pool:
#最大连接数据库连接数,设 0 为没有限制
max-active: 8
#最大等待连接中的数量,设 0 为没有限制
max-idle: 8
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
max-wait: -1ms
#最小等待连接中的数量,设 0 为没有限制
min-idle: 0
lettuce:
pool:
max-active: 8
max-idle: 8
max-wait: -1ms
min-idle: 0
shutdown-timeout: 1000ms
password: 你的密码
port: 6379
server:
port: 8000
redis的操作
spring-boot-starter-data-redis提供了两个操作Redis的工具,StringRedisTemplate
和
RedisTemplate
两者的区别主要有下面
- StringRedisTemplate是RedisTemplate的子类
- 两者使用了不同的序列化类,RedisTemplate使用的是JdkSerializationRedisSerializer,StringRedisTemplate使用的是StringRedisSerializer。
- StringRedisTemplate更加专注于字符串的操作,而RedisTemplate提供了更多的数据类型的操作。
- RedisTemplate将数据保存到Redis中的时候会将值和键都序列化成字节数组进行保存。
RedisTemplate支持的数据类型
因为StringRedisTemplate是继承于RedisTemplate的所以,目前主要介绍StringRedisTemplate
操作字符串
redisTemplate.opsForValue();
操作hash
redisTemplate.opsForHash();
操作list
redisTemplate.opsForList();
操作set
redisTemplate.opsForSet();
操作ZSet(有序set)
redisTemplate.opsForZSet();
操作Geo(地图信息)
redisTemplate.opsForGeo();
操作HyperLogLog(HyperLogLog算法)
redisTemplate.opsForHyperLogLog()
基础操作
公共方法
设置过期时间
redisTemplate提供了expire来设置某个key的过期时间
@Override
public void setExpire(String key, long timeout, TimeUnit unit) {
//设置超时时间10秒 第三个参数控制时间单位,详情查看TimeUnit
redisTemplate.expire(key,timeout,unit);
}
删除某个key的内容
redisTemplate提供了delete来删除某个key
/**
* 删除某个Key
* @param key
* @param timeout
* @param unit
*/
@Override
public void remove(String key, long timeout, TimeUnit unit) {
//设置超时时间10秒 第三个参数控制时间单位,详情查看TimeUnit
redisTemplate.delete(key);
}
对字符串的操作
对字符串的操作应该算是Redis最基础的功能了
设置和取出字符串内容
@Override
public void setData(String key,String value) {
stringRedisTemplate.opsForValue().set(key,value);
}
@Override
public String getData(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
对List的操作
根据源码可以看到从redis中取出的的确是list但是Spring封装了一些模仿Deque的方法,实现了双端操作
/**
* 操作list的操作
* @param key
* @param value
* @param location
*/
@Override
public void setListData(String key,String value,ListLocation location) {
if (ListLocation.LEFT.equals(location)) {
// 也可以这么设置 redisTemplate.boundListOps(key).leftPush(key,value);
redisTemplate.opsForList().leftPush(key,value);
} else {
redisTemplate.opsForList().rightPush(key,value);
}
}
/**
* 获得list的值
* @param key
* @param location
* @return
*/
@Override
public Object getListData(String key,ListLocation location) {
if (ListLocation.LEFT.equals(location)) {
return redisTemplate.opsForList().leftPop(key);
} else {
return redisTemplate.opsForList().rightPop(key);
}
}
使用Pop方法会取出对应位置的值并且移除它们。使用下面的测试可以很明确的发现这点。
@Test
public void setListData() {
String key = "a";
redisService.removeListData(key);
String value = "A";
redisService.setListData(key,value,ListLocation.LEFT);
String value1 = "B";
redisService.setListData(key,value1,ListLocation.LEFT);
Object listData = redisService.getListData(key, ListLocation.LEFT);
Assert.assertEquals("B",listData);
Object listData2 = redisService.getListData(key, ListLocation.LEFT);
Assert.assertEquals("A",listData2);
}
对Hash的操作
对hash的操作基本上和我们正常操作map类似
/**
* 针对map类型的数据操作-设置hash的值
* @param key
* @param hashKey
* @param value
*/
@Override
public void setHashData(String key,String hashKey,String value) {
redisTemplate.opsForHash().put(key,hashKey,value);
}
/**
* 针对map类型的数据操作-设置hash的值
* @param key
* @param map
*/
@Override
public void setHashData(String key, Map map) {
redisTemplate.opsForHash().putAll(key,map);
}
对Set的操作
redisTemplate提供了随机取得一个或者指定数据元素的方法,并且在取出这些元素后会被移除掉
/**
* set类型数据操作-设置set的值
* @param key
* @param value
*/
@Override
public void setSetData(String key,String value){
redisTemplate.opsForSet().add(key,value);
}
/**
* set类型数据操作-获得set的值
* @param key
* @return
*/
@Override
public Object getSetData(String key){
// 随机返回并移除key对应set中某一个成员
Object pop = redisTemplate.opsForSet().pop(key);
// 随机返回并移除key对应set中某count个成员
// pop(K key, long count)
return pop;
}
对ZSet(有序Set)的操作
ZSet是一种有序的Set,在保存数据的时候我们需要设置(double score),标识此内容的一个排序分值
然后我们使用分值范围的查询可以筛选出指定范围的内容。
@Override
public void setZsetData(String key,String value,Double source){
redisTemplate.opsForZSet().add(key,value,source);
}
/**
* zset类型数据操作-获得ZSet中的值
* @param key
* @param source1
* @param source2
* @return
*/
@Override
public Set getZsetData(String key,Double source1,Double source2){
Set set = redisTemplate.opsForZSet().rangeByScore(key, source1, source2);
return set;
}
下面的测试内容中,我们分别设置了1-7的分值,然后我们查询3-6之间的数据,最后可以拿到
C、D、E、F四个内容,而且返回的数据应该是有序的。
@Test
public void setZsetData() {
redisService.setZsetData("dai","B",2D);
redisService.setZsetData("dai","A",1D);
redisService.setZsetData("dai","D",4D);
redisService.setZsetData("dai","C",3D);
redisService.setZsetData("dai","F",6D);
redisService.setZsetData("dai","E",5D);
redisService.setZsetData("dai","G",7D);
Set dai = redisService.getZsetData("dai", 3D, 6D);
Assert.assertTrue(dai.size() == 4);
Object[] objects = dai.toArray();
Assert.assertTrue("C".equals(objects[0]));
Assert.assertTrue("D".equals(objects[1]));
Assert.assertTrue("E".equals(objects[2]));
Assert.assertTrue("F".equals(objects[3]));
}
对Geo(地图信息)的操作
Redis在 3.2 版本提供了对Geo的支持,我们现在可以将地图信息保存到Redis中,后续可以通过范围获得符合的内容,也可以来计算距离
/**
* 设置Geo的值
* @param key
* @param location
*/
@Override
public void setGeoData(String key, RedisGeoCommands.GeoLocation <Object> location){
redisTemplate.opsForGeo().add(key,location);
}
/**
* 获得Geo的值
* @param key
* @param circle
* @return
*/
@Override
public GeoResults getGeoData(String key, Circle circle){
GeoResults radius = redisTemplate.opsForGeo().radius(key, circle);
return radius;
}
下面的测试内容中,我们分别设置了两个相近的坐标,然后查询500范围内只能获得一个坐标,
将范围扩大到5000便可以获得所有的坐标。
@Test
public void setGeoData() {
String key = "A";
Point point = new Point(114.403629,30.475316);
RedisGeoCommands.GeoLocation <Object> location =
new RedisGeoCommands.GeoLocation <>("软件园",point);
Point point2 = new Point(114.386119,30.473688);
RedisGeoCommands.GeoLocation <Object> location2 =
new RedisGeoCommands.GeoLocation <>("财经政法",point2);
// 保存坐标
redisService.setGeoData(key,location);
redisService.setGeoData(key,location2);
redisService.setExpire(key,5000L, TimeUnit.MILLISECONDS);
// 查询指定坐标,距离500米,此时应该只有一个坐标
Circle circle = new Circle(114.403629,30.475316,500);
GeoResults geoData = redisService.getGeoData(key, circle);
List content = geoData.getContent();
Assert.assertTrue(content.size() == 1);
// 查询指定坐标,距离5000米,此时应该只有两个坐标
Circle circle2 = new Circle(114.403629,30.475316,5000);
GeoResults geoData2 = redisService.getGeoData(key, circle2);
List content2 = geoData2.getContent();
Assert.assertTrue(content2.size() == 2);
}
HyperLogLog算法
HyperLogLog的主要作用是用来做基数统计。基数统计:一个集合中不重复元素的个数。例如集合 {“A”,“B”,“C”,“D”,“E”,“B”,“D”},它有7个元素,但它的基数为5。
/**
* 设置HyperLogLog的值
* @param key
* @param objs
*/
@Override
public void setHyperLogLogData(String key,Object... objs){
redisTemplate.opsForHyperLogLog().add(key,objs);
}
/**
* 获得HyperLogLog的值
* @param key
* @return
*/
@Override
public Long getHyperLogLogData(String key){
return redisTemplate.opsForHyperLogLog().size(key);
}
在下面的测试内容中,我们添加了values中的七个元素,但是实际中基数统计并不是7而是5
@Test
public void setHyperLogLogData() {
String key = "loglog";
// 在HyperLogLog中实际插入的内容为A-E
String[] values = new String[] {"A","B","C","D","E","B","D"};
redisService.setHyperLogLogData(key,values);
redisService.setExpire(key,3000L, TimeUnit.MILLISECONDS);
Long hyperLogLogData = redisService.getHyperLogLogData(key);
Assert.assertTrue(hyperLogLogData == 5);
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
Long hyperLogLogData2 = redisService.getHyperLogLogData(key);
Assert.assertTrue(hyperLogLogData2 == 0);
}
本篇文章涉及的源码下载地址:https://gitee.com/daifyutils/springboot-samples
附录,RedisTemplate文档
RedisTemplate API 地址:https://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/RedisTemplate.html
RedisTemplate
方法 | 描述 |
---|---|
bound***Ops | 返回绑定到给定键的特定于(字符串、list、map、set、zset、坐标)的操作接口 |
convertAndSend | 将消息发送至指定通道中 |
countExistingKeys | 计算存在的键的数量 |
delete | 移除键 |
discard | 丢弃RedisOperations.multi()之后的操作 |
dump | 执行Redis dump并发挥结果 |
exec | 执行事务,使用默认的redisserializer反序列化字节[]或字节[]元组的集合或映射的任何结果。 |
execute(RedisCallback action) | 基于Redis连接执行操作 |
executePipelined | 在管道连接上执行给定的操作对象,返回结果。 |
executeWithStickyConnection | 分配并绑定一个新的RedisConnection |
expire | 设置键的超时时间 |
expireAt | 设置键的超时时间,使用timestamp |
getClientList | 请求有关已连接客户端的信息和统计信息 |
getDefaultSerializer | 返回默认序列化器 |
getExpire(K key) | 获得指定键的超时时间 |
get***KeySerializer() | 返回指定类别(字符串、list、map、set、zset、坐标)使用的序列化器 |
hasKey | 判断键是否存在 |
isExposeConnection | 返回是否公开连接代理(默认值) |
keys | 根据匹配模式获得给定的键 |
killClient | 关闭指定连接 |
move | 将指定键移动到指定索引的数据源 |
multi | 标记事务 |
opsFor*** | 返回(字符串、list、map、set、zset、坐标,集群)操作接口 |
persist | 移除过期key |
randomKey | 获得一个随机key |
rename | 给key进行重命名 |
renameIfAbsent | 当新的名称不存在时候进行重命名 |
restore | 还原操作 |
setBeanClassLoader | 设置类加载器 |
setDefaultSerializer | 设置默认序列化器 |
setExposeConnection | 设置是否将Redis连接公开到RedisCallback代码 |
set***Serializer | 设置指定类别(字符串、list、map、set、zset、坐标)使用的序列化器 |
slaveOf | 将redis复制设置更改为new master |
slaveOfNoOne | 切换服务器为master |
sort | 为指定结果排序 |
type | 返回键的类别 |
unlink | 断开键连接 |
unwatch | 刷新监控 |
watch | 在事务开始时使用RedisOperations.multi()监视给定的修改键 |
ValueOperations-操作字符串
方法 | 描述 |
---|---|
append | 向指定key中添加内容 |
bitField | 获得集合中复合 BitFieldSubCommands的结果 |
decrement | 将键中保存的整数减去指定值 |
get | 获得值 |
getAndSet | 设置参数并返回旧值 |
increment | 将键中保存的整数加去指定值 |
multiGet | 批量获得值 |
multiSet | 批量增加值 |
multiSetIfAbsent | 键不存在的时候设置值 |
set | 设置参数 |
setBit | 设置按键存储的值的偏移量 |
setIfAbsent | 如果key不存在则保存 |
setIfPresent | 如果key存在则保存 |
size | 获得指定结果的长度 |
HashOperations-操作hash
方法 | 描述 |
---|---|
delete | 删除map中指定值 |
entries | 获得map的entries |
get | 获取map中的指定值 |
hasKey | 判断指定hasKey是否存在 |
increment | 给map中指定值增加值 |
keys | 返回map中key的集合 |
lengthOfValue | 返回map中指定值的长度 |
multiGet | 批量获得结果 |
put | 添加元素 |
putAll | 批量添加 |
putIfAbsent | 假如存在则添加 |
scan | 遍历集合 |
size | 获得指定键成员数量 |
values | 获得键结果的value集合 |
ListOperations-操作list
方法 | 描述 |
---|---|
index | 获得list指定元素的索引 |
leftPop | 删除并返回存储在键上的列表中的第一个元素 |
leftPush | 添加元素 |
leftPushAll | 批量添加元素 |
leftPushIfPresent | list存在则添加元素 |
range | 获得list中指定范围内容的元素 |
remove | 移除list指定的元素 |
rightPop | 删除并返回存储在键上的列表中的最后一个元素 |
rightPopAndLeftPush | 移除指定键最后一个元素,并添加至另外一个键的头部 |
rightPush | 添加元素 |
rightPushAll | 批量添加元素 |
rightPushIfPresent | list存在则添加元素 |
set | 在指定索引添加元素 |
size | 元素的总数量 |
trim | 剔除指定范围内的不合规元素 |
SetOperations-操作set
方法 | 描述 |
---|---|
add | 添加元素 |
difference | 获得两个键之间不同的内容 |
differenceAndStore | 获得集合中不同的内容,并且保存在新的键中 |
distinctRandomMembers | 从set中随机获取一定数量的结果 |
intersect | 合并键的元素 |
intersectAndStore | 合并键的元素并保存至指定键内 |
isMember | 判断指定键是否包含指定元素 |
members | 获取所有的元素 |
move | 将指定值从键1转移至键2 |
pop | 删除并返回一个随机元素 |
randomMember | 获取随机元素 |
randomMembers | 获取指定数量的随机元素 |
remove | 移除指定元素 |
scan | 遍历集合 |
size | 获得集合中元素数量 |
union | 合并两个集合 |
unionAndStore | 合并两个集合并保存在新的键中 |
ZSetOperations-操作ZSet(有序set)
方法 | 描述 |
---|---|
add | 添加或者更新元素 |
count | 指定范围内结果数量 |
incrementScore | 增加指定值的分数 |
intersectAndStore | 两个键联合排序,并保存在第三个键内 |
range | 获取指定范围的元素 |
rangeByLex | 获取指定范围的元素,条件为RedisZSetCommands.Range.getMin() and RedisZSetCommands.Range.getMax() |
rangeByScore | 获取指定范围的元素,条件为分值 |
rangeByScoreWithScores | 获取指定范围的元素,条件为分值和索引 |
rangeWithScores | 获取指定范围之间的有序集合 |
rank | 获得指定元素的索引 |
remove | 移除指定的元素 |
removeRange | 移除此键对应集合中指定范围的元素 |
removeRangeByScore | 移除此键对应集合中指定分值范围的元素 |
reverseRange | 获取指定范围内的结合,排序从高到底 |
reverseRangeByScore | 获得set的RedisZSetCommands.Tuple从高到低,范围为选择的索引, |
reverseRangeByScoreWithScores | 获得set的RedisZSetCommands.Tuple从高到低,范围为选择的索引,以及选择的分值 |
reverseRank | 当得分从高到低时,确定排序集合中指定元素的索引。 |
scan | 便利ZSet |
score | 获取指定键,指定元素的分值 |
size | 获取指定键中元素的数量 |
unionAndStore | 将选择的两个键进行联合排序,并将结果保存在第三个键中 |
zCard | 获得指定key结果长度. |
GeoOperations-操作Geo(地图信息)
方法 | 描述 |
---|---|
and | 添加坐标到指定键 |
distance | 计算两个坐标之间的距离 |
hash | 获得指定键,与之匹配的结果的Geohash显示 |
position | 获得指定键,与之匹配的结果的Point显示 |
radius | 获得指定坐标一定范围内的结果 |
remove | 移除坐标 |
HyperLogLogOperations-操作HyperLogLog(HyperLogLog算法)
方法 | 描述 |
---|---|
add | 添加值到指定键中 |
delete | 移除指定键 |
size | 获取指定键中元素的数量 |
union | 将指定键的所有值合并到目标键中. |