推广 热搜: 公司  快速  中国  上海  未来    企业  政策  教师  系统 

SpringBoot项目实战 - SpringBoot使用RedisTemplate

   日期:2024-11-04     作者:caijiyuan    caijiyuan   评论:0    移动:http://kaire.xrbh.cn/news/9999.html
核心提示:Redis所有的key(键)都是字符串。我们在谈基础数据结构时,讨论的是存储值的数据类型,主要包括常见的

Redis所有的key(键)都是字符串。我们在谈基础数据结构时,讨论的是存储值的数据类型,主要包括常见的5种数据类型,分别是:String、List、Set、Zset、Hash

SpringBoot项目实战 - SpringBoot使用RedisTemplate

Redis基础文章非常多,关于基础数据结构类型,我推荐你先看下官方网站内容 ,然后再看下面的小结

结构类型结构存储的值结构的读写能力String字符串可以是字符串、整数或浮点数对整个字符串或字符串的一部分进行操作;对整数或浮点数进行自增或自减操作;List列表一个链表,链表上的每个节点都包含一个字符串对链表的两端进行push和pop操作,读取单个或多个元素;根据值查找或删除元素;Hash散列包含键值对的无序散列表包含方法有添加、获取、删除单个元素Set集合包含字符串的无序集合字符串的集合,包含基础的方法有看是否存在添加、获取、删除;还包含计算交集、并集、差集等Zset有序集合和散列一样,用于存储键值对字符串成员与浮点数分数之间的有序映射;元素的排列顺序由分数的大小决定;包含方法有添加、获取、删除单个元素以及根据分值范围或成员来获取元素

1、String字符串

String是redis中最基本的数据类型,一个key对应一个value。

命令简述使用RPUSH将给定值推入到列表右端RPUSH key valueLPUSH将给定值推入到列表左端LPUSH key valueRPOP从列表的右端弹出一个值,并返回被弹出的值RPOP keyLPOP从列表的左端弹出一个值,并返回被弹出的值LPOP keyLRANGE获取列表在给定范围上的所有值LRANGE key 0 -1LINDEX通过索引获取列表中的元素。你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。LINEX key index
  • 使用列表的技巧
    lpush+lpop=Stack(栈)
    lpush+rpop=Queue(队列
    lpush+ltrim=Capped Collection(有限集合
    lpush+brpop=Message Queue(消息队列

  • 命令执行

  1. 微博TimeLine: 有人发布微博,用lpush加入时间轴,展示新的列表信息。
  2. 消息队列

3、Hash散列

Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。

命令简述使用HSET添加键值对HSET hash-key sub-key1 value1HGET获取指定散列键的值HGET hash-key key1HGETALL获取散列中包含的所有键值对HGETALL hash-keyHDEL如果给定键存在于散列中,那么就移除这个键HDEL hash-key sub-key1
  1. 缓存: 能直观,相比string更节省空间,的维护缓存信息,如用户信息,视频信息等。

4、Set集合

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

命令简述使用SADD向集合添加一个或多个成员SADD key valueSCARD获取集合的成员数SCARD keySMEMBERS返回集合中的所有成员SMEMBERS key memberSISMEMBER判断 member 元素是否是集合 key 的成员SISMEMBER key member

其它一些集合操作,请参考这里https://www.runoob.com/redis/redis-sets.html

  1. 标签(tag),给用户添加标签,或者用户给消息添加标签,这样有同一标签或者类似标签的可以给推荐关注的事或者关注的人。
  2. 点赞,或点踩,收藏等,可以放到set中实现

5、Zset有序集合

  1. 排行榜:有序集合经典使用场景。例如小说视频等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数,更新时间,字数等打分,做排行。

RedisTemplate 为我们操作 Redis 提供了丰富的 API,可以将他们简单进行下归类。

1、常用数据操作

这一类 API 也是我们最常用的一类。

众所周知,redis 存在 5 种数据类型

字符串类型(string,散列类型(hash,列表类型(list,集合类型(set,有序集合类型(zset

而 redisTemplate 实现了 RedisOperations 接口,在其中,定义了一系列与 redis 相关的基础数据操作接口,数据类型分别于下来 API 对应

非绑定key操作

ValueOperations<K, V> opsForValue();
<HK, HV> HashOperations<K, HK, HV> opsForHash();
ListOperations<K, V> opsForList();
SetOperations<K, V> opsForSet();
ZSetOperations<K, V> opsForZSet();

绑定key操作

BoundValueOperations<K, V> boundValueOps(K key);
<HK, HV> BoundHashOperations<K, HK, HV> boundHashOps(K key);
BoundListOperations<K, V> boundListOps(K key);
BoundSetOperations<K, V> boundSetOps(K key);
BoundZSetOperations<K, V> boundZSetOps(K key);
若以 bound 开头,则意味着在操作之初就会绑定一个 key,后续的所有操作便默认认为是对该 key 的操作,算是一个小优化。

2.1、String类型

设置当前的 key 以及 value 值

redisTemplate.opsForValue().set(key, value)

设置当前的 key 以及 value 值并且设置过期时间

redisTemplate.opsForValue().set(key, value, timeout, unit)

TimeUnit.DAYS //天
TimeUnit.HOURS //小时
TimeUnit.MINUTES //分钟
TimeUnit.SEConDS //秒
TimeUnit.MILLISEConDS //毫秒

将旧的 key 设置为 value,并且返回旧的 key(设置 key 的字符串 value 并返回其旧值

redisTemplate.opsForValue().getAndSet(key, value);

在原有的值基础上新增字符串到末尾

redisTemplate.opsForValue().append(key, value)

获取字符串的长度

redisTemplate.opsForValue().size(key)

重新设置 key 对应的值,如果存在返回 false,否则返回 true

redisTemplate.opsForValue().setIfAbsent(key, value)

设置 map 集合到 redis

Map valueMap = new HashMap();
valueMap.put(“valueMap1”,“map1”);
valueMap.put(“valueMap2”,“map2”);
valueMap.put(“valueMap3”,“map3”);
redisTemplate.opsForValue().multiSet(valueMap);

如果对应的 map 集合名称不存在,则添加否则不做修改

Map valueMap = new HashMap();
valueMap.put(“valueMap1”,“map1”);
valueMap.put(“valueMap2”,“map2”);
valueMap.put(“valueMap3”,“map3”);
redisTemplate.opsForValue().multiSetIfAbsent(valueMap);

通过 increment(K key, long delta) 方法以增量方式存储 long 值(正值则自增,负值则自减

redisTemplate.opsForValue().increment(key, increment);

批量获取值

修改 redis 中 key 的名称

如果旧值 key 存在时,将旧值改为新值

判断是否有 key 所对应的值,有则返回 true,没有则返回 false

删除单个 key 值

批量删除 key

设置过期时间

返回当前 key 所对应的剩余过期时间

返回剩余过期时间并且指定时间单位

查找匹配的 key 值,返回一个 Set 集合类型

将 key 持久化保存

将当前数据库的 key 移动到指定 redis 中数据库当中

2.2、Hash 类型

「Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。」 「Redis 中每个 hash 可以存储 2^32 - 1 键值对(40多亿)。」

获取变量中的指定 map 键是否有值,如果存在该 map 键则获取值,没有则返回 null。

获取变量中的键值对

新增 hashMap 值

以 map 集合的形式添加键值对

仅当 hashKey 不存在时才设置

删除一个或者多个 hash 表字段

查看 hash 表中指定字段是否存在

给哈希表 key 中的指定字段的整数值加上增量 increment

获取所有 hash 表中字段

获取 hash 表中存在的所有的值

获取 hash 表中字段的数量

匹配获取键值对,ScanOptions.NONE 为获取全部键对

2.3、List 类型

通过索引获取列表中的元素

获取列表指定范围内的元素(start 开始位置, 0 是开始位置,end 结束位置, -1返回所有)

存储在 list 的头部,即添加一个就把它放在最前面的索引处

把多个值存入 List 中(value 可以是多个值,也可以是一个 Collection value)

List 存在的时候再加入

按照先进先出的顺序来添加(value 可以是多个值,或者是 Collection var2)

设置指定索引处元素的值

移除并获取列表中第一个元素(如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止)

移除并获取列表最后一个元素

从一个队列的右边弹出一个元素并将这个元素放入另一个指定队列的最左边

删除集合中值等于 value 的元素(index=0, 删除所有值等于 value 的元素; index>0, 从头部开始删除第一个值等于 value 的元素; index<0, 从尾部开始删除第一个值等于 value 的元素)

将 List 列表进行剪裁

获取当前 key 的 List 列表长度

2.4、Set 类型

添加元素

移除元素(单个值、多个值)

判断集合是否包含 value

获取两个集合的交集(key 对应的无序集合与 otherKey 对应的无序集合求交集)

获取多个集合的交集(Collection var2)

key 集合与 otherKey 集合的交集存储到 destKey 集合中(其中 otherKey 可以为单个值或者集合)

key 集合与多个集合的交集存储到 destKey 无序集合中

获取两个或者多个集合的并集(otherKeys 可以为单个值或者是集合)

key 集合与 otherKey 集合的并集存储到 destKey 中(otherKeys 可以为单个值或者是集合)

获取两个或者多个集合的差集(otherKeys 可以为单个值或者是集合)

差集存储到 destKey 中(otherKeys 可以为单个值或者集合)

获取集合中的所有元素

随机获取集合中 count 个元素

随机获取集合中的一个元素

遍历 set 类似于 Interator(ScanOptions.NONE 为显示所有的)

2.5、zset 类型

ZSetOperations 提供了一系列方法对有序集合进行操作,添加元素(有序集合是按照元素的 score 值由小到大进行排列)。

删除对应的 value,value 可以为多个值

增加元素的 score 值,并返回增加后的值

返回元素在集合的排名,有序集合是按照元素的 score 值由小到大排列

返回元素在集合的排名,按元素的 score 值由大到小排列

获取集合中给定区间的元素(start 开始位置,end 结束位置, -1 查询所有)

按照 Score 值查询集合中的元素,结果从小到大排序

从高到低的排序集中获取分数在最小和最大值之间的元素

根据 score 值获取集合元素数量

获取集合中 key、value 元素对应的 score 值

移除指定索引位置处的成员

移除指定 score 范围的集合成员

获取 key 和 otherKey 的并集并存储在 destKey 中(其中 otherKeys 可以为单个字符串或者字符串集合

获取 key 和 otherKey 的交集并存储在 destKey 中(其中 otherKeys 可以为单个字符串或者字符串集合

遍历集合(和 iterator 一模一样

Spring Boot 中配置 Redis: application.properties

Spring Boot 的 spring-boot-starter-data-redis 为 Redis 的相关操作提供了一个高度封装的 RedisTemplate 类,而且对每种类型的数据结构都进行了归类,将同一类型操作封装为 operation 接口。RedisTemplate 对五种数据结构分别定义了操作,如下所示

操作字符串:redisTemplate.opsForValue()
操作 Hash:redisTemplate.opsForHash()
操作 List:redisTemplate.opsForList()
操作 Set:redisTemplate.opsForSet()
操作 ZSet:redisTemplate.opsForZSet()
但是对于 string 类型的数据,Spring Boot 还专门提供了 StringRedisTemplate 类,而且官方也建议使用该类来操作 String 类型的数据。那么它和 RedisTemplate 又有啥区别呢

RedisTemplate 是一个泛型类,而 StringRedisTemplate 不是,后者只能对键和值都为 String 类型的数据进行操作,而前者则可以操作任何类型。
两者的数据是不共通的,StringRedisTemplate 只能管理 StringRedisTemplate 里面的数据,RedisTemplate 只能管理 RedisTemplate 中 的数据。
实践

redis工具类

报错1

报错2

关于 Redis 的几个经典问题

缓存与数据库一致性问题

对于既有数据库操作又有缓存操作的接口,一般分为两种执行顺序。

先操作数据库,再操作缓存。这种情况下如果数据库操作成功,缓存操作失败就会导致缓存和数据库不一致。
第二种情况就是先操作缓存再操作数据库,这种情况下如果缓存操作成功,数据库操作失败也会导致数据库和缓存不一致。
大部分情况下,我们的缓存理论上都是需要可以从数据库恢复出来的,所以基本上采取第一种顺序都是不会有问题的。针对那些必须保证数据库和缓存一致的情况,通常是不建议使用缓存的。
缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案

  1. 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截
  2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击

缓存雪崩问题
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案

  1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
  3. 设置热点数据永远不过期。

缓存击穿问题
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期,这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案

  1. 加互斥锁,。当从缓存中获取数据失败时,给当前接口加上锁,从数据库中加载完数据并写入后再释放锁。若其它线程获取锁失败,则等待一段时间后重试。(数据库取数据时加锁)
  2. 使用布隆过滤器。将所有可能存在的数据缓存放到布隆过滤器中,当黑客访问不存在的缓存时迅速返回避免缓存及 DB 挂掉。
本文地址:http://syank.xrbh.cn/news/9999.html    迅博思语资讯 http://syank.xrbh.cn/ , 查看更多
 
标签: 项目 实战
 
更多>同类资讯
0相关评论

新闻列表
企业新闻
推荐企业新闻
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  粤ICP备2023022329号