目录
一、数据类型
二、 持久化策略
1. RDB
2. AOF
3. 结合使用
三、 key过期删除策略
四、 回收策略
五、 分布式锁
六、 缓存穿透,缓存击穿,缓存雪崩
参考:https://blog.csdn.net/Mr_FLM/article/details/97380305
Redis数据类型简介:
Redis支持字符串、哈希表、列表、集合、有序集合、位图、地理位置和HyperLogLog这八种数据类型。Redis的所有数据结构都以唯一的key字符串作为名称,然后通过这个唯一的key值获取相应的value数据。不同类型的数据结构的差异就在于value的结构不一样。
1、字符串(string)
Redis的字符串时动态字符串,是可以修改的字符串,内部结构类似于Java的ArrayList。它采用预分配冗余空间的方式来减少内存的频繁分配,内部为当前字符串分配的实际空间capacity一般要高于实际字符串长度len。当字符串长度小于1MB时,扩容都是加倍现有的空间。如果字符串长度超过1MB,扩容时一次只会多扩1MB的空间。需要注意的是字符串最大长度为512MB。
常见用途:
存储用户信息。存储对象时,将用户对象使用JSON序列化成字符串,然后塞进Redis来缓存。取出对象时,将JSON字符串反序列化用户对象。
2、列表(list)
Redis的列表相当于Java的LinkedList,注意它时链表而不是数组。这意味着list的插入与删除操作非常快,时间复杂度为O(1),但是索引定位很慢,时间复杂度为O(n)。列表中的每个元素之间都使用双向指针顺序连接,同时支持前后向遍历。当列表弹出最后一个元素时,该数据结构被自动删除,内存被回收。
常见用途:
充当异步队列。一个线程将需要延后处理的任务结构体序列化成字符串,塞进Redis的列表,另一个线程从这个列表中轮询数据进行处理。
3、字典(hash)
Redis的字典相当于Java语言里面的HashMap,如下图所示,它是无序字典,内部存储了很多键值对。实现结构上与HashMap也是一样的,都是 “数组 + 链表” 形式的二维结构,第一维hash的数组位置碰撞时,就会将碰撞的元素使用链表串联起来。
不同的是,Redis的字典的值只能是字符串,另外它们的rehash的方式也不一样。因为Java的HashMap在字典很大时,rehash是个耗时的操作,需要一次性全部rehash。Redis为了追求高性能,不能堵塞服务,所以采用渐进式的rehash策略。
渐进式的rehash会在rehash的同时,保留新旧两个hash结构,查询会同时查询两个hash结构,然后在后续的定时任务或者hash操作指令 (hset、hdel) 中,循环渐进地将旧hash的内容一点点地迁移到新的hash结构中。当搬迁完成后,就会使用新的hash结构取而代之。当hash移除了最后一个元素之后,该数据结构被自动删除,内存被回收。
常见用途:
存储用户信息,可以对用户结构中每个字段单独操作。
4、集合(set)
Redis集合相当于Java中的HashSet,它内部存储的值是无序的、唯一的。它的内部相当于一个特殊的字典,只不过字典中的所有的value都是一个值NULL。当集合中最后一个元素被移出之后,数据结构被自动删除,内存被回收。
常见用途:
存储活动中中奖的用户ID,因为自带去重功能,可以保证同一个用户不会中奖两次。
5、有序集合(zset)
Redis有序集合,如下图所示,类似于Java的SortedSet和HashMap的结合体。一方面它是一个set,保证了内部value的唯一性,另一方面它可以给每个value赋予一个score,代表这个value的排序权重。它内部实现用的是一种叫作 “跳跃列表” 的数据结构。zset中最后一个value被移除后,数据结构被自动删除,内存被回收。
常见用途:
1、zset可以用来存储粉丝列表,value值是粉丝的用户ID,score是关注时间。实现对粉丝列表按关注时间进行排序。
1、zset可以用来存储学生成绩,value值是学生的ID,score是学生的成绩。对成绩进行排序得到其名次。
6、位图(bitmap)
Redis在2.2.0版本添加了对位图bitmap的支持。bitmap是一串连续的二进制数字 (0或1),每一位所在的位置为偏移 (offset),在bitmap上可执行AND,OR和XOR以及其它位操作。
常见用途:
统计日活跃用户或者网站页面访问量。
7、地理位置
Redis在3.2.0版本添加了对地理位置 (GEO) 的支持。它使用geohash保存地理位置的坐标,使用有序集合 (zset) 保存地理位置的集合。
常见用途:
1、根据经纬度查找地理位置;
2、根据地理位置计算经纬度;
3、根据地理位置,计算两地距离。
8、HyperLogLog
Redis在2.8.9版本添加了HyperLogLog数据结构。HyperLogLog是用来做基数统计的算法。它的优点是,在输入元素的数量或者体积非常大时,计算基数所需的空间总是固定的、并且是很小的。
在Redis里面,每个HyperLogLog键只需要占12KB的存储空间。在计数比较小时,它的存储空间才用稀疏矩阵存储,空用占用很小,仅仅在计数慢慢变大,稀疏矩阵占用空间渐渐超过阈值时,才会一次性转变成稠密矩阵,才会占用12KB的内存。HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身。它提供不精确的去重计数方案,标准误差是0.81%。
常见用途:
统计网站页面访问量。
————————————————
版权声明:本文为CSDN博主「SuperLonelyCat」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Mr_FLM/article/details/97380305
数据集快照方式来记录redis数据库的所有键值对,隔段时间将数据写入临时的文件,持久化结束后,用这个临时文件替换上次的文件。save时可以BgSave使用fork协程来操作
aof日志记录的时数据操作修改的指令记录日志。类似与mysql的Binlog,redolog。aof随着时间无限增量
如果采用RDB快照时间使用BgSave可能会丢失数据,AOF恢复数据可能会很慢。Redis 4.0 后,为了解决这个问题,提出了新的持久化机制,混合持久化,将RDB文件和局部增量的AOF结合使用。
RDB可以使用相间隔时间较长的保存策略,AOF不需要保存全量的操作日志 只保存前一次RDB开始到这段时间的增量AOF日志即可,一般来说,这个日志会很小。
当一个键处于过期状态,其实并不是实时删除的,而是通过一定的机制来把过期的数据移除,达到内存释放的作用
被删除存在以下几种场景:
定时删除:
在设置过期时间同时,创建一个定时器,让定时器在定时到来时立即删除操作, 对内存很友好,但是单线程对cpu很不利,不适用
惰性删除:
放任过期不管,每当从键空间获取键时,判断并删除
定期删除:
一段时间,对数据检查,过期的删除,一般结合惰性删除使用。
当内存不足时,会触发回收
volatile
常用策略: 已设置过期的数据,中删除最近使用少的数据
使用setnx结合过期时间使用redis的分布式锁。
缓存穿透:
想象一下这个情况,如果每次都去查询数据库,而每次查询都是空,每次又都不会进行缓存。假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库。即便是采用UUID,也是很容易找到一个不存在的KEY,进行攻击。
小编在工作中,会采用缓存空值的方式,也就是【代码流程】中第5步,如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如设置为60秒
缓存击穿:
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
小编在做电商项目的时候,把这货就成为“爆款”。
其实,大多数情况下这种爆款很难对数据库服务器造成压垮性的压力。达到这个级别的公司没有几家的。所以,务实主义的小编,对主打商品都是早早的做好了准备,让缓存永不过期。即便某些商品自己发酵成了爆款,也是直接设为永不过期就好了。
缓存雪崩:
缓存雪崩,是指在某一个时间段,缓存集中过期失效。
产生雪崩的原因之一,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。
小编在做电商项目的时候,一般是采取不同分类商品,缓存不同周期。在同一分类中的商品,加上一个随机因子。这样能尽可能分散缓存过期时间,而且,热门类目的商品缓存时间长一些,冷门类目的商品缓存时间短一些,也能节省缓存服务的资源。