Redis面试核心技术点和缓存相关问题

目录

Redis的数据结构和原理

Redis持久化:RDB和AOF

Redis的集群设计

缓存雪崩、击穿、穿透

高并发场景下缓存和数据库更新策略

Redis的大key和热key和大value

本地缓存


磁盘IO和网络开销 相比于 请求内存IO 要高上千倍,如果某个数据从数据库磁盘读出来需要 0.0045S,经过网络请求传输需要 0.0005S,那么每个请求完成最少需要 0.005S,该数据服务器每秒最多只能响应200 个请求。而如果该数据存于内存中,读出来只需要 100us,那么每秒能够响应 10000 个请求。这就是存储在硬盘的MySQL和存储在内存的Redis的差别。基于内存的缓存可以把系统响应能力提高 N 个数量级,远高于传统基于硬盘的关系型数据库。

Redis单线程有一个最大好处就是 节省线程切换的开销,更不用考虑并发读写带来的复杂操作场景,大大节省了线程间切换的时间。单线程模型避免了多线程的频繁上下文切换,这也避免了多线程可能产生的竞争问题。Reids 核心是基于非阻塞的 IO 多路复用机制。

Redis的数据结构和原理

Redis常用的5种数据结构如下,更多命令和使用场景请查看:Redis命令合集和设计场景_浮尘笔记的博客-CSDN博客

  • 字符串 String: 基础的数据存储类型,可存储文本、Json、图片数据等任何二进制文件。主要命令:set/get。
  • 列表 List: 按照插入顺序排序的字符串链表,在插入时如果key不存在会创建一个新的链表。主要命令:lpush/rpush/lpop/rpop。
  • 哈希 Hash: 适合存储键值对信息,比如一个用户的昵称、性别、年龄等属性可以存储为一个key。主要命令:hset/hget/hgetall/hmset/hdel。
  • 集合 Set: 无序集合,值不能重复。可以原来存储唯一IP、唯一用户ID 等信息。主要命令:sadd/smembers/srem。
  • 有序集合 Sorted Set: 支持从小到大排序的集合,适用于排行榜结构的数据存储。主要命令:zadd/zscore/zrange[withscores]。

Redis底层原理:Redis 使用C语言编写,其中String类型使用简单动态字符串(simple dynamic string,简称 SDS)实现,有一个专门用于保存字符串长度的变量,可以通过len属性的值获取字符串长度,从一定程度上提高了读取效率。Redis中字符串的定义如下:

struct sdshdr {int len; //记录 buf 中已经使用的空间长度int free; //记录 buf 中还空余的空间char buf[]; //记录字符串存储的内容
}

有序集合 Sorted Set 的内部使用 哈希表(HashMap) 和跳跃表 (SkipList)  来保证数据的存储和有序,HashMap 里放的是成员到 score 的映射,跳表里存放的是所有的成员,排序依据是HashMap 里存的 score,使用跳表的结构可以获得比较高的查找效率,并且在实现上比较简单。

【问】为什么 Redis 的使用跳表结构而不用红黑树?
【答】红黑树的查找效率很高,但是在进行重新平衡时会涉及到大量节点的变化,因此实现和操作起来都比较复杂。而跳表通过简单的多层索引结构,实现简单,且能达到近似于红黑树的查找效率,插入多层节点不需要像红黑树那样有额外操作;而且跳表还能实现范围查找及输出,而红黑树只支持单个元素查找,对于范围查找效率低。

关于Redis底层的更多细节请查看:Redis底层数据结构和原理_浮尘笔记的博客-CSDN博客

缓存的淘汰策略:缓存相比于磁盘更加昂贵,因此不能把所有数据都放入缓存,只能把最重要的或者要求查询速度最快的数据缓存起来,因此需要有一定的策略来让过期的缓存失效。常见的缓存淘汰策略有下面几个:

  • FIFO(First In First Out): 先进先出算法,先放入缓存的先被移除。
  • LRU(Least Recently Used): 最近最少使用算法,使用时间距离现在最久的那个被移除。
  • LFU(Least Frequently Used): 最不常用算法,一定时间段内使用次数(频率)最少的那个被移除。

Redis持久化:RDB和AOF

RDB 是 Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中,会在指定目录下生成一个 dump.rdb 文件。Redis 如果重启了,会通过加载 dump.rdb 文件恢复数据。可以使用 SAVE 和 BGSAVE 两个命令来生成 RDB 文件,SAVE是阻塞的,BGSAVE 是后台 fork 子进程进行,不会阻塞主进程处理命令请求。载入 RDB 文件不需要手工运行,而是 server 端自动进行。只要启动时检测到 RDB 文件存在,server 端便会载入 RDB 文件重建数据集。如果同时存在 AOF 的话会优先使用 AOF 重建数据集,因为其保存的数据更完整。

如果业务对数据完整性和一致性要求不高,RDB 的启动速度更快; RDB 的性能很好,需要持久化时,主进程会 fork 一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的 I/O 操作。缺点就是可能丢失间隔时间内的数据,而且RDB备份时会创建一个子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍),最后再将临时文件替换之前的备份文件。

AOF 默认不开启,它采用日志的形式记录每个写操作,生成一个 appendonly.aof 文件,并将日志追加到文件末尾。Redis 重启的时候会根据日志文件的内容,将写指令从前到后执行一次以完成数据的恢复工作,有点类似 MySQL 的 binlog。优点就是能最大限度地保证数据不丢失,数据的完整性和一致性更高。缺点就是AOF备份产生的 appendonly.aof 文件较大,数据恢复的时候也会比较慢,Redis 针对 AOF 文件大的问题,提供了重写的瘦身机制:可以通过bgrewiteaof手动触发,或者配置相关选项自动触发重写。

关于Redis持久化的更多内容请查看:redis笔记06-持久化rdb和aof

Redis的集群设计

稍微优点规模的项目,不管是用 MySQL还是 Redis,单机基本上扛不住,差不多都得使用集群了。Reids 官方给出了 Redis-cluster 方案,无中心架构,可线性扩展到 1000 个节点。

Redis Cluster 是官方在 Redis 3.0 版本正式推出的高可用以及分布式的解决方案,内置数据自动分片机制,由多个 Redis 实例组成的整体,数据按照槽(slot) 存储分布在多个 Redis 实例上,集群内部将所有的 key 映射到 16384 个 Slot 中。

Redis Cluster 实现的功能:

  • 将数据分片到多个实例 (按照 slot 存储);
  • 集群节点宕掉会自动 failover;
  • 提供相对平滑扩容 (缩容) 节点。 

Redis Cluster 的优点:

  • 无中心架构:三机房部署,其中一主一从构成一个分片,之间通过异步复制同步数据,异步复制存在数据不一致的时间窗口,保证高性能的同时牺牲了部分一致性(CAP定理)。一旦某个机房掉线,则分片上位于另一个机房的 slave 会被提升为 master 从而可以继续提供服务。
  • 可扩展性:可线性扩展到 1000 多个节点,节点可动态添加或删除。
  • 降低运维成本,提高系统的扩展性和可用性。
  • Redis Cluste 可以线性扩展至 1000 个节点。Redis Cluster 本身就能自动进行 master 选举和故障转移。

  • 三机房部署,每个机房有一主一从,即一个 Master 对应一个 Slave。机房 1 中的 Master 1 连接的 Slave 在机房 2,机房 2 中的 Master 2 连接的 Slave 在机房 3,机房 3 中的 Master 3连接的 Slave 在机房 1,这样构成了一个环。
  • 其中一主一从构成一个分片,之间通过异步复制同步数据,一旦某个机房掉线,则分片上位于另一个机房的 slave 会被提升为 master,从而可以继续提供服务;每个 master 负责一部分slot,数目尽量均摊;客户端对于某个 Key 操作先通过公式计算出所映射到的slot,然后直连某个分片,写请求一律走 master,读请求根据路由规则选择连接的分片节点。
  • Master 负责写,Master 会自动同步到 Slave,假设机房 1 的机器全部断电了,机房1的Master 写服务宕机,此时 Slave 读服务会被提升为 Master ,也就是说机房 1 的数据在机房 2 的 Slava2 上还有备份,数据还在,在宕机的 master 没有恢复前 Slave 要同时承担读写服务,虽然累一点,但是系统仍然能提供服务。
  • 如果单个机房距离很远, Master 1 的数据同步到 Slave2 上是跨机房同步,肯定不如同机房快,这样一来 Slave2 负责的读就会有延迟,Master1 要更新的数据还没有同步到他在另一个机房的备份前,读操作就是不一致的,这样设计牺牲掉一致性(C)。

缓存雪崩、击穿、穿透

很多人在处理缓存和数据库同步问题的思路是这样的:先查缓存,如果缓存没有,则去查数据库,然后更新缓存,如下图所示:

这样设计在数据量小的时候基本没啥问题,如果数据量大,遇到缓存中热点key集中失效,就很可能引发雪崩或者穿透;

雪崩 就是缓存中大批量热点数据过期后,系统的大量请求犹如雪崩一般涌入,引起数据库压力,造成数据库查询堵塞甚至宕机。解决办法:

  • 缓存失效时间分散开,比如每个 key 的过期时间是随机,防止同一时间大量数据过期现象发生,这样不会出现同一时间全部请求都落在数据库层。如果缓存数据库是分布式部署,将热点数据尽可能均匀分布在不同 Redis 和数据库中,有效分担压力,别让一台机器扛着压力。
  • 简单粗暴,让 Redis 数据永不过期,人为手动控制删除已过期的数据。

穿透 是调用者发起的请求参数(key)在缓存和数据库中都不存在,绕过 Reids,通过不存在的 key成功穿透到数据库层或者更底层,大规模不断发起不存在的 key 的请求,会导致系统压力过大最后故障。解决办法:

  • 分布式布隆过滤器:Redis 自身支持布隆(BloomFilter),参考:Redis(十) 布隆过滤器
  • 返回空值:遇到数据库和 Redis 都查询不到的值,在 Redis 里设置一个缺省值,过期时间很短,目的在于同一个 key 再次请求时直接返回 null,避免穿透。

击穿 和穿透类似,是指一个 key 是热点 key,某个瞬间会有成千上万次请求(比如微博热点排行榜,key 是小时时间戳,value 是个 list 的榜单)。每个小时产生一个 key,这个key 会有百万 QPS,如果这个 key 失效了,就像保险丝熔断,百万 QPS 直接压垮数据库。解决办法:

  • 对于访问特别频繁的热点数据就不设置过期时间了,让key永久有效,然后手动控制删除key。

关于缓存雪崩、穿透、击穿的更多内容请查看:缓存雪崩、缓存击穿、穿透穿透具体指哪些问题?_浮尘笔记的博客-CSDN博客 

高并发场景下缓存和数据库更新策略

如果更新一个数据,先更新据库再更新缓存,可能出现高并发场景下的缓存和数据库中数据不一致问题。如果有多个线程同时更新数据库,然后更新缓存,可能出现下面的情况:

针对这个问题,有一个办法,就是先更新数据库,再删除缓存,等待下次读取数据的时候再从数据库读取最新值,然后写入新的缓存:

怎么解决?可以使用 延迟双删,具体二次删除缓存延迟多久,基本上要大于一次更新操作所花费的时间。如果第二次删除失败,可以放到队列中循环删除。

总结:优先查询缓存,如果缓存未命中则查询数据库,将结果写入缓存;数据更新时先更新数据库,再删除缓存,然后一段时间后再延迟删缓存(防止并发场景下操作出现问题)

Redis的大key和热key和大value

正常情况下,Redis 集群中数据都是均匀分配到每个节点,请求也会均匀的分布到每个分片上,但在一些特殊场景中(比如外部爬虫、攻击、热点商品、热搜话题等),这种短时间内某些 key 访问量过于大,对于这种相同的 key 会请求到同一台数据分片上,导致该分片负载较高成为瓶颈,导致雪崩等一系列问题。

热点数据最大的问题会造成 Reids 集群负载不均衡(也就是数据倾斜)导致的故障,这些问题对于 Redis 集群都是致命打击。造成 Reids 集群负载不均衡故障的主要原因:

  • 高访问量的 Key,也就是热 key,如果一个 key 访问的 QPS 超过 1000 就要特别注意了,比如热门商品,热门话题等。
  • 大 Value,有些 key 访问 QPS 虽然不高,但是由于 value 很大,造成网卡负载较大,网卡流量被打满,单台机器可能出现千兆/秒,IO 故障。
  • 热点 Key + 大 Value 同时存在,服务器杀手。

热点 key 或大 Value 会造成哪些故障:

  • 数据倾斜问题:大 Value 会导致集群不同节点数据分布不均匀,造成数据倾斜问题,大量读写比例非常高的请求都会落到同一个 redis server 上,该 redis 的负载就会严重升高,容易打挂。
  • QPS 倾斜:分片上的 QPS 不均。
  • 大 Value 会导致 Redis 服务器缓冲区不足,造成 get 超时。
  • Redis 缓存失效导致数据库层被击穿的连锁反应。

如何准确定位热点数据?

  • 根据业务情况,人工预估统计可能会成为热点的数据,比如 促销活动商品,热门话题等。
  • 在调用端统计某些key的请求次数,但是无法预知具体是哪些key,代码侵入性强。
  • Redis 集群代理层统计:像 Twemproxy、codis 这些基于代理的 Redis 分布式架构,统一的入口,可以在 Proxy 层做收集上报,但是缺点很明显,并非所有的 Redis 集群架构都有 proxy。
  • Redis 服务端收集:监控 Redis 单个分片的 QPS,发现 QPS 倾斜到一定程度的节点进行 monitor,获取热点 key, Redis 提供了 monitor 命令,可以统计出一段时间内的某 Redis 节点上的所有命令,分析热点 key,在高并发条件下,会存在内存暴涨和 Redis 性能的隐患,所以此种方法适合在短时间内使用;同样只能统计一个Redis 节点的热点 key,对于集群需要汇总统计,实现起来比较麻烦。

如何解决热点数据问题:主要从两个方面考虑,第一是数据分片,让压力均摊到集群的多个分片上,防止单个机器打挂;第二是迁移隔离。

  • key 拆分:如果当前 key 的类型是一个二级数据结构,例如哈希类型。如果该哈希元素个数较多,可以考虑将当前 hash 进行拆分,这样该热点 key 可以拆分为若干个新的 key 分布到不同 Redis 节点上,从而减轻压力。
  • 迁移热点 key:以 Redis Cluster 为例,可以将热点 key 所在的 slot 单独迁移到一个新的 Redis 节点上,这样这个热点 key 即使 QPS 很高,也不会影响到整个集群的其他业务,还可以定制化开发,热点 key 自动迁移到独立节点上,这种方案也叫做:多副本。
  • 热点 key 限流:对于读命令 可以通过迁移热点 key 然后添加从节点来解决,对于写命令 可以通过单独针对这个热点 key 来限流。 
  • 增加本地缓存:对于数据一致性不是很高的业务,可以将热点 key 缓存到业务机器的本地缓存中,因为是业务端的本地内存中,省去了一次远程的 IO 调用。但是当数据更新时,可能会造成业务和 Redis 数据不一致。

Redis存储的大 Value 如何优化?

  • 由于 Redis 是单线程运行的,如果一次操作的value 很大会对整个 redis 的响应时间造成影响,因为 Redis 是 Key-Value 结构数据库,大 value 就是单个 value 占用内存较大,对 Redis 集群造成最直接的影响就是数据倾斜。
  • 一般如果 string 类型的 value > 10KB,set、list、hash、zset 等集合数据类型中的元素个数 > 1000个就算是大value;如果string 类型 value > 100KB,set、list、hash、zset 等集合数据类型中的元素个数 > 10000个就算是超大value。
  • 一个较大的 key-value 可以拆分成几个 key-value ,将操作压力平摊到多个 redis 实例中,降低对单个 redis 的 IO 影响;可以将拆分后的几个 key-value 存储在一个 hash 中,每个 field 代表一个具体的属性,使用 hget,hmget 来获取部分的 value,使用 hset,hmset 来更新部分属性。

更多关于Redis的优化方案请查看:Redis 常见的性能问题和优化方案

本地缓存

同样是内存里读写数据,为啥使用本地缓存就会更快?

因为本地缓存的请求是当前服务器上的,相比于请求 Redis或者MySQL都是要转发一次到对应的数据库服务器,而当前代码和Redis服务器可能都不在同一个机房(跨机房,甚至是异地),Redis 相比本地缓存,多一次网络 IO,那肯定不如在本地获取数据快。

常用的本地缓存框架:Google Guava、Ehcache、Spring Cache、Java Map。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/353801.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

es elasticsearch 十四 各种机制 评分机制 正序索引 解决跳跃结果问题 解决耗时过长问题 解决相同属性值都到一个地方

目录 评分机制 机制 查看评分实现如何算出来的explaintrue 分析能否被搜索到 Doc value 正排序索引 Query phase Fetch phase Preference 问题 解决跳跃结果问题 Timeout 到达时间直接返回,解决耗时过长问题 Routing 数据准确分配到某地,解决相…

ChatGPT会取代低代码开发平台吗?

编程作为一种高端技能,向来是高收入高科技的代名词。近期,伴随着ChatGPT在全球的爆火,过去通过窗口“拖拉拽”的所见即所得方式的低代码开发模式,在更加智能和更低成本的AI搅局之下,又面临了更深层次的影响。 低代码平…

高性能至强融核服务器,剖析两大至强融核产品规格_Intel服务器CPU_服务器评测与技术-中关村在线...

英特尔至强融核协处理器基于英特尔集成众核(英特尔MIC)架构,可作为现有英特尔至强处理器E5-2600/4600产品家族的补充,为高度并行化的应用提供无与伦比的性能。 此次推出的至强融核协处理器3100系列和5110p两大家族,基于其最先进的22纳米3-D三…

处理器最新排行_鲁大师Q2季度PC硬件排行:Intel十代酷睿初入战局,最受欢迎CPU是它...

点击右上角关注我们,每天给您带来最新最潮的科技资讯,让您足不出户也知道科技圈大事! 鲁大师2020年Q2季度消费级PC硬件排行数据来源于2020.04.01-06.30日,为减少小众产品(服务器)冲击榜单,使得榜单更具备参考价值&…

CPU避坑指南——1、CPU基础知识-型号

目录 前言 AMD与intel基础知识 选CPU共同问题剖析 什么是CPU CPU标识的说明 CPU后面的字母 AMD说明 前言 插槽类型:要选择与主板兼容的CPU插槽类型,例如Intel主板需要选用Intel CPU,AMD主板需要选用AMD CPU。 型号:要根据…

Android 开发常用性能优化工具总结

目录 systraceSystrace是什么?可以分析哪些问题?启动 perfetto什么是Perfetto?Perfetto和Systrace的关系? ProfileCPUMemory WinScope--跟踪窗口转换Layout InspectorUiAutomatorViewerhierarchyviewerLintTencent/matrix开发者选项显示面(surface)更新…

2021年5月国产数据库排行榜:“华为高斯模式”取得成功,阿里OPA持续攀升

2021年5月国产数据库排行榜已经出炉,前十中TiDB依然以612分稳坐榜首,分数较上月降低8分;阿里系OceanBase上涨34分位列第二,为本月最大涨幅,阿里云PolarDB上涨28分,排在第三,阿里云AnalyticDB排在…

台式计算机cpu多好,2019台式处理器排行榜_台式机处理器排行榜 前六强详细介绍...

台式机处理器排行榜 前六强详细介绍 JPG,300x200,128KB,375_250 2019国产手机排名前十,中国最好手机排名第一竟是这部 JPG,337x337,131KB,311_311 INTEL AMD能够带来多核服务器时代 JPG,1620x10…

2017 开源中国新增开源项目排行榜 TOP 100

2017 年开源中国社区新增开源项目排行榜 TOP 100 新鲜出炉! 这份榜单根据 2017 年开源中国社区新收录的开源项目的关注度和活跃度整理而来,这份最受关注的 100 款开源项目榜单在一定程度上预示着业界的最新流行趋势。 可以看到,前十名中有九…

华为OD机试真题 Java 实现【玩牌高手】【2023 B卷 100分】,附详细解题思路

一、题目描述 给定一个长度为n的整型数组,表示一个选手在n轮内可选择的牌面分数。选手基于规则选牌, 请计算所有轮结束后其可以获得的最高总分数。 选择规则如下: 在每轮里选手可以选择获取该轮牌面,则其总分数加上该轮牌面分…

计算机处理器性能排名,cpu天梯图2018最新版 2018电脑cpu处理器性能排行榜

小编为大家分享2018年最新cpu天梯图,包含桌面端台式机cpu和移动端笔记本电脑cpu性能排行榜,电脑处理器cpu主要有Intel和AMD两大主流品牌。电脑cpu性能好坏决定一台电脑运算能力,所以用户买电脑时非常关心cpu的性能,cpu性能可以通过cpu天梯图来判断,现在是2018年,自然要看…

物理机服务器cpu性能排行榜,g务器cpu性能排行_CPU天梯图2019年7月份新版——CPU性能排行天梯图...

CPU天梯图2019年7月份新版——CPU性能排行天梯图2019(4) CPU天梯图2019年7月份新版——CPU性能排行天梯图2019(4),入门级市场:0 - 600元 奔腾、赛扬依旧是经济型市场的主力出货处理器,然而过去一个月它们...>>2人转发 CPU天梯图2019年7…

工业相机分类、相关参数含义

一、工业相机参数 1、分辨率 分辨率是相机最基本的参数,由相机所采用的芯片分辨率决定,在采集图像时,相机的分辨率对检测精度有很大的影响,在对同样大的视场(景物范围)成像时,分辨率越高&…

HTML5简易涂鸦板制作

运行效果 代码中主要要学会阅读英文单词&#xff0c;务必认真学习English 代码清单1 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><script>var startX,startY;var flag false;window.onload …

canvas 制作简易涂鸦画板(教程)

公司大电视机是安卓系统而且系统,但因为突然无法联网又不允许第三方应用程序,但零时需要画板功能。所以就简单做个画板工具代替一下。 1.在canvas中获取光标坐标 获取坐标的代码很简单: <!DOCTYPE html> <html lang"en"><head><meta charset&qu…

基于涂鸦 Arduino SDK 制作的幻彩灯带(内涵详细开发步骤)

作者&#xff1a;金拱门门神 基于涂鸦Arduino SDK制作的幻彩灯带 物料清单硬件 (4) RGB灯带数量&#xff1a;1 淘宝10元Arduino Uno数量&#xff1a;1 淘宝25元涂鸦CBU模组数量&#xff1a;1 涂鸦提供PCB数量&#xff1a;1 捷配免费打样 步骤 1.在涂鸦平台创建产品 https…

PS制作涂鸦风格非主流图片教程

PS制作涂鸦风格非主流图片教程 2009-04-07 16:10:05 作者&#xff1a; 来源&#xff1a; 互联网 浏览次数&#xff1a; 227 文字大小&#xff1a;【 大】【 中】【 小】 效果图 1 效果图 2 原图 1、打开文件&#xff0c;新建一文档。如下图&#xff1a;

canvas涂鸦板

canvas涂鸦板 功能说明 此画板兼容PC端和移动端&#xff0c;是使用HTML5开发的一款画图软件&#xff0c;用户可以在画板中随意涂鸦&#xff0c;然后保存成图片 技术说明&#xff1a; 利用canvas的画图功能html5在pc端和移动端浏览器中的事件差异 开发步骤 html代码 <…

给文字做涂鸦效果的五种实现方案

介绍 在很多创意网站上&#xff0c;我们都会见到很多文字涂鸦效果&#xff0c;本期我们就介绍五种方法来实现这些文字涂鸦效果&#xff0c;康康如何通过前端技术&#xff0c;一起来让你的网页更有创意吧。 当然在做之前&#xff0c;我们先准备一张涂鸦纹理图哟~ 正文 backgr…

涂鸦音乐

在声音处理技术里有一种常用方法就是将声音信号转化成频谱图。比如下面这幅图&#xff0c;就是由一段小提琴演奏转化而来的。 有人会问&#xff0c;转成频谱图后又怎样呢&#xff1f;我不想谈接下来技术上可以做的各种分析&#xff0c;只从人感知信息的方式这个角度来说。 频谱…