本文主要是介绍Redis基础数据结构、持久化机制和缓存淘汰策略,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
part 01:Redis基础数据结构
1、Redis基础数据结构
-
string:可以将JSON序列化成字符串,放入Redis缓存
-
原子计数:如果value值是一个整数,还可以对它进行
自增操作。自增是有范围的,它的范围是
signed long
的最大最小值,超过了这个值,
Redis
会报错(可以用来设置分布式锁)
-
incr key #自增1,如果key不存在,key的值会先被初始化为0,然后再执行incr操作
-
incrby key 5 #增加5
* set key value
* get key
* exists key #判断是否存在key
* del key #删除
* mset key1 value1 key2 value2 ... #批量设置值
* mget key1 key2 ... #批量取值
* expire key 5 #设置过期时间,5s后过期
* setex key 5 value #5s后过期
* setnx ke value #如果key不存在就执行set创建,存在就不执行
-
list:相当于Java中的LinkedList,增删快O(1),查询慢O(n)。常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。(当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。)
* rpush key value1 value2... #从右边插入
* lpop key #从左边取出,第一个元素
* rpop key #从右边取出,最后一个元素
* llen key #返回长度
* lrange key 0 10 #从左边开始取出0-10的数据
* lindex key index #通过索引index获取列表中的元素
-
hash:相当于Java中的HashMap。当哈希表中元素数量逐渐增加时,此时产生hash冲突的概率逐渐增大,且由于dict也是采用拉链法解决hash冲突的,随着hash冲突概率上升,链表会越来越长,这就会导致查找效率下降,需要扩容,会发生reHash。相反,当元素不断减少时,元素占用dict的空间就越少,出于对内存的极致利用,此时就需要进行缩容操作。负载因子=哈希表中已保存节点数量/哈希表的大小
-
优点:可以获取对象信息中的部分字段信息
-
缺点:存储消耗要高于单个字符串
* hset key k1 v1
* hmset key k1 v1 k2 v2 k3 v3 ... #批量放入
* hgetall key #取出key里面所有元素,包括对应的key value
* hlen key #返回长度
* hset key k1 v2 #更新操作
* hget key k1 #取出
-
set:相当于Java中的HashSet,内部的键值对是无序且唯一的。内部实现相当于特殊的hash,hash中所有的value都是null
* sadd key val1 val2 #批量放入,不重复
* smembers key #无序取出
* sismember key val1 #查询val1是否存在
* scard key #获取长度
* spop key #取出一个
-
zset(有序集合):类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score(可以重复,double类型),代表这个 value 的排序权重。
* zadd key 1 value #1为score,vlue唯一,重复更新score
* zrange key 0 -1 #按score排序列出,0表示第一个,-1 表示最后一个
* zrevrange key 0 -1 #按score倒序列出,参数区间为排名范围
* zrangebyscore key 0 8.88 #根据score区间遍历key
* zrangebyscore key -inf 8.88 withscores#根据score区间(-无穷,8.88]遍历key,同时返回分值。
* zcard key #获取长度
* zscore key value #获取指定value的score
* zrank key value #获取指定value的排名
* zrem key value #删除value
2、Redis其他高级命令
-
keys:全量遍历键。用来列出所有满足特定正则字符串规则的key,当redis数据量比较大时,性能比较差,要避免使用。keys k*
-
scan:渐进式遍历键。scan 参数提供了三个参数,第一个是 cursor 整数值,第二个是 key 的正则模式,第三个是遍历的 limit hint。第一次遍历时,cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor。一直遍历到返回的 cursor 值为 0 时结束。cursor游标是无序的
-
info:查看Redis服务运行信息。分为 9 大块,每个块都有非常多的参数
-
Server 服务器运行的环境参数
-
Clients 客户端相关信息
-
Memory 服务器运行内存统计数据
-
Persistence 持久化信息
-
Stats 通用统计数据
-
Replication 主从复制相关信息
-
CPU CPU 使用情况
-
Cluster 集群信息
-
KeySpace 键值对统计数量信息
part 02:Redis持久化机制
1、Redis单线程为什么还能高性能?
-
因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。
正因为 Redis 是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如keys),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。
-
Redis的IO多路复用:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
2、Redis持久化机制
-
RDB快照:
-
在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。
-
可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集,二进制。
比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:
# save 60 1000
-
缺点:存在数据丢失,保存数据时效率慢
-
AOF:
-
快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件,重启的时候读取一遍这个文件并执行里面的指令
-
可以通过修改配置文件来打开 AOF 功能:
# appendonly yes
-
可以配置 Redis 多久才将数据 fsync 到磁盘一次
-
每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。appendfsync always
-
每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。(推荐且默认)appendfsync everysec
-
从不 fsync :将数据交给操作系统来处理。更快,也更不安全。appendfsync no
-
缺点:当AOF文件很大的时候,启动慢
-
Redis 4.0 混合持久化:
-
AOF在重写(aof文件里可能有太多没用指令,所以aof会定期根据内存的最新数据生成aof文件)时将重写这一刻之前的内存rdb快照文件的内容和增量(重写之后下次重写之前产生的记录,重写过程中新操作会存在内存里,等aof重写完之后再追加到aof文件末尾)的AOF修改内存数据的命令日志文件存在一起,都写入新的aof文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,原子的覆盖原有的AOF文件,完成新旧两个AOF文件的替换
-
AOF根据配置规则在后台自动重写,也可以人为执行命令bgrewriteaof重写AOF。 于是在 Redis 重启的时候,可以先加载 rdb 的内容(效率快),然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。
-
开启混合持久化:
# aof-use-rdb-preamble yes
# appendonly yes
part 03:缓存淘汰策略
1、什么时候进行缓存淘汰
-
当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap)。交换会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样存取效率基本上等于不可用。
在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提供了配置参数 maxmemory 来限制内存超出期望大小。
当实际内存超出 maxmemory 时,Redis 提供了几种可选策略 (maxmemory-policy) 来让用户自己决定该如何腾出新的空间以继续提供读写服务。
2、缓存淘汰策略
-
noeviction:不会继续写请求(DEL请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。(默认的淘汰策略)
-
volatile-lru(Least Recently Used最近最少使用):淘汰设置了过期时间的key,最近最少使用的key优先被淘汰。没有设置过期时间的key不会被淘汰。
-
volatile-ttl:淘汰的设置了过期时间的key,根据key的剩余寿命ttl的值进行淘汰,ttl越小优先被淘汰
-
volatile-random:淘汰过期key集合中随机的key
-
allkeys-lru:和volatile-lru一样,也是最近最少使用的key优先被淘汰,不过allkeys-lru要淘汰的key是全体key集合,而不只是过期的key集合。
-
allkeys-random:淘汰全体key集合中随机的key
volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的 key 进行淘汰。如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时不必携带过期时间。如果你还想同时使用 Redis 的持久化功能,那就使用 volatile-xxx 策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被 LRU 算法淘汰。
这篇关于Redis基础数据结构、持久化机制和缓存淘汰策略的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!