redis数据结构、持久化、缓存淘汰策略

Redis 单线程高性能,它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。

1.Redis数据结构及简单操作指令

String、list、set、hash、zset(有序set)

总体来说redis都是通过Key-Value的形式来存储数据的。只是不用数据类型Value的形式不同。

String:最简单数据结构,比如我们将一个对象转成json串来存储

  set key value 存放数据

  get key 获取数据

  exists key 查看数据是否存在,存在返回1否则0

  del key 删除数据 返回操作成功的条数

  mset key1 value1 key2 value2 key3 value3...存放多组数据

  mget key1 ke2y key3... 获取多个key的数据,返回一个集合,类似Map的values方法

  expire key second 设置key 过去时间,单位秒

  setex key second value设置key 过去时间,单位秒(等价于先set,再expire)

  setnx key value 如果key不存在就set 返回1.如果存在返回0(可以基于此实现分布式锁)

List:并不是java里面的list,redis的list更像一个链表或者说队列/栈的结构。这就意味着它的删除插入快,但是通过索引定位就比较慢了。当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。

Redis 的列表结构常用来做异步队列使用。将需要延后处理的任务塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。

  rpush key value1 value2 value3...  插入list数据

  llen key     查看长度

  lpop key    按加入顺序获取(先进先出,类似队列)

  rpop key   后进先出,有点类似栈

  列表取数据,取完后整个列表都被回收了,就是说只能取一次数据。

Hash:类似java的hashMap,和字符串相比,我们存储数据的时候可以只存储对象的部分属性,而字符串则需要完整将整个对象转换。当然hash存储结构的消耗肯定是高于字符串的

  hset redisKey hashKey1 value1

   hset redisKey hashKey2 value2  插入数据

  hgetall redisKey  获取数据,key value间隔出现

  hlen redisKey  查看hash长度

  hget redisKey hashKey 获取hashKey 对应的value

  hmset redisKey hashKey1 value1 hashKey2 value2 hashKey2 value3 批量插入值

Set : 类似HashSet,但是list类似,最后一个数据取完之后,该结构会被清理,无法再次获取数据

  sadd key value

  sadd key value1 value2   批量添加

  smembers key    查看所有

  sismember key value  查询某个值是否存在,存在返回1

  scard  key   查看大小

  spop key    获取一个元素

原子计数操作

如果value是整数的话还可以实现自增操作(也可以用于实现分布式锁,该增长有限,最大到long max,超过该值会直接报错)

incr key 自增 如果key不存在默认从0自增1

incrby key step 设置增加步长step

2.redis持久化

虽然说redis都是内存级别的操作,其实也是有持久化的。

一种是基于RDB快照,

Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。

可以对 Redis 进行设置, 让它在N 秒内数据集至少有 M 个改动这一条件被满足时, 自动保存一次数据集。

另一种是AOF(append-only file)

快照并不可靠,上次快照之后,还未到达下一次快照条件时,这时候服务出现了问题,那么这期间的数据是无法保存到快照版本中的。这个时候就需要AOF了,它将每一条指令都记录进文件,当redis重启的时候,重新执行这个文件里面指令,就可以恢复所有的数据到内存中了。

可以通过配置appendonly yes 来开启AOF,默认是关闭的

AOF也有三种同步数据的策略,

每次有操作都去刷新文件,很慢,但安全

每秒同步刷新一次:可能会丢失一秒内的数据

从不同步同步刷新:让操作系统在需要的时候刷新数据,不安全

默认的是每秒刷一次

混合持久化:

RDB快照数据恢复速度快,但是可能会有大量数据丢失,所以通常恢复数据还是用的AOF日志重放,但是AOF相对来说速度会很慢,尤其是在数据量大的时候。因此在4.0的时候带来了混合持久化,也就是AOF在刷新的时候,先记录上次的快照版本,然后记录上次快照版本到现在的增量操作,然后合并成一个文件,覆盖原来的appendonly.aof文件。Redis重启的时候,先加载RDB快照的内容,在重放AOF日志中增量操作的内容就可以了。

开启混合持久化:aof-use-rdb-preamble yes

混合持久化中appendonly.aof内容格式,一部分是RDB文件内容格式,另外的才是AOF文件的内容格式。

3.缓存淘汰策略:

当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 。会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样存取效率基本上等于不可用。

在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提供了配置参数 maxmemory 来限制内存超出期望大小。

当实际内存超出 maxmemory 时,Redis 提供了几种可选策略 (maxmemory-policy) 来让用户自己决定该如何腾出新的空间以继续提供读写服务。

 maxmemory <bytes>

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don‘t evict anything, just return an error on write operations.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction

noeviction 不会继续处理写请求 (del,read请求可以继续进行)。这样可以保证不会丢失数据,但是会让线上的写相关的业务不能持续进行。这是默认的淘汰策略。

volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。

volatile-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl 越小越优先被淘汰。

volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。

allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期时间的 key 也会被淘汰。

allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。

volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的 key 进行淘汰。如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时不必携带过期时间。如果你还想同时使用 Redis 的持久化功能,那就使用 volatile-xxx 策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被 LRU 算法淘汰。

原文地址:https://www.cnblogs.com/nijunyang/p/11443001.html

时间: 2024-10-09 07:46:57

redis数据结构、持久化、缓存淘汰策略的相关文章

redis缓存淘汰策略

缓存淘汰策略 介绍 当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap).交换会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样龟速的存取效率基本上等于不可用. 在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提供了配置参数 maxmemory 来限制内存超出期望大小. 当实际内存超出 maxmemory 时,Redis 提供了几种可选策略 (maxmemory-policy) 来让用户自己

Redis 数据结构与内存管理策略(下)

Redis 数据结构与内存管理策略(下) Redis 数据类型特点与使用场景 String.List.Hash.Set.Zset 案例:沪江团购系统大促 hot-top 接口 cache 设计 Redis 内存数据结构与编码 OBJECT encoding key.DEBUG OBJECT key 简单动态字符串(simple dynamic string) 链表(linked list) 字典(dict) 跳表(skip list) 整数集合(int set) 压缩表(zip list) Re

Redis中的LRU淘汰策略分析

Redis作为缓存使用时,一些场景下要考虑内存的空间消耗问题.Redis会删除过期键以释放空间,过期键的删除策略有两种: 惰性删除:每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键:如果没有过期,就返回该键. 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键. 另外,Redis也可以开启LRU功能来自动淘汰一些键值对. LRU算法 当需要从缓存中淘汰数据时,我们希望能淘汰那些将来不可能再被使用的数据,保留那些将来还会频繁访问的数据,但最大的问题是缓存并

Redis数据过期和淘汰策略详解(转)

原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除了对性能,稳定性有很高的要求外,对内存占用也比较敏感.在使用过程中,有些用户会觉得自己的线上实例内存占用比自己预想的要大. 事实上,实例中的内存除了保存原始的键值对所需的开销外,还有一些运行时产生的额外内存,包括: 垃圾数据和过期Key所占空间 字典渐进式Rehash导致未及时删除的空间 Redis

三种缓存淘汰策略

1, FIFO 先进先出,底层是利用双向链表,新来的数据放到链表的尾部,如果链表塞满了就删除头部的. 2, LFU 最近最少使用算法.思路就是如果一个数据在最近一段时间内使用次数最少,那么将来一段时间使用的可能性也很少. LFU 是基于访问次数的. 实现:两个HASHMAP, 一个是用来存储数据的, key-value. 一个是用来存储次数的, key-time. 当访问一个key 的时候就在 key-time, 也就是的第二个hashmap 对应的time 加1. 删除的时候就寻找最少time

redis键的过期和内存淘汰策略

键的过期时间 设置过期时间 Redis可以为存储在数据库中的值设置过期时间,作为一个缓存数据库,这个特性是很有帮助的.我们项目中的token或其他登录信息,尤其是短信验证码都是有时间限制的. 按照传统的方法都是项目本身判断过期,这样无疑影响了系统性能. redis可以为set或者expire两种方式为键设置过期时间 1 Jedis jedis = new Jedis("localhost"); 2 //nxxx:nx是不存在是才set,xx是存在时才set 3 //expx:EX是秒,

Chapter 6 链表(上):如何实现LRU缓存淘汰算法?

缓存淘汰策略: 一.什么是链表? 1.和数组一样,链表也是一种线性表. 2.从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构. 3.链表中的每一个内存块被称为节点Node.节点除了存储数据外,还需记录链上下一个节点的地址,即后继指针next. 二.为什么使用链表?即链表的特点 1.插入.删除数据效率高O(1)级别(只需更改指针指向即可),随机访问效率低O(n)级别(需要从链头至链尾进行遍历). 2.和数组相比,内存空间消耗更大,因为每个存

06 | 链表(上):如何实现LRU缓存淘汰算法?

我们先来讨论一个经典的链表应用场景,那就是 LRU 缓存淘汰算法. 缓存的大小有限,当缓存被用满时,哪些数据应该被清理出去,哪些数据应该被保留?这就需要缓存淘汰策略来决定. 常见的策略有三种: 先进先出策略 FIFO(First In,First Out).最少使用策略 LFU(Least Frequently Used).最近最少使用策略 LRU(Least Recently Used). 三种最常见的链表结构,它们分别是:单链表.双向链表和循环链表. 数组简单易用,在实现上使用的是连续的内存

Redis基本数据类型、数据持久化、过期策略及淘汰机制

一点技术.技术乐享!!! 如果有人问你:Redis这么快,他的“多线程模式”你了解吗? 请回答他:您是想问Redis这么快,为什么还是单线程模式吗? redis是什么 简单来说redis是C语言开发的一个开源的(遵从BSD协议)高性能键值对(key-value)的内存数据库,可以用作数据库.缓存.消息中间件等. 性能优秀,数据在内存中,读写速度非常快,支持并发10W QPS. 单进程单线程,是线程安全的,采用Io多路复用机制. 丰富的数据类型,支持字符串(string).散列(hash).列表(