springboot中RedisTemplate的使⽤
Redis 简介
Redis 是⼀个开源(BSD 许可)、内存存储的数据结构服务器,可⽤作数据库,⾼速缓存和消息队列代理。它⽀持字符串、哈希表、列表、集合、有序集合等数据类型。内置复制、Lua 脚本、LRU 收回、事务以及不同级别磁盘持久化功能,同时通过 Redis Sentinel 提供⾼可⽤,通过Redis Cluster 提供⾃动分区。
Redis 使⽤场景
微服务以及分布式被⼴泛使⽤后,Redis 的使⽤场景就越来越多了,这⾥我罗列了主要的⼏种场景。
1. 分布式缓存:在分布式的系统架构中,将缓存存储在内存中显然不当,因为缓存需要与其他机器共享,这时 Redis 便挺⾝⽽出了,缓存也是
Redis 使⽤最多的场景。
2. 分布式锁:在⾼并发的情况下,我们需要⼀个锁来防⽌并发带来的脏数据,Java ⾃带的锁机制显然对进程间的并发并不好使,此时可以利⽤
Redis 单线程的特性来实现我们的分布式锁,如何实现,可以参考这篇⽂章。
3. Session 存储/共享:Redis 可以将 Session 持久化到存储中,这样可以避免由于机器宕机⽽丢失⽤户会话信息。(个⼈认为更重要的是因为
服务集的出现,需要⼀个分布式Session来作为统⼀的会话)
4. 发布/订阅:Redis 还有⼀个发布/订阅的功能,您可以设定对某⼀个 key 值进⾏消息发布及消息订阅,当⼀个 key 值上进⾏了消息发布后,
所有订阅它的客户端都会收到相应的消息。这⼀功能最明显的⽤法就是⽤作实时消息系统。
5. 任务队列:Redis 的 lpush+brpop 命令组合即可实现阻塞队列,⽣产者客户端使⽤ lrpush 从列表左侧插⼊元素,多个消费者客户端使⽤
brpop 命令阻塞式的”抢”列表尾部的元素,多个客户端保证了消费的负载均衡和⾼可⽤性。
6. 限速,接⼝访问频率限制:⽐如验证码的接⼝,通常为了防⽌别⼈恶意频刷,会限制⽤户每分钟获取验证码的频率,例如⼀分钟不能
超过 5 次。
当然 Redis 的使⽤场景并不仅仅只有这么多,还有很多未列出的场景,如计数、排⾏榜等。
Redis 数据类型
前⾯也提到过,Redis ⽀持字符串、哈希表、列表、集合、有序集合五种数据类型的存储。
字符串(str ing)
string类型是⼆进制安全的。意思是redis的string可以包含任何数据。⽐如jpg图⽚或者序列化的对象 。
string类型是Redis最基本的数据类型,⼀个键最⼤能存储512MB。
string 这种数据结构应该是我们最为常⽤的。在 Redis 中 string 表⽰的是⼀个可变的字节数组,我们初始化字符串的内容、可以拿到字符串的长度,可以获取 string 的⼦串,可以覆盖 string 的⼦串内容,可以追加⼦串。
redis支持的五种数据类型Redis 的 string 类型数据结构
如上图所⽰,在 Redis 中我们初始化⼀个字符串时,会采⽤预分配冗余空间的⽅式来减少内存的频繁分配,如图 1 所⽰,实际分配的空间capacity ⼀般要⾼于实际字符串长度 len。如果您看过 Java 的 ArrayList 的源码相信会对此种模式很熟悉。
列表(list)
redis列表是简单的字符串列表,排序为插⼊的顺序。列表的最⼤长度为2^32-1。
redis的列表是使⽤链表实现的,这意味着,即使列表中有上百万个元素,增加⼀个元素到列表的头部或尾部的操作都是在常量的时间完成。
可以⽤列表获取最新的内容(像帖⼦,微博等),⽤ltrim很容易就会获取最新的内容,并移除旧的内容。
⽤列表可以实现⽣产者消费者模式,⽣产者调⽤lpush添加项到列表中,消费者调⽤rpop从列表中提取,如果没有元素,则轮询去获取,或者使⽤brpop等待⽣产者添加项到列表中。
在 Redis 中列表 list 采⽤的存储结构是双向链表,由此可见其随机定位性能较差,⽐较适合⾸位插⼊删除。像 Java 中的数组⼀样,Redis 中的列表⽀持通过下标访问,不同的是 Redis 还为列表提供了⼀种负下标,-1 表⽰倒数⼀个元素,-2 表⽰倒数第⼆个数,依此类推。综合列表⾸尾增删性能优异的特点,通常我们使⽤ rpush/rpop/lpush/lpop 四条指令将列表作为队列来使⽤。
List 类型数据结构
如上图所⽰,在列表元素较少的情况下会使⽤⼀块连续的内存存储,这个结构是 ziplist,也即是压缩列表。它将所有的元素紧挨着⼀起存储,分配的是⼀块连续的内存。当数据量⽐较多的时候才会改成 quicklist。因为普通的链表需要的附加指针空间太⼤,会⽐较浪费空间。⽐如这个列表⾥存的只是 int 类型的数据,结构上还需要两个额外的指针 prev 和 next。所以 Redis 将链表和 ziplist 结合起来组成了 quicklist。也就是将多个 ziplist 使⽤双向指针串起来使⽤。这样既满⾜了快速的插⼊删除性能,⼜不会出现太⼤的空间冗余。
哈希表(ha sh)
redis的哈希值是字符串字段和字符串之间的映射,是表⽰对象的完美数据类型。
哈希中的字段数量没有限制,所以可以在你的应⽤程序以不同的⽅式来使⽤哈希。
hash 与 Java 中的 HashMap 差不多,实现上采⽤⼆维结构,第⼀维是数组,第⼆维是链表。hash 的 key 与 value 都存储在链表中,⽽数组中存储的则是各个链表的表头。在检索时,⾸先计算 key 的 hashcode,然后通过 hashcode 定位到链表的表头,再遍历链表得到 value 值。可能您⽐较好奇为啥要⽤链表来存储 key 和 value,直接⽤ key 和 value ⼀对⼀存储不就可以了吗?其实是因为有些时候我们⽆法保证hashcode 值的唯⼀,若两个不同的 key 产⽣了相同的 hashcode,我们需要⼀个链表在存储两对键值对,这就是所谓的 hash 碰撞。
集合(set)
redis集合是⽆序的字符串集合,集合中的值是唯⼀的,⽆序的。可以对集合执⾏很多操作,例如,测试元素是否存在,对多个集合执⾏交集、并集和差集等等。
我们通常可以⽤集合存储⼀些⽆关顺序的,表达对象间关系的数据,例如⽤户的⾓⾊,可以⽤sismember很容易就判断⽤户是否拥有某个⾓⾊。
在⼀些⽤到随机值的场合是⾮常适合的(抽奖),可以⽤ srandmember/spop 获取/弹出⼀个随机元素。
同时,使⽤@EnableCaching开启声明式缓存⽀持,这样就可以使⽤基于注解的缓存技术。注解缓存是⼀个对缓存使⽤的抽象,通过在代码中添加下⾯的⼀些注解,达到缓存的效果。
@Cacheable:在⽅法执⾏前Spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;没有则调⽤⽅法并将⽅法返回值放进缓存。(查)
@CachePut:将⽅法的返回值放到缓存中。(增/改)
@CacheEvict:删除缓存中的数据。(删)
熟悉 Java 的同学应该知道 HashSet 的内部实现使⽤的是 HashMap,只不过所有的 value 都指向同⼀个对象。Redis 的 Set 结构也是⼀样,它的内部也使⽤ Hash 结构,所有的 value 都指向同⼀个内部值。
有序集合(so r ted set)
有序集合由唯⼀的,不重复的字符串元素组成。有序集合中的每个元素都关联了⼀个浮点值,称为分数。可以把有序集合zset看成hash和集合的混合体,分数即为hash的key。
有序集合中的元素是按序存储的,不是请求时才排序的。
有时也被称作 ZSet,是 Redis 中⼀个⽐较特别的数据结构,在有序集合中我们会给每个元素赋予⼀个权重,其内部元素会按照权重进⾏排序,我们可以通过命令查询某个范围权重内的元素,这个特性在我们做⼀个排⾏榜的功能时可以说⾮常实⽤了。其底层的实现使⽤了两个数据结构,
pojo
以上
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论