Redis基础数据结构、持久化机制和缓存淘汰策略

2021/5/19 19:29:46

本文主要是介绍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基础数据结构、持久化机制和缓存淘汰策略的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程