Redis – 高性能 + 高并发

2023年1月29日08:56:45

目录

1.关系型数据库和非关系型数据库的区别 ?

1. KV型NoSql(代表----Redis)

2. 搜索型NoSql(代表--ElasticSearch )

3. 文档型NoSql(代表----MongoDB)

4. Memcache 与 Redis 的区别都有哪些?

5. 数据库与NoSql及各种NoSql间的对比

2.Redis 是什么?  都有哪两种缓存? 为什么这么快?  Redis 的优缺点? 

1. Redis 是什么? 

2. 本地/分布式 缓存:

3. Redis 为什么快:

4.Redis 和其key-value 相比, 有什么特殊的?

5. Resid 优缺点 : 

3. Redis 中key-value中value 的5 种数据类型

1. 在项目中的应用场景

4. 数据的一致性问题、删除策略

1.如何让保证缓存数据的一致性问题?

2. Redis 中查询的数据怎么保证数据查询的一致性?

3. 为什么是删除缓存,而不是更新缓存?

4. 数据不一致 * 简单情况 : 为什么先删缓存, 再更新数据库?

5. 数据不一致 * 复杂情况: 数据变更--> 删了缓存-->修改数据库之前有了请求...

6. 单节点下:  ✅先删缓存 后更新库 与 ❌先更新库 后删缓存 对比

7. key 过期的删除策略

7. Redis key的过期时间和永久有效分别怎么设置?

8. 有大量的 key 需要设置同一时间过期,需要注意 什么?

5. 内存相关

1. MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据

2. Redis的[ 内存淘汰策略/回收策略 ]有哪些?  ----  6 种..

3. Redis主要消耗什么物理资源? 

3.Redis集群最大节点个数是多少?

3.一个字符串类型的值能存储最大容量是多少?

4.为什么 Redis 需要把所有数据放到内存中?

5. Redis的内存用完了会发生什么?

6. Redis如何做内存优化?

6.  Redis 单线程快的原因?

1. 单线程机制

7. Redis持久

1. Redis 能保证数据不丢失吗?

2. Redis 怎么防止数据丢失?

3. RDB快照模式 :  Redis DataBase. 

4. AOF 日志模式 : Append Only File 

5. 两种机制对比:

6. 如何选择合适的持久化方式

7. Redis持久化数据和缓存怎么做扩容?

8. 在你的项目中 Redis 中都存什么信息? 所有数据都可以存在Redis中吗?

6. Redis 事务

1. Redis 事务的本质 :

2. Redis事务的三个阶段

3. 事务管理(ACID)概述 

7. Redis 集群

1. Redis 集群的原理

2. 哨兵模式

2.说说 Redis 哈希槽的概念?

3. Redis 集群的 主从复制--(异步复制)

Redis 回收进程如何工作的?

8. 缓存异常 : 

1. 缓存击穿 :

2. 缓存穿透 :

3 缓存雪崩 :

4. 缓存预热

5. 缓存降级

6. 热点数据和冷数据

7. 缓存热点key

n.  Redis 常见性能问题和解决方案:

分布式 、 锁部分、集群方案、主从复制



无脑打开, 准没错 : Redis 常见面试题(2020最新版) - Java知音号 - 博客园

1.关系型数据库和非关系型数据库的区别 ?

source : Sql Or NoSql,看完这一篇你就懂了 - 五月的仓颉 - 博客园

source2: 关系型数据库与非关系型数据库区别 - 灬菜鸟灬 - 博客园

关系型数据库:  适合处理一般量级的数据. (Mysql 和 Oracle)

  • 表&表 ; 表&字段 ; 数据&数据 之间存在着关系.
  • 优点: 数据之间有关系, 增删改查方便 ; 且关系型数据库是有事务操作的(ACID), 保证了数据的完整性和一致性.
  • 缺点: 数据量大时操作效率低, 增删改查慢, 维护困难.

非关系型数据库: 处理海量数据, 出发点是为了代替关系型数据库 (Redis  和 MangoDB)

  • 优点 : 易扩展, 数据间没有联系; 对于海量数据的处理比较有优势; 可用性高
  • 缺点 : 数据间没有关系, 单独存在; 且没有事务关系, 无法保证数据的完整性和安全性. 且不具备分词功能.

Nosql : 非关系型数据库 Not only sql

Nosql 数据库四大分类 :

  1. 键值对存储 : (key-value)形式, Redis 键值存储, 优 : 适合结构查询; 缺 :存储缺少结构化
  2. 列存储 : (Hbase). 优 :快速查询,扩展性强 ; 缺 : 功能局限
  3. 文档数据存储 : MongoDB. 优 : 要求不严格, 缺 :查询效率不高
  4. 图形数据库存储 : 应用于社交网络, 优 : 有图型结构相关算法, 缺 : 需要整个图计算结果,不容易做分布式集群方案

1. KV型NoSql(代表----Redis)

        KV型NoSql顾名思义就是 以键值对形式存储的非关系型数据库。Redis、MemCache是其中的代表,Redis又是KV型NoSql中应用最广泛的NoSql,KV型数据库以Redis为例,最大的优点我总结下来就两点:

  • 数据基于内存,读写效率高
  • KV型数据,时间复杂度为O(1),查询速度快

因此,KV型NoSql最大的优点就是高性能,利用Redis自带的BenchMark做基准测试,TPS可达到10万的级别,性能非常强劲。同样的Redis也有所有KV型NoSql都有的比较明显的缺点

  • 只能根据K查V,无法根据V查K
  • 查询方式单一,只有KV的方式,不支持条件查询,多条件查询唯一的做法就是数据冗余,但这会极大的浪费存储空间
  • 内存是有限的,无法支持海量数据存储
  • 同样的,由于KV型NoSql的存储是基于内存的,会有丢失数据的风险

综上所述,KV型NoSql最合适的场景就是缓存的场景:

  • 读远多于写
  • 读取能力强
  • 没有持久化的需求,可以容忍数据丢失,反正丢了再查询一把写入就是了

例如根据用户id查询用户信息,每次根据用户id去缓存中查询一把,查到数据直接返回,查不到去关系型数据库里面根据id查询一把数据写到缓存中去。


2. 搜索型NoSql(代表--ElasticSearch 

它的优点为:

  • 支持分词场景、全文搜索,这是区别于关系型数据库最大特点
  • 支持条件查询,支持聚合操作,类似关系型数据库的Group By,但是功能更加强大,适合做数据分析
  • 数据写文件无丢失风险,在集群环境下可以方便横向扩展,可承载PB级别的数据
  • 高可用,自动发现新的或者失败的节点,重组和重新平衡数据,确保数据是安全和可访问的

同样,ElasticSearch也有比较明显的缺点:

性能全靠内存来顶,也是使用的时候最需要注意的点,非常吃硬件资源、吃内存,大数据量下64G + SSD基本是标配,算得上是数据库中的爱马仕了。至于ElasticSearch内存用在什么地方,大概有如下这些:

  • Indexing Buffer----ElasticSearch基于Luence,Lucene的倒排索引是先在内存里生成,然后定期以Segment File的方式刷磁盘的,每个Segment File实际就是一个完整的倒排索引
  • Segment Memory----倒排索引前面说过是基于关键字的,Lucene在4.0后会将所有关键字以FST这种数据结构的方式将所有关键字在启动的时候全量加载到内存,加快查询速度,官方建议至少留系统一半内存给Lucene
  • 各类缓存----Filter Cache、Field Cache、Indexing Cache等,用于提升查询分析性能,例如Filter Cache用于缓存使用过的Filter的结果集
  • Cluter State Buffer----ElasticSearch被设计为每个Node都可以响应用户请求,因此每个Node的内存中都包含有一份集群状态的拷贝,一个规模很大的集群这个状态信息可能会非常大
  • 读写之间有延迟,写入的数据差不多1s样子会被读取到,这也正常,写入的时候自动加入这么多索引肯定影响性能
  • 数据结构灵活性不高,ElasticSearch这个东西,字段一旦建立就没法修改类型了,假如建立的数据表某个字段没有加全文索引,想加上,那么只能把整个表删了再重建

因此,搜索型NoSql最适用的场景就是有条件搜索尤其是全文搜索的场景,作为关系型数据库的一种替代方案。


3. 文档型NoSql(代表----MongoDB)

因此文档型NoSql的出现是解决关系型数据库表结构扩展不方便的问题的

因此,对于MongDB,我们只要理解成一个Free-Schema的关系型数据库就完事了,它的优缺点比较一目了然,优点:

  • 没有预定义的字段,扩展字段容易
  • 相较于关系型数据库,读写性能优越,命中二级索引的查询不会比关系型数据库慢,对于非索引字段的查询则是全面胜出

缺点在于:

  • 不支持事务操作,虽然Mongodb4.0之后宣称支持事务,但是效果待观测
  • 多表之间的关联查询不支持(虽然有嵌入文档的方式),join查询还是需要多次操作
  • 空间占用较大,这个是MongDB的设计问题,空间预分配机制 + 删除数据后空间不释放,只有用db.repairDatabase()去修复才能释放
  • 目前没发现MongoDB有关系型数据库例如MySql的Navicat这种成熟的运维工具

总而言之,MongoDB的使用场景很大程度上可以对标关系型数据库,但是比较适合处理那些没有join、没有强一致性要求且表Schema会常变化的数据。


4. Memcache 与 Redis 的区别都有哪些?

1)、存储方式

Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。

Redis有部份存在硬盘上,这样能保证数据的持久性

2)、value大小

redis最大可以达到1GB,而memcache只有1MB

3)、数据支持类型

Memcache对数据类型支持相对简单。1. 文本型 、二进制类型

Redis有复杂的数据类型。String     List    Hash  Set   ZSet.

4)、持久化支持

Redis有 RDB 和 AOF 持久化机制,  Memecache 没有
5)、查询【操作】类型

Redis : 1. 批量操作 2. 事务支持 3. 每个类型不同的CRUD

Memecache : 1.常用的CRUD 2. 少量的其他命令

6)使用底层模型不同

它们之间  底层实现方式与客户端之间通信的应用协议 不一样。

Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。


5. 数据库与NoSql及各种NoSql间的对比

最后一部分,做一个总结,本文归根到底是两个话题:

  • 何时选用关系型数据库,何时选用非关系型数据库
  • 选用非关系型数据库,使用哪种非关系型数据库

首先是第一个话题,关系型数据库与非关系型数据库的选择,在我理解里面无非就是两点考虑:

第一点,不多解释应该都理解,非关系型数据库都是通过牺牲了ACID特性来获取更高的性能的,假设两张表之间有比较强的一致性需求,那么这类数据是不适合放在非关系型数据库中的。

第二点,核心数据不走非关系型数据库,例如用户表、订单表,但是这有一个前提,就是这一类核心数据会有多种查询模式,例如用户表有ABCD四个字段,可能根据AB查,可能根据AC查,可能根据D查,假设核心数据,但是就是个KV形式,比如用户的聊天记录,那么HBase一存就完事了。

这几年的工作经验来看,非核心数据尤其是日志、流水一类中间数据千万不要写在关系型数据库中,这一类数据通常有两个特点:

  • 写远高于读
  • 写入量巨大

一旦使用关系型数据库作为存储引擎,将大大降低关系型数据库的能力,正常读写QPS不高的核心服务会受这一类数据读写的拖累。

接着是第二个问题,如果我们使用非关系型数据库作为存储引擎,那么如何选型?其实上面的文章基本都写了,这里只是做一个总结(所有的缺点都不会体现事务这个点,因为这是所有NoSql相比关系型数据库共有的一个问题):


2.Redis 是什么?  都有哪两种缓存? 为什么这么快?  Redis 的优缺点? 

1. Redis 是什么? 

        可以理解成是一个缓存, 缓存主要解决高性能高并发的问题.

        不能用作海量数据的高性能读写, 只能用在较小数据量的高性能操作和运算.

  • 高性能: 每次从硬盘上读数据会比较慢,如果数据库中的数据改变, 同步改变缓存中相应的数据即可.
  • 高并发: 请求缓存承受的压力比请求数据库的压力小. 所以请求缓存的话可以不经过数据库. 减压了

2. 本地/分布式 缓存:

  • 本地缓存     : Java自带的map / guava 实现本地缓存,其生命周期随JVM 的销毁而结束, 在多例情况下,每一实例都要保存一份缓存, 会有缓存不一致的现象. 
  • 分布式缓存  : 相比于多实例情况, 各实例共享一份缓存数据, 数据具有一致性.  缺点是: 架构复杂.

3. Redis 为什么快:

  • 完全基于内存, 绝大部分的请求是内存操作, (少部分需要去硬盘上读取), 像Hashmap 的查抄和操作的时间复杂度都是O(1).
  • 数据结构简单, 对数据操作简单
  • 采用单线程,避免了不必要的切换和竞争, 也不存在多线程的切换而消耗CPU, 就也不用考虑锁的添加、释放和死锁导致的性能消耗
  • 使用了多路IO 复用模型, 非阻塞IO
  • 使用的底层模型不同, Redis 直接自己构建了VM 机制, 避免了底层实现方式以及客户端之间通信应用协议不一样的问题.

 

4.Redis 和其key-value 相比, 有什么特殊的?

  • Redis 提供了原子性操作
  • Redis 运行在内存中但是可以持久化到磁盘所以在对不同数据集进行高速读写时 需要权衡内存,因为数据量不能大于硬件内存.「在内存中的操作简单.」

  • Redis 支持数据的备份,即 master-slave 模式的数据备份。

  • Redis 不仅仅支持简单的 key-value 类型的数据String ,同时还提供 list,set,zset, hash 等数据结构的存储。

5. Resid 优缺点 : 

优点 :

  • 读写速度快. 读的速度是 11 0000次/s ; 写的速度是 81000次/s. 

    • 因为数据存在内存中,类似于 HashMap,HashMap 的优势就是查 找和操作的时间复杂度都是 O1)
  • 支持事务
  • 支持数据持久化. 支持 AOF 和 RDB 两种持久化方式.
  • 支持多种数据结构. 其中value类型包括: String; hash; set;zset; list;
  • 支持主从复制, 住机会自动将数据同步到从机,可以进行读写分离.
  • 可用于缓存,可以按 key 设置过期时间,过期后将会自动删除

缺点:

  • 只能根据K查V,无法根据V查K
  • 查询方式单一,只有KV的方式,不支持条件查询,多条件查询唯一的做法就是数据冗余,但这会极大的浪费存储空间
  • 受限于数据库容量(受到物理内存的限制), 不能用作海量数据的高性能读写, 只能用在较小数据量的高性能操作和运算.
  • Redis 不能自动容错,不具备自动恢复功能.主从机宕机的话都会导致前端部分读写请求失败, 解决办法: 只能等待及其重启或者手动切换前端ip.
  • 宕机之后可能会发生数据不一致的问题. 造成可用性差. 如果在宕机前数据没能从主机传到从机,qiehuanIP后数据就不一致了
  • Redis 不好在线扩容. 所以在使用时要留有足够大的空间, 会造成资源浪费.


3. Redis 中key-value中value 的5 种数据类型

数据类型 可存储的值 可进行的操作 应用场景
String 字符串、整数、浮点数

对字符串字符串的一部分操作,

对整数和浮点数自增自减操作,

简单的键值对缓存
List 列表 从两端压入或弹出的元素,对单个或者多个元素进行修剪, 只保留一个范围内的元素 存储一些列表型数据结构,类似微博里的粉丝列表、文章评论列表的数据
Hash 包含键值对的无序散列表

添加、获取、一处单个简直对;获取所有键值对,

检查某个键是否存在

结构化的数据,比如一个对象的所有信息
Set 无序集合 添加、获取、移除单个元素, 检查一个元素是否存在于集合中.计算交集、并集、差集, 从集合里面随机获取元素 交集: 比如找共同好友
ZSet 有序集合 添加、获取、删除元素,根据分支范围或者成员来获取元素, 计算一个键的排名

去重,可排序

1. 在项目中的应用场景

source :  https://blog.csdn.net/weixin_39930252/article/details/111715945

1、缓存数据

最常用,对经常需要查询且变动不是很频繁的数据 常称作热点数据。

2、消息队列

相当于消息订阅系统,比如ActiveMQ、RocketMQ。如果对数据有较高一致性要求时,还是建议使用MQ)

3、计数器

比如统计点击率、点赞率,redis具有原子性,可以避免并发问题

4、电商网站信息

大型电商平台初始化页面数据的缓存。比如去哪儿网购买机票的时候首页的价格和你点进去的价格会有差异。

5、热点数据

比如新闻网站实时热点、微博热搜等,需要频繁更新。总数据量比较大的时候直接从数据库查询会影响性能
 


4. 数据的一致性问题、删除策略

1.如何让保证缓存数据的一致性问题?

source : 高并发问题 - 如何解决Redis缓存和MySQL数据一致性的问题 - MSJ521 - 博客园

缓存和数据库一致性解决方案: 

1.第一种方案:采用延时双删策略

2.具体的步骤就是:先删除缓存、再写数据库、休眠500毫秒、再次删除缓存;

休眠500毫秒问题 : 要评估自己的项目的读数据业务逻辑的耗时。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。当然这种策略还要考虑redis和数据库主从同步的耗时。最后的的写数据的休眠时间:则在读数据业务逻辑的耗时基础上,加几百ms即可。

3.设置缓存过期时间

从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。所有的写操作以数据库为准,只要到达缓存过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。

4.该方案的弊端

结合双删策略+缓存超时设置,这样最差的情况就是在超时时间内数据存在不一致,而且又增加了写请求的耗时。

1.第二种方案:异步更新缓存(基于订阅binlog的同步机制)

1.技术整体思路:MySQL binlog增量订阅消费+消息队列+增量数据更新到redis

1)读Redis:热数据基本都在Redis

2)写MySQL: 增删改 都是操作MySQL

3)更新Redis数据:MySQ的数据操作binlog,来更新到Redis

2.Redis更新

        1)数据操作主要分为两大块:

                一个是全量(将全部数据一次写入到redis)

               一个是增量(实时更新)

               这里说的是增量,指的是mysql的update、insert、delate变更数据。

        2)读取binlog后分析 ,利用消息队列,推送更新各台的redis缓存数据。

这样一旦MySQL中产生了新的写入、更新、删除等操作,就可以把binlog相关的消息推送至Redis,Redis再根据binlog中的记录,对Redis进行更新。

其实这种机制,很类似MySQL的主从备份机制,因为MySQL的主备也是通过binlog来实现的数据一致性。

这里可以结合使用canal(阿里的一款开源框架),通过该框架可以对MySQL的binlog进行订阅,而canal正是模仿了mysql的slave数据库的备份请求,使得Redis的数据更新达到了相同的效果。

当然,这里的消息推送工具也可以采用别的第三方:kafka、rabbitMQ等来实现推送更新Redis。

================================================================

2. Redis 中查询的数据怎么保证数据查询的一致性?

source : Redis中如何保证数据库和缓存双写时的数据的一致性? - King-D - 博客园

1.“缓存+数据库” 必须保持一致性采用读请求和写请求串行化串到一个内存队列的方案。

        串行化可以保证一定不会出现不一致的情况,但是它也会导致系统的吞吐量大幅度降低,用比正常情况下多几倍的机器去支撑线上的一个请求。

2. 最经典的缓存+数据库读写的模式,就是 Cache Aside Pattern

        的时候,先读缓存,缓存没有的话,再读数据库,取出数据后放入缓存,同时返回响应。

        更新时候,先更新数据库,然后再删除缓存

================================================================

3. 为什么是删除缓存,而不是更新缓存?

        很多时候,在复杂点的缓存场景,缓存不单单是数据库中直接取出来的值。而是需要进行运算后才能缓存出最新的值.

        还有就是, 如果每次更新数据库都更新缓存的话, 都更新缓存, 这里涉及到一个问题就是 更新在缓存中的数据是不是热数据.

        删除缓存,而非更新缓存,用的是懒计算思想.这样开销大幅降低, 当用到缓存才去算缓存。

================================================================

source :如何保证缓存(redis)与数据库(MySQL)的一致性-阿里云开发者社区

4. 数据不一致 * 简单情况 : 为什么先删缓存, 再更新数据库?

问题:先更新数据库,再删除缓存。如果删除缓存失败了,那么会导致数据库中是新数据,缓存中是旧数据,数据就出现了不一致。

解决思路:先删除缓存,再更新数据库。如果数据库更新失败了,那么数据库中是旧数据,缓存中是空的,那么数据不会不一致。因为读的时候缓存没有,所以去读了数据库中的旧数据,然后更新到缓存中。

采用 cache aside pattern 并发更新操作的时候可以先删除缓存,然后更新数据库。

此方案下的更新操作情况:

  1. 删除缓存失败,那么不会去执行update操作。

  2. 删除缓存成功,update失败,读请求还是会将旧值写回到redis中。

  3. 删除缓存成功,update成功,读请求会将新值写回到redis中。

================================================================

5. 数据不一致 * 复杂情况: 数据变更--> 删了缓存-->修改数据库之前有了请求...

问题描述 : 数据发生了变更,先删除了缓存,然后要去修改数据库,此时还没修改。一个请求过来,去读缓存,发现缓存空了,去查询数据库,查到了修改前的旧数据,放到了缓存中。随后数据变更的程序完成了数据库的修改。完了,数据库和缓存中的数据不一样了...

解决方案 : 这种情况应该采用异步读写请求队列去解决,简言之就是: update请求入队列,读请求入队列,update操作未执行完之前,读操作被阻塞,但是读操作需要while循环 一段时间,因为一旦当前操作的读请求之前还有一个读请求在队列中,很可能前一个读请求已经将update后的新值已经读取到redis当中了。

6. 单节点下:  ✅先删缓存 后更新库 与 ❌先更新库 后删缓存 对比

单节点: 不涉及主从复制的这种情况

  • 先删缓存,再更新数据库:

  采用同步更新缓存的策略,可能会导致数据长时间不一致,如果用延迟双删来优化,还需要考虑究竟需要延时多长时间的问题——读的效率较高,但数据的一致性需要靠其它手段来保证
  采用异步更新缓存的策略,不会导致数据不一致,但在数据库更新完成之前,都需要到数据库层面去读取数据,读的效率不太好——保证了数据的一致性,适用于对一致性要求高的业务

  • 先更新数据库,再删缓存:

  无论是同步/异步更新缓存,都不会导致数据的最终不一致,在更新数据库期间,缓存中的旧数据会被读取,可能会有一段时间的数据不一致,但读的效率很好——保证了数据读取的效率,如果业务对一致性要求不是很高,这种方案最合适


7. key 过期的删除策略

缓存中某些数据不再是热数据时, 可以通过删除 key-value 中的key 来减轻内存压力.

1. 惰性过期只有在访问key 时才去判断 这个key 是否过期, 过期则删除.

        会减轻CPU 的压力, 但是会增大内存压力. [如果好多key 不再被访问了,但也会一直占用内存]

2. 定时过期为每个key 设置定时器,到期就立即删除.

        对内存很友好; 但会占用大量的CPU资源去处理过期的数据,会影响到 : 缓存的响应时间 & 吞吐量。

3. 定期过期 : 每隔一定时间, 扫描一定数量的key ,如果过期,则删除. [是惰性过期和定时过期的折中]

        可设置每次扫描的时间间隔 & 每次扫描的限定耗时.

所以, 定期过期是一个平衡、折中方案. Redis 同时使用了这两种策略.

定时清理  缺点: 维护大量缓存的key是比较麻烦的,

惰性清理  缺点: 每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!

7. Redis key的过期时间和永久有效分别怎么设置?

     Expire 和 Persist 命令。

8. 有大量的 key 需要设置同一时间过期,需要注意 什么?

        如果大量的 key 过期时间设置的过于集中,到过期的那个时间点,redis 可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一 些。


5. 内存相关

1. MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据

redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略

2. Redis的[ 内存淘汰策略/回收策略 ]有哪些?  ----  6 种..

source : Redis数据淘汰策略_ThinkWon的博客-CSDN博客

Redis的内存淘汰策略是指 : 在Redis用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。

全局的 键空间选择性移除

  • no-eviction:当内存不足以容纳新写入数据时,新写入操作会报错。禁止清楚数据

  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。(这个是最常用的)

  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。

设置过期时间的键空间选择性移除

  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key

  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。

  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

使用规则 

1、如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率 低,则使用 allkeys-lru

2、如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用 allkeys-random

总结

Redis的内存淘汰策略的选取并不会影响过期的key的处理。

内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;

过期策略用于处理过期的缓存数据。

3. Redis主要消耗什么物理资源? 

内存。

3.Redis集群最大节点个数是多少?

16384个

3.一个字符串类型的值能存储最大容量是多少?

512M

4.为什么 Redis 需要把所有数据放到内存中?

        Redis 为了达到最快的读写速度将数据都读到内存中,并通过 异步 的方式将数据写入磁盘。所以 redis 具有快速和数据持久化的特征。如果不将数据放在内存中, 磁盘 I/O 速度会严重影响 redis 的性能。

5. Redis的内存用完了会发生什么?

如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回。)

或者可以配置内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。

6. Redis如何做内存优化?

可以好好利用Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的Key-Value可以用更紧凑的方式存放到一起。

尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,尽可能的将数据模型抽象到一个散列表中.

比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面


6.  Redis 单线程快的原因?

  • 作者:xu-ning
  • 原文链接:https://blog.csdn.net/tsundere_ning/article/details/119904844
    更新时间:2023年1月29日08:56:45 ,共 11324 字。