Redis面试题 (2023最新版)

文章目录

一、Redis为什么快?

1、基于内存

内存读写效率远高于磁盘读写,省去磁盘IO操作

2、 存储形式

Redis作为K-V键值对型的内存数据库,所有键值都是用字典来存储,即哈希表结构。哈希表的特性就有在O(1)时间复杂度就可以获取对应的值。

3、 编码

支持多种数据结构及编码,针对不通业务场景,都有相对应的数据结构和编码。

根据元素的数量,有一个阈值,小于阈值和大于阈值的编码不同。

4 IO多路复用

核心思想:让单个线程去监视多个连接,某个连接就绪,就触发读写事件。即可以单个线程处理多个客户端连接,无需创建和维护过多的进程和线程。

5、单线程,避免上下文切换

内部执行命令为单线程,避免上下文切换带来的CPU开销

6、渐进式ReHash、缓存时间戳

(1)渐进式ReHash:

Redis使用全局哈希表来保存所有键值对,

哈希表相当于一个数组,数组的每个元素称为一个哈系桶,每个哈系桶中保存了键值对的数据。

在这里插入图片描述

数据增加到一定阈值,数组扩容会导致数据发生移动,此时访问会发生阻塞

渐进式ReHash:把一次性大量拷贝(数组移动)的开销,分摊到多次处理请求的过程中。

Redis默认使用两种全局哈希表,开始插入数据时默认使用哈希表1,此时哈希表2并没有被分配空间。随着数据逐步增多,开始执行ReHash。

  1. 给哈希表2分配更大的空间,
  2. 将哈希表1中的数据重新映射并拷贝到哈希表2中
  3. 释放哈希表1的空间

在这里插入图片描述

7、缓存时间戳:

业务中需要用到时间戳时,一般会使用System.currentTimeMillis()或者New Date()等方式获取系统的毫秒时间戳,每一次获取都是一次系统调用(需要调用操作系统中对应的函数,涉及上下文切换),相对比较耗时。

作为单线程的Redis承受不起,因此它由一个定时任务,每毫秒更新一次缓存,获取时间都是从缓存中直接拿。

二、Redis合适的应用场景

常用基本数据类型(5种)

名称英文名作用域
字符串String缓存、计数器、分布式Session
哈希Hash存放对象
列表list消息队列、文章列表
集合set标签、随机数、社交图谱
有序集合ZSET排行榜
BitmapsBitmaps布隆过滤器
HyperLogLogHyperLogLogUV
GeoGeoRedis3.2推出的,地理位置定位,用于存储地理位置信息,并对存储的信息进行操作

1、字符串(String)

命令的时间复杂度:

字符串这些命令中除了del、mset、mget支持多个键的批量操作,时间复杂度和键的个数相关,为O(n),getrange的字符串长度相关,也是O(n),其余的命令基本上都是O(1)的时间复杂度,在速度上还是非常快的。

(1)缓存

具有支撑高并发的特性,能起到加速读写的作用,降低后端压力

(2)计数器

实现快速计数、查询缓存的功能,同时数据可以异步落地到其他数据源

(3)分布式会话(共享Session)

问题:如果一个分布式Web服务将用户的Session信息保存在各自服务器中,出于负载均衡的考虑,分布式服务会将用户的访问均衡到不同服务器上,用户刷新一次访问,可能会发现需要重新登录。

解决方案:使用Redis将用户的Session进行集中管理,这种情况下只要保证Redis是高可用和扩展性的,每次用户更新或查询登录信息都直接从Redis集中获取。

(4)分布式锁

场景:同一个资源并发访问,如秒杀、下单减库存等场景。适用String数据类型。

  • synchronize和reentrantlock本地锁性能较低
  • 并发量不大,可以使用数据库悲观锁,但并发量大的场景会降抵DB性能
  • 可以使用Redis Setnx来实现分布式锁

2、哈希(Hash)

适用于存放对象,相较于String类型存储对象时效率开发效率更高。

3、列表(list)

用来存储多个有序字符串

(1)消息队列

lpush+brpop命令组合即可实现阻塞队列,生产环境客户端使用lpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式的”抢“列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性。

(2)文章列表

每个用户有属于自己的文章列表,现需要分页展示文章列表。此时可以考虑使用列表,有序,且支持按照索引范围获取元素

还可实现其他数据结构

4、集合(set)

(1)标签(tag)

例如一个用户可能对娱乐、体育感兴趣,另一个用户可能对历史、新闻感兴趣,这些兴趣点就是标签。通过这些数据可以得到喜欢同一个标签的人,这些数据对于用户体验以及增强用户粘度比较重要。

(2)随机数(抽奖活动)
(3)社交网络

点赞、粉丝、共同好友、喜好、推送、下拉刷新等功能。适用String数据类型和hash类型,存放对象使用hash类型。

标签适用于set数据类型,例如一个用户可能对娱乐、体育感兴趣,另一个用户可能对历史、新闻感兴趣,这些兴趣点就是标签。通过这些数据可以得到喜欢同一个标签的人,这些数据对于用户体验以及增强用户粘度比较重要。

排行榜适用于有序集合(ZSET)数据类型。

5、有序集合(ZSET)

(1)排行榜

多维度:时间、浏览量、获赞数等等。

Redis高级数据结构

6、Bitmaps

可以实现对位的操作,单独提供了一套命令,可以想象成以位为单位的数组,数组下标叫做偏移量。

用于数据量上亿的场景下,例如几亿用户系统签到,去重登录次数统计,某用户是否在线状态等。此时不可能给每个用户一个key。

这里需要用到位操作,使用setbit、getbit、bitcount命令。

原理:redis内构一个足够长的数组,每个数组只能是0和1两个值,数组下标表示用户id,这个几亿长的大数组就可以通过下标和元素值(0和1)来构建一个记忆系统。

在这里插入图片描述

(1)布隆过滤器

在这里插入图片描述

7、HyperLogLog

(1)UV

统计每个网页每天的UC数据,HyperLogLog提供不精确的去重计数方案,误差0.81%

在这里插入图片描述

三、Redis为什么6.0之前不支持多线程

1、Redis的瓶颈不是CPU,受制于内存、网络

存储于内存,快速读写网络开销大

2、提高Redis性能,Pipeline(命令批量)

每秒100万个请求包装进Pipeline

3、单线程,内部维护成本相对较低,不需要管理多线程安全

命令执行顺序不确定性,读写并发问题

4、多线程(线程切换、加锁/解锁、导致死锁问题)

5、惰性Rehash(渐进式)减少阻塞

一般的公司,单线程Redis就够了。

四、Redis为什么6.0之后引入多线程

1、小数据包。数据-》内存 响应时间 100ns 8w-10wQPS(极限)

2、针对大的公司,需要更大的QPS,IO的多线程(内部执行命令还是单线程)

3、为什么不采用分布式架构—很大的缺点。

服务器数量多,维护成本高。Redis命令 不适用 需要数据分区,无法解决热点数据读写的问题。

数据倾斜、重新分配、扩容、缩容,更加复杂。

本质:多线程任务 分摊到Redis 同步IO中,读写负载。

五、Redis有哪些高级功能

(1)慢查询

快速定位系统中的慢操作,监测发生时间、耗时、命令的详细信息。

(2)Pipeline

在这里插入图片描述

(3)watch命令:

确保事务中的key有没有被其他客户端修改过,才执行事务,否则不执行(类似于乐观锁)。

(4)Redis+Lua语言实现限流

在这里插入图片描述

(5)分布式锁

首先需要Redis有互斥的能力,可以使用SETNX命令,(即如果key不存在,才会设置它的值,否则什么也不做。两个客户端进程可以执行这个命令,达到互斥,就可以实现一个分布式锁。

锁的过期时间不好计算

在这里插入图片描述

解决方案:分布式锁加入看门狗

加锁时,先设置一个过期时间,然后开启**“守护线程”**,定时检测这个锁的失效时间,如果快要过期了,操作共享资源还未完成,则自动对锁进行续期,重新设置过期时间。

(6)高并发高可用

主从复制:

提供了复制功能,实现了相同数据的多个Redis副本。每个主节点可以对应多个从节点,复制的数据流只能由主节点复制到从节点。

在这里插入图片描述
在这里插入图片描述

(7)哨兵:Redis Sentinel

背景:主从复制模式下,主节点故障,需要人工将从节点晋升为主节点。

2,8版本开始提供哨兵架构解决此问题。

主从复制的问题
  • 需要手动晋升子节点,同时需要修改应用方的节点地址。
  • 主节点的写能力收到单机限制
  • 主节点的存储能力收到单机的限制

六、为什么需要使用Redis

1、高性能

Mysql(磁盘)毫秒级

Redis(内存)微秒级

更新策略:项目启动时全量同步:热点数据

2、高并发

Mysql 并发量:1000/s

Redis 并发量:100000/s

集群架构

在这里插入图片描述

七、Redis的事务

本质:按照顺序串行化执行队列中的每个命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。

顺序性、一次性、排他性执行一个队列中的一系列命令。

命令描述
EXEC执行所有事务块命令
DISCARD取消事务,放弃执行事务块所有命令
MULTI标记一个事务块,开启事务
UNWATCH取消WATCH命令对所有key的监视
WATCH监视key,如果在事务执行之前,该key被其他命令改动,那么事务将被打断
        //构建redis连接
        Jedis jedis = jedisPool.getResource();
        //标记一个事务块,开启事务
        Transaction transaction = jedis.multi();
        try {
            transaction.set("name1","江先进");
//            int n = 10/0;
            transaction.set("name2","张硕");
            //执行事务
            transaction.exec();
        }catch (Exception e){
            //取消事务
            transaction.discard();
            e.printStackTrace();
        }

在这里插入图片描述

回滚机制上,Redis只能对基本语法错误进行判断。运行时错误无法回滚。

八、Redis的过期策略以及内存淘汰机制

1、内存淘汰机制

  • 定期删除(定时扫描策略)

    设置了过期时间的key放入独立字典,Redis默认会每秒进行十次过期扫描,不会遍历Key,而是采用简单的贪心策略。

    1. 从过期字典中随机20个key;
    2. 删除其中已经过期的;
    3. 如果过期比例超过1/4,则重复真个步骤;

    一定要注意过期时间,如果大批量key过期(雪崩),需要给过期时间设置一个时间范围,不能全部同一时间过期

  • 惰性删除

    客户端访问key的时候,redis对key的过期时间进行检查,如果过期就立即删除,不会返回任何东西。

总结:定期删除是集中处理,惰性删除是零散处理。

2、过期策略

  • 定时过期:每个设置过期时间的key都需要创建一个定时器,到期清除key。该策略会立即清除过期的数据,对内存友好,但是会占用大量CPU去处理过期数据,影响吞吐量
  • 惰性过期:只有访问一个key时,才会判断是否已过期,过期则清除。最大化节省CPU资源,对内存不友好。可能会导致大量过期的key因未被访问而无法清除。
  • 定期过期:每隔一定时间,扫描一定数量的key,并删除其中过期的,通过调整定时扫描的时间间隔和扫描限定耗时,使CPU和内存达到一个最佳平衡状态。

Redis中同时使用了惰性过期和定期过期两种策略。

每隔100ms就随机抽取一定量key,检查和删除。同时获取key时,会检查一下是否过期,过期则删除。

隐患:同样可能定期删除,漏删了大量过期key,也没有走惰性删除,就会导致大量过期key堆积在内存。

3、缓存淘汰算法

Redis 缓存淘汰算法用于在内存资源不足时,决定哪些数据需要从缓存中移除。Redis 提供了多种策略以应对不同的应用场景:

  1. volatile-lru(LRU for volatile keys):

    • 当内存不足以容纳新写入的数据时,会优先剔除已设置过期时间的键值对,并根据LRU原则删除最近最少使用的数据。
  2. allkeys-lru

    • 不区分是否设置了过期时间,所有键都会根据LRU规则淘汰,即删除最近最少使用的数据。
  3. volatile-ttl

    • 同样针对设置了过期时间的键,但淘汰时不是基于访问频率而是基于键的剩余存活时间(TTL),选择TTL最短的键进行淘汰。
  4. noeviction

    • 不进行任何数据淘汰,当内存满时,执行可能导致占用更多内存的命令将返回错误。
  5. allkeys-random

    • 随机淘汰任意键,不论其是否被频繁使用或何时到期。
  6. volatile-random

    • 淘汰一个随机的已设置过期时间的键。

值得注意的是,Redis 实现的 LRU 算法并不是精确的 LRU,因为为了性能考虑,它并没有真正维护一个完整的 LRU 链表结构。Redis 采用了一种近似 LRU 的实现方法:通过为每个键维护一个 lru 字段来记录最后一次访问的时间戳,在内存不足时,Redis 会选择一定数量(比如 5 个)的候选键,然后比较这些候选键的 lru 值,选择其中最小的一个进行淘汰。这样可以降低维护 LRU 数据结构的成本,同时在大部分情况下能够达到类似 LRU 的效果。

九、什么是缓存穿透?如何避免?

本质:数据库和Redis都不存在

场景:查询id为-1的数据

坏处:每次都需要查询数据库和redis,增加磁盘IO的压力

解决方案

  1. 参数校验、屏蔽非法参数
  2. 数据库查询为空,可以给缓存一个空值或默认值,防止第二次再去数据库
  3. 使用布隆过滤器快速判断数据是否存在,将所有可能存在的数据哈希存到一个足够大的容器中,不存在的数据被这个bitmap拦截掉

布隆过滤器的应用:

在这里插入图片描述

在这里插入图片描述

十、什么是缓存雪崩?如何避免?

本质:数据库和Redis都存在,但redis都过期了

同一时间,缓存大面积失效,大量请求都直接去访问数据库

原因:

1、Redis失效、宕机(故障)
  • 搭建Redis集群,主从架构
  • RDB持久化、IOF持久化
  • 加入缓存组件:EHCache,搭建多级缓存(容易高并发的数据存入)
  • 加入限流组件:hystrix,超过一定流量后,增加请求限制(保护数据处理层)
2、Redis大量key的ttl过期
  • ttl(过期时间)岔开,增加随机值,避免同一时间全部失效。

在这里插入图片描述

解决方案

  1. 热点数据永不过期,或者通过异步线程在每次热点数据快要过期时,进行续期
  2. 数据的过期时间不要全一致,设为一定范围内的随机时间
  3. 并发量不高,可加入队列或者锁,限制同一时间访问数据库的阈值
  4. 分布式部署,将热点数据打散分不到多个节点
  5. 如果是缓存中间件宕机了,需要尽可能保证其高可用性,可以搭建redis集群,提前做好报警机制

十一、缓存击穿

本质:单个key没有或过期,同一时间查询这同一条数据并发量过多

解决方案

  1. 热点数据用不过期,或者通过异步线程在每次热点数据快要过期时,进行续期
  2. 使用互斥锁,避免大量请求同时查询数据库
  3. 熔断、降级、防止系统崩溃
  4. 还可以考虑对重要的热点数据进行多级缓存

十二、Redis如何设计分布式锁

概念

  • 锁:同一时间只允许一个线程或者一个应用程序进入执行
  • 分布式锁:必须要求Redis有【互斥】能力,可以使用SETNX命令:即key不存在了才会设置它的值,否则什么也不做。

注意事项

  1. 如果过期时间是每个服务自己生成,需要保证每个客户端时间同步。
  2. 必须保存持有者唯一标识,否则可能被别的客户端释放/解锁。
  3. 给锁设置过期时间,以免进程挂了或异常了无法释放锁。
  4. 加入看门狗:开启守护线程,定期检测锁的失效时间,如果快过期了,业务还没有执行完,则续期。

看门狗:开源框架Redisson,只要线程一个线程加锁成功,就会启动一个watch dog,每隔10秒检查一下锁是否释放,只要第一个线程还持有锁,就延长锁的失效时间,解决了锁过期但业务还没执行完的问题。

十三、什么是bigkey?会有什么影响?

1、概念:

key对应的value所占内存空间较大

例如一个字符串类型的value最大存到512M,一个列表类型的value最大可以存储2的32次方-1个元素。

2、字符串类型:

体现在单个value值特别大,一般认为超过10kb就是bigkey,和具体OPS相关(不同系统不同并发)。

3、非字符串类型:

哈希、列表、集合、有序集合,体现在元素个数过多。

4、危害:
  • 内存空间不均匀

  • 超时堵塞:单线程操作bigkey比较耗时

  • 网络拥塞:每次获取bigkey产生的网络流量较大

    例如:一个bigkey为1MB,每秒访问为1000,则每秒产生1000MB的流量,普通千兆网(按照字节算是128MB/s)的服务器是灭顶之灾,而且服务器通常会采用单机多实例的方式来部署,可能会对其他实例造成影响。

5、解决方案:value拆分

十四、Redis如何解决key冲突

1、业务隔离

2、key的设计

业务模块+系统名称+关键(id),针对用户可以加入(userid)

3、分布式锁

场景:多个客户端并发写key

客户端拿到锁,才能进行操作,避免多个客户端竞争该key

4、时间戳

key拼接时间戳,根据时间戳保证多个客户端的业务执行顺序

十五、怎么提高换成命中率

1、提前加载

2、增加缓存的存储空间,增加缓存的数据

3、调整缓存的存储类型

例:对象通过Hash存储,而不用String。

根据业务做适当调整。

4、调整缓存的存储类型

  • 定时任务更新
  • MySQL通过检测binlog,将消息推送到Redis,更新缓存
  • 通过Mq,业务更新修改数据时,通过MQ发送消息,消费更新缓存

十六、Redis持久化方式有哪些方式?有什么区别?

16.1 持久化

将数据写入磁盘,避免因进程退出而造成的数据丢失,下次重启时通过持久化文件恢复数据。

16.2 RDB

通过快照(内存中数据在某一时刻的状态记录)的方式实现持久化,根据快照的触发条件,将内存的数据快照写入磁盘,以二进制的压缩文件进行存储。

缺点:每隔一段时间触发持久化,数据安全性低。

16.3 AOF

以独立日志的方式记录每次写的命令,重启时重新执行AOF文件中的命令恢复数据

AOF重写机制:AOF文件的大小达到某个阈值时,会将其中指令进行压缩。(如果有对于某个key多次的变更指令,则仅保留最新的数据指令)。

优化

  • 因为AOF重写过程中需要读取当前内存中所有键值数据,性能较低,redis将其放在一个后台子线程中完成。
  • 为了避免重写过程中出现数据变动,主进程的数据变更需要追加到AOF重写缓冲区中,等到AOF重写完成后,再把AOF重写换乘区里面的内容追加到新的AOF文件中。

缺点:AOF文件可能过大,性能较差

4、混合式

如果执行bgrewriteaof命令,将内存中已有的数据以二进制格式存放在AOF文件中(模拟RDB),后续命令亦然采用AOF追加方式。

生产环境中一般采用两种持久化机制混合使用。

将内存中数据快照存储在AOF文件中(模拟RDB),后续再以AOF追加方式。

如果仅作为缓存使用,可以承受几分钟数据丢失,可以使用RDB,对主程序性能影响最小。

在这里插入图片描述

十七、为什么Redis需要把所有数据放到内存中?

1、内存访问与磁盘访问的差距:

在这里插入图片描述

  • 几乎是10倍以上,如果不是顺序读取而是随机读取效率会相差更大
  • 同时还有CPU上下文切换的开销
2、Redis通过异步,持久化将数据写入磁盘
3、随着技术的发展,硬件上来说内存也越来越便宜了
4、默认情况下,哪怕Redis内存不够了,也不会发生宕机,而是只可读不能写(Noeviction策略)
5、通过内存淘汰策略,确保整体服务正常运行

十八、如何保证缓存与数据库双写一致性?

1、新增数据类

新增数据时,数据会直接写入数据库,不用对缓存做任何操作;此时缓存没有新增数据,而数据库中是最新值。

2、更新缓存类
(1)先更新缓存,在更新DB(一般不考虑)

原因:缓存更新成功,更新数据库时出现异常,会导致数据源与缓存数据完全不一致,而且很难察觉,因为缓存中的数据一直都存在。

(2)先更新DB,在更新缓存(一般不考虑)

原因:数据库更新成功了,缓存更新失败了,同样会导致数据源与缓存数据完全不一致,也很难察觉。

3、删除缓存
(3)先删除缓存,后更新DB
问题:

两个请求:A(更新)和B(查询)

A -> 删除缓存中的数据 -> 更新数据库

B -> 查询缓存为空 -> 查询数据库 -> 补录到缓存

A -> 还未更新成功/事务还未提交,B -> 查询到的其实是数据库旧值

解决方案:
  • 先淘汰缓存
  • 再写数据库
  • 休眠1秒,再次淘汰缓存

这个休眠的时间需要评估项目的读数据业务逻辑的耗时,确保请求结束时,写请求可以删除读请求造成的缓存脏数据。

(4)先更新DB,后删除缓存

查询:先读缓存 -> 缓存没有就读数据库 -> 取出数据放入缓存 -> 同时返回响应。

更新:先更新数据库 -> 删除缓存

4、如何选择

一般线上更多偏向于删除缓存类操作(容易避免问题)

原因:

  • 删除缓存比在DB中要快,所以一般先更新DB,后删除缓存
  • 问题只会出现在查询比删除慢的情况,出现率相对最少
  • 同时延迟双删可以有效避免缓存不一致情况。

在这里插入图片描述

伪代码实现延迟双删:
redis.deykey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)
5、读取binlog日志

异步删除、更新缓存,

  • 可以使用canal将binlog日志采集发送到MQ队列中。
  • 通过ACK机制确认处理这条更新消息,删除缓存,保证数据一致性。

十九、Redis集群方案

1、分布式解决方案 :Redis Cluster

3.0版本推出

场景:单机内存、并发、流量等瓶颈

方案:
(1)客户端分区:

优点:分区逻辑可控

缺点:需要处理数据路由、高可用、故障转移等问题

(2)代理方案:

优点:简化客户端分布式逻辑,升级维护便利

缺点:加重架构部署复杂度和性能损耗

2、虚拟槽分区(0~16383)

在这里插入图片描述

主节点数量基本不可能超过1000个,节点连接需要不断发送ping/pong命令,消耗网络带宽

3、集群功能限制

(1)key批量操作支持有限:mset、mget仅支持相同slot值的key。

(2)key事务操作支持有限:仅支持在同一节点上的事务操作。

(3)key作为数据分区的最小颗粒度,不允许大的键值对(hash、list)映射在不同节点。

(4)不支持多数据库空间。单机为0-15(16个),集群模式仅能使用db0。

(5)复制结构仅支持一层,节点只能复制到主节点,不支持嵌套树状复制结构。

4、搭建集群

方式:

(1)Redis协议手工搭建。

(2)5.0之前有ruby语言脚本搭建。

(3)5.0之后搭建功能合并至redis-cli。

节点数至少奇数点个,官方推荐三主三从。

二十、Redis集群方案什么情况下会导致整个集群不可用?

A、B、C三个节点集群,B节点失败(主故障,且没有替代方案)整个集群都是不可用的。

集群不可用判定:

保护措施:默认情况下当16384个槽点任何一个没有指派到节点时,整个集群不可用。

主节点下线->故障发现->自动完成转移期间,整个集群为不可用状态。

可用通过设置cluster-require-full-coverage配置为no:主节点故障时,不影响其他主节点的可用性。

二十一、Redis集群会有写操作丢失吗?为什么?

Redis无法保证数据的强一致性

一般只能向主节点写入数据,再异步同步到子节点

此时如果响应给客户端后还未异步同步成功时,主节点宕机了,子节点升至主节点,此时就会出现写入操作丢失。

二十二、Redis常见性能问题和解决方案

1、持久化 性能问题

早期仅支持全量复制->部分复制(一台机器性能开销过大)

因此开始配置主从 :主节点不再做持久化而是交给从节点来做

2、数据比较重要,开启AOF。策略最好配置每秒同步。
3、主从复制 流畅,建议同一个局域网内操作,负责网络开销过大
4、尽量避免主库压力过大,增加从库
5、主从复制 尽量不要使用网状结构、线性结构

二十三、热点数据和冷数据

1、热数据

访问频次较高,考虑使用缓存Redis

地图信息

点赞数、收藏数、分享数(不断变化)同步Redis

数据更新之前至少读取2次才能放缓存

2、冷数据

访问频次少

不需要放缓存

二十四、什么情况下可能会导致Redis阻塞

1、客户端阻塞

命令执行时间过长: keys* Hgetall smembers 时间复杂度O(N)

2、BIGkey删除

需要释放大量占用内存 zset(100万的元素 删除大概需要2s)

3、清空库

flushdb flushall 涉及删除所有键值对

4、AOF日志同步写,记录AOF日志

大量写的操作

1一个同步写磁盘操作大概耗时1~2ms

5、从库 加载RDB文件

RDB文件过大

6、Redis尽量部署在独立的服务器中

二十五、线上Redis响应慢处理思路

  • 1、紧急处理方案,扩容

  • 2、生产环境查看Redis内存使用率,分析一定时间段内key数量变化

    分析是否是大量数据未设置过期时间,或者是因为新版本迭代引起

  • 3、清除bigkey,优化生成bigkey的代码块,调整未设置过期时间的代码块

  • 4、根据业务场景调整淘汰策略

二十六、 Redis 高可用

高可用:数据不能丢失(尽量减少丢失),保证Redis

26.1 主从模式

  • 部署多台Redis服务器,主从复制以保证数据副本一致。主库通过将RDB文件发送给从库实现复制。
  • 主从之间采用读写分离,主库写操作,从库仅负责读操作。
  • 主库如果宕机了,人工切换一台从库称为主库,通知应用方更新主节点地址。

问题:数据不一致。

原因:主从库网络延迟,从库接收到命令,但它正在执行阻塞性命令。

解决方法:保证网络通畅,监控主从库复制进度。

26.2 哨兵模式

Redis从2.8开始提供哨兵机制。

####26.2.1 作用

  • 监控:周期性ping主从库,检测是否挂了,标记下线状态。
  • 自动选主切换:多个从库中按照一定规则选一个作为主库。
  • 通知:选出主库后,将新主库的连接信息发送给其他从库以及应用方,重新建立联系。
26.2.2 哨兵

由一个或多个哨兵实例组成哨兵系统,监控其他Redis节点的同时,哨兵实例之间也互相监控。

哨兵之间通过发布订阅机制组成集群。一主多从

缺点:无法实现在线扩容,并发压力受限于单个服务器的资源配置。

26.3 Redis Cluster

哨兵模式解决了自动切换主从的问题,但是没有解决在线扩容的问题。

本质:Redis Cluster实现了Redis的分布式存储,每个节点存储不同的数据,实现数据分片。

引入Slot槽实现数据分片,每个节点分配一个Slot区间,当我们存取Key的时候,Redis根据key计算得到Slot值,找到对应的节点进行读写。多主多从。

二十七、布隆过滤器

布隆过滤器可以应对缓存穿透问题

数据结构:一个很长的二进制向量和一组Hash映射函数组成。

作用:检索一个元素是否在一个集合中,空间查询效率比一般的算法要好的多。

缺点:有一定误识别率和删除困难。

原理:集合A中有n个元素,利用K个哈希散列函数,将A中每个元素映射到一个长度为a位的数组B中不同位置上。这些位置上的二进制数均设置为1。经过这个K个哈希散列函数映射后,发现其k个位置上的二进制数全部为1,这个元素很可能属于集合A。

二十八、Redis的理解

本质:基于Key-Value存储结构的非关系型数据库

数据类型:提供5种基本数据类型,String、set、zset、list、Hash。

性能:基于内存存储,并且在数据结构上做了大量优化,IO性能较好。

作用:作为应用与数据库之间的分布式缓存组件。

高可用:提供了主从复制、哨兵、以及集群方式实现高可用,集群中通过hash槽的方式实现了数据分片,进一步提升了性能。

  • 52
    点赞
  • 632
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
1、什么是 Redis? 2、Redis 相比 memcached 有哪些优势? 3、Redis 支持哪几种数据类型? 4、Redis 主要消耗什么物理资源? 5、Redis 的全称是什么? 6、Redis 有哪几种数据淘汰策略? 7、Redis 官方为什么不提供 Windows 版本? 8、一个字符串类型的值能存储最大容量是多少? 9、为什么 Redis 需要把所有数据放到内存中? 10、Redis 集群方案应该怎么做?都有哪些方案? 11、Redis 集群方案什么情况下会导致整个集群不可用? 12、MySQL 里有 2000w 数据,Redis 中只存 20w 的数据, 如何保证 Redis 中的数据都是热点数据? 13、Redis 有哪些适合的场景? 14、Redis 支持的 Java 客户端都有哪些?官方推荐用哪个? 15、RedisRedisson 有什么关系? 16、Jedis 与 Redisson 对比有什么优缺点? 17、Redis 如何设置密码及验证密码? 18、说说 Redis 哈希槽的概念? 19、Redis 集群的主从复制模型是怎样的? 20、Redis 集群会有写操作丢失吗?为什么? 21、Redis 集群之间是如何复制的? 22、Redis 集群最大节点个数是多少? 23、Redis 集群如何选择数据库? 24、怎么测试 Redis 的连通性? 25、Redis 中的管道有什么用? 26、怎么理解 Redis 事务? 27、Redis 事务相关的命令有哪几个? 28、Redis key 的过期时间和永久有效分别怎么设置? 29、Redis 如何做内存优化? 30、Redis 回收进程如何工作的? 31、Redis 回收使用的是什么算法? 32、Redis 如何做大量数据插入? 33、为什么要做 Redis 分区? 34、你知道有哪些 Redis 分区实现方案? 35、Redis 分区有什么缺点? 36、Redis 持久化数据和缓存怎么做扩容? 37、分布式 Redis 是前期做还是后期规模上来了再做好?为 什么? 38、Twemproxy 是什么? 39、支持一致性哈希的客户端有哪些? 40、Redis 与其他 key-value 存储有什么不同? 41、Redis 的内存占用情况怎么样? 42、都有哪些办法可以降低 Redis 的内存使用情况呢? 43、查看 Redis 使用情况及状态信息用什么命令? 44、Redis 的内存用完了会发生什么? 45、Redis 是单线程的,如何提高多核 CPU 的利用率? 46、一个 Redis 实例最多能存放多少的 keys?List、Set、 Sorted Set 他们最多能存放多少元素? 47、Redis 常见性能问题和解决方案? 48、Redis 提供了哪几种持久化方式? 49、如何选择合适的持久化方式? 50、修改配置不重启 Redis 会实时生效吗?
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柚几哥哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值