Redis常见面试题(二)

Redis性能优化

Redis性能测试

阿里Redis性能优化

使用批量操作减少网络传输

Redis命令执行步骤:1、发送命令;2、命令排队;3、命令执行;4、返回结果。其中 1 与 4 消耗时间 --> Round Trip Time(RTT,往返时间),也就是数据在网络上传输的时间,使用批量操作大幅减少RTT。

实现:Lua脚本

Lua 脚本同样支持批量操作多条命令。一段 Lua 脚本可以视作一条命令执行,可以看作是 原子操作 。也就是说,一段 Lua 脚本执行过程中不会有其他脚本或 Redis 命令同时执行,保证了操作不会被其他指令插入或打扰,Lua 脚本中支持一些简单的逻辑处理比如使用命令读取值并在 Lua 脚本中进行处理。

存在问题:

  • 如果 Lua 脚本运行时出错并中途结束,之后的操作不会进行,但是之前已经发生的写操作不会撤销,所以即使使用了 Lua 脚本,也不能实现类似数据库回滚的原子性。

  • Redis Cluster 下 Lua 脚本的原子操作也无法保证了,原因同样是无法保证所有的 key 都在同一个 hash slot(哈希槽)上。

大量Key集中过期问题

Redsi采用定期删除 + 惰性 / 懒汉式删除策略

问题:如果遇到大量过期key的话,客户端请求必须等待定期清理过期key任务线程执行完成,因为定期删除任务是在Redis主线程中执行的,就导致客户端请求无法被及时处理。

解决方案:

  1. 给key设置随机过期时间。(建议)
  2. 惰性删除 / 延迟释放。采用异步方式延迟释放key使用的内存,将该操作交给单独的子线程处理,避免阻塞主线程。

Redis bigKey(大Key)

概念:一个key的value所占的内存比较大,这个key就可以看作是bigkey。

大概标准:

  • String类型的value不超过1MB
  • 符合类型(List、Hash、Set、Sorted Set)不超过5000个

处理工具:

  1. redis-rdb-tools
  2. rdb_bigkeys
  3. 阿里云Redis分析

Redis hotKey(热Key)

概念:一个Key访问的次数明显多于其他Key,例如Redis实例每秒处理请求达5000次,其中一个key的每秒访问量就达2000次 --> hotKey

出现原因:某热点数据访问量暴涨(重大搜索事件、参与秒杀的商品)

导致问题:

  1. 占用大量CPU 和 带宽
  2. 如果访问突然访问的hotKey突然超出Redis的处理能力,Redis就会直接宕机,在此情况下,大量请求将落到后面的数据库上,导致数据库崩溃。

处理工具:

  1. 京东开源工具

  2. 阿里云Redis分析

缓存穿透

概念:大量请求的Kye是不合理的,根本不存在与缓存中,也不存在于数据库中。就会导致这些请求直接到数据库上,根本没有经过缓存着一层,对数据库造成压力。

举个例子:某个黑客故意制造一些非法的 key 发起大量请求,导致大量请求落到数据库,结果数据库上也没有查到对应的数据。也就是说这些请求最终都落到了数据库上,对数据库造成了巨大的压力。

解决办法:参数校验

缓存穿透

1. 布隆过滤器

目的:解决海量数据(缓存穿透、海量数据去重)

概念:二进制向量 / 位数组 和 一系列随机映射函数(哈希函数)两部分组成的数据结构。

特点占用空间少效率高,但是返回的结果是概率性的,而不是非常准确,添加到集合中的元素越多,报错的可能性越大,并且放在布隆过滤器中的元素不容易删除

位数组

Bloom Filter 会使用一个较大的 bit 数组来保存所有的数据,数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1(代表 false 或者 true),这也是 Bloom Filter 节省内存的核心所在。这样来算的话,申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 KB ≈ 122KB 的空间。

原理

  • 当一个元素加入布隆过滤器中:
    • 使用布隆过滤器中的哈希函数对元素值进行计算,得到哈希值(有几个哈希函数得到几个哈希值)
    • 根据得到的哈希值,在位数组中把对应下标的值设置为1。
  • 判断一个元素是否存在于布隆过滤器中:
    • 对给定元素再次进行相同的哈希函数计算。
    • 的到值之后判断位数组中的每个元素是否都为1,如果值都为1,那么说明这个值在布隆过滤器中,如果存在的值不为1,说明该元素不在布隆过滤器中。

布隆过滤器原理图

使用场景:

  1. 判断给定数据是否存在:黑名单功能(判断一个IP或手机号码是否在黑名单中)、判断一个数字是否在搜索数据集中(数据集很大,上亿),防止缓存穿透(判断缓存中是否包含某个元素)。
  2. 去重:爬给定网站的时候对已经爬取过的URL去重、对巨量的QQ号/订单号去重。

实现:

  1. 一个合适大小的位数组保存数据
  2. 几个不同的哈希函数
  3. 添加元素到位数组(布隆过滤器)的方法实现
  4. 判断元素是否存在于位数组的方法实现
import java.util.BitSet;

public class MyBloomFilter {

    /**
     * 位数组的大小
     */
    private static final int DEFAULT_SIZE = 2 << 24;
    /**
     * 通过这个数组可以创建 6 个不同的哈希函数
     */
    private static final int[] SEEDS = new int[]{3, 13, 46, 71, 91, 134};

    /**
     * 位数组。数组中的元素只能是 0 或者 1
     */
    private BitSet bits = new BitSet(DEFAULT_SIZE);

    /**
     * 存放包含 hash 函数的类的数组
     */
    private SimpleHash[] func = new SimpleHash[SEEDS.length];

    /**
     * 初始化多个包含 hash 函数的类的数组,每个类中的 hash 函数都不一样
     */
    public MyBloomFilter() {
        // 初始化多个不同的 Hash 函数
        for (int i = 0; i < SEEDS.length; i++) {
            func[i] = new SimpleHash(DEFAULT_SIZE, SEEDS[i]);
        }
    }

    /**
     * 添加元素到位数组
     */
    public void add(Object value) {
        for (SimpleHash f : func) {
            bits.set(f.hash(value), true);
        }
    }

    /**
     * 判断指定元素是否存在于位数组
     */
    public boolean contains(Object value) {
        boolean ret = true;
        for (SimpleHash f : func) {
            ret = ret && bits.get(f.hash(value));
        }
        return ret;
    }

    /**
     * 静态内部类。用于 hash 操作!
     */
    public static class SimpleHash {

        private int cap;
        private int seed;

        public SimpleHash(int cap, int seed) {
            this.cap = cap;
            this.seed = seed;
        }

        /**
         * 计算 hash 值
         */
        public int hash(Object value) {
            int h;
            return (value == null) ? 0 : Math.abs((cap - 1) & seed * ((h = value.hashCode()) ^ (h >>> 16)));
        }

    }
}
Redis中的布隆过滤器

使用Docker安装Redis中的布隆过滤器redis-stack

2. 接口限流

根据用户或者IP对接口限流,对于一场频繁访问的行为,采取黑名单机制,例如将异常IP列入黑名单。

缓存击穿和雪崩都可以配合接口限流来解决

分布式服务限流实战

缓存击穿

概念:请求的key对应的是热点数据,该数据存在于数据库中,但不存在于缓存中(缓存中的那份数据已经过期),瞬间大量的请求直接发送到数据库,对于数据库造成了巨大的压力,有可能会直接多请求宕机。

缓存击穿

例子:秒杀进行过程中,缓存中的某个秒杀商品的数据突然过期,这就导致瞬时大量对该商品的请求直接落到数据库上,对数据库造成了巨大的压力。

解决

  1. 提前预热(推荐):针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
  2. 加锁(看情况):在缓存失效后,通过设置互斥锁确保只有一个请求去查询数据库并更新缓存。

缓存穿透和缓存击穿有什么区别?

缓存穿透中,请求的 key 既不存在于缓存中,也不存在于数据库中。

缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期)

缓存雪崩

概念缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力

缓存雪崩

例子:数据库中的大量数据在同一时间过期,这个时候突然有大量的请求需要访问这些过期的数据。这就导致大量的请求直接落到数据库上,对数据库造成了巨大的压力。

解决

针对 Redis 服务不可用的情况:

  1. Redis 集群:采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。Redis Cluster 和 Redis Sentinel 是两种最常用的 Redis 集群实现方案。
  2. 多级缓存:设置多级缓存,例如本地缓存 + Redis 缓存的二级缓存组合,当 Redis 缓存出现问题时,还可以从本地缓存中获取到部分数据。

针对大量缓存同时失效的情况:

  1. 设置随机失效时间(可选):为缓存设置随机的失效时间,例如在固定过期时间的基础上加上一个随机值,这样可以避免大量缓存同时到期,从而减少缓存雪崩的风险。
  2. 提前预热(推荐):针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
  3. 持久缓存策略(看情况):虽然一般不推荐设置缓存永不过期,但对于某些关键性和变化不频繁的数据,可以考虑这种策略。
缓存预热如何实现?

常见的缓存预热方式有两种:

  1. 使用定时任务,比如 xxl-job,来定时触发缓存预热的逻辑,将数据库中的热点数据查询出来并存入缓存中。
  2. 使用消息队列,比如 Kafka,来异步地进行缓存预热,将数据库中的热点数据的主键或者 ID 发送到消息队列中,然后由缓存服务消费消息队列中的数据,根据主键或者 ID 查询数据库并更新缓存。
缓存雪崩和缓存击穿有什么区别?

缓存雪崩和缓存击穿比较像,但缓存雪崩导致的原因是缓存中的大量或者所有数据失效,缓存击穿导致的原因主要是某个热点数据不存在与缓存中(通常是因为缓存中的那份数据已经过期)。

Redis集群面试题

Redis Sentinel

  1. 什么是 Sentinel? 有什么用?
  2. Sentinel 如何检测节点是否下线?主观下线与客观下线的区别?
  3. Sentinel 是如何实现故障转移的?
  4. 为什么建议部署多个 sentinel 节点(哨兵集群)?
  5. Sentinel 如何选择出新的 master(选举机制)?
  6. 如何从 Sentinel 集群中选择出 Leader ?
  7. Sentinel 可以防止脑裂吗?

Redis Cluster

  1. 为什么需要 Redis Cluster?解决了什么问题?有什么优势?
  2. Redis Cluster 是如何分片的?
  3. 为什么 Redis Cluster 的哈希槽是 16384 个?
  4. 如何确定给定 key 的应该分布到哪个哈希槽中?
  5. Redis Cluster 支持重新分配哈希槽吗?
  6. Redis Cluster 扩容缩容期间可以提供服务吗?
  7. Redis Cluster 中的节点是怎么进行通信的?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Scala学习记录,List

List是一个不可变&#xff08;immutable&#xff09;的序列。特点&#xff1a;数据是有序的 前面学习的Set&#xff0c;Map数据是无序的&#xff1b;Array是有序的&#xff0c;Array数组物理空间上是连续的 List可变不可变&#xff1a; list中不可变的列表是不能修改的 list…

【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目

给你字符串 s 和整数 k 。 请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。 英文中的 元音字母 为&#xff08;a, e, i, o, u&#xff09;。 示例 1&#xff1a; 输入&#xff1a;s "abciiidef", k 3 输出&#xff1a;3 解释&#xff1a…

0-基于图的组合优化算法学习(NeurIPS 2017)(未完)

文章目录 Abstract1 Introduction2 图上的贪婪算法的通用表述3 表示:图嵌入3.1 Structure2Vec3.2 参数化 Q ^ ( h ( S ) , v ; Θ ) \widehat{Q}(h(S), v; \Theta) Q ​(h(S),v;Θ)4 Training: Q-learningAbstract 为NP-hard组合优化问题设计好的启发式或近似算法通常需要大…

RK3568平台开发系列讲解(设备树篇)设备树(device Tree)的由来

🚀返回专栏总目录 文章目录 一、设备树的由来二、设备树的组成沉淀、分享、成长,让自己和他人都能有所收获!😄 一、设备树的由来 首先不得不提到Linus的一封重要的邮件:(硬件解耦)(可以复用的代码) Gaah. Guys, this whole ARM thing is a f*cking pain in the ass.…

基于C++深度优先遍历迷宫

c实现的深度优先遍历迷宫&#xff0c;迷宫大小为20*20&#xff0c;代码简练清楚&#xff0c;内涵关键注释。代码与网上都不一样。 深度优先遍历迷宫&#xff0c;核心思想是借助一个栈&#xff0c;站在一个节点上时&#xff0c;将它附近可以走的节点存在栈中&#xff0c;再按顺…

QML项目实战:自定义CheckBox

目录 一.添加模块 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.15 二.自定义CheckBox 1.CheckBox设置 2.勾选框设置 3.标签部分 4. 状态变化处理 5.文本设置 三.效果 1.当enabled为true 2.当enabled为true 3.当…

天命人开店日记之门店经营调研(下)

在调研前拟定了一些想要去了解的信息&#xff0c;包括&#xff1a;月销量、净利润、用户购买的主要担忧、与电商平台的竞争差异等关键内容&#xff0c;然而当自己去实地考察线下门店时&#xff0c;确发现实际情况与自己的预期相差非常大。大大出乎预料的包括三方面&#xff1a;…

【昇腾】Linux系统常见命令

文章目录 查看操作系统信息查看EulerOS内核版本 查看root下的内容查看/etc目录下的内容sh: yum: command not foundValueError: zero-size array to reduction operation minimum which has no identityAttributeError: torch_npu._C._NPUDeviceProperties object has no attri…

立体视觉的核心技术:视差计算与图像校正详解

立体视觉的核心技术&#xff1a;视差计算与图像校正详解 在立体视觉中&#xff0c;通过双目相机&#xff08;即左右两台相机&#xff09;的不同视角捕获的图像&#xff0c;结合几何关系&#xff0c;我们可以推算出场景中物体的深度。本文将深入讲解如何基于视差&#xff08;di…

11.6-11.7重大专业能力测试(换皮c++考试)全攻略(两天速通版)

relations的vector存储的就是Relation类型的数据&#xff0c;并不是指针&#xff0c;所以relations[i]访问Relation的成员就是直接用.&#xff0c; 但是joins的JoinSql里面存的是指针&#xff0c;并不是实际的数据&#xff0c;所以应当用->来访问其中的成员 结构体当中的Sq…

Go语言结构体、方法与接口

文章目录 一、结构体构造函数Go语言中的构造函数语法 二、结构体方法和接收器无参数和返回值值类型接收者指针类型接收者方法继承方法重写 三、结构体比较结构体比较要求结构体比较符号 四、接口声明接口定义接口特点接口格式标准格式接口的实现&#xff1a;空接口error接口 五…

用Puppeteer点击与数据爬取:实现动态网页交互

用Puppeteer与代理IP抓取51job招聘信息&#xff1a;动态网页交互与数据分析 引言 在数据采集领域&#xff0c;传统的静态网页爬虫方式难以应对动态加载的网页内容。动态网页通常依赖JavaScript加载数据&#xff0c;用户需要与页面交互才能触发内容显示。因此&#xff0c;我们…

Sophos | 网络安全

在 SophosLabs 和 SophosAI 的威胁情报、人工智能和机器学习的支持下&#xff0c;Sophos 提供广泛的高级产品和服务组合&#xff0c;以保护用户、网络和端点免受勒索软件、恶意软件、漏洞利用、网络钓鱼和各种其他网络攻击。Sophos 提供单一的集成式基于云的管理控制台 Sophos …

盘点RPA在政务领域落地应用

数字政府是数字经济的中坚力量&#xff0c;以强有力的“抓手”带动着各行各业的数字化转型以及新技术的应用与普及。近两年&#xff0c;以RPA为代表的数字技术在政务实践中的表现受到了很高的关注&#xff0c;RPA数字员工在各地相关政务部门悄然上岗&#xff0c;有效助力政府信…

mysql5.7安装SSL报错解决(2),总结

Caused by: java.io.EOFException: SSL peer shut down incorrectly 在java里面连接mysql5.7.17数据库&#xff0c;报以上错误&#xff0c; 将数据库升级到mysql5.7.44就可以了。 这两天处理java连接mysql的问题&#xff0c;报了各种错误&#xff0c;总结一下就是openssl和mysq…

前端基础-html-注册界面

&#xff08;200粉啦&#xff0c;感谢大家的关注~ 一起加油吧~&#xff09; 浅浅分享下作业&#xff0c;大佬轻喷~ 网页最终效果&#xff1a; 详细代码&#xff1a; ​ <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"…

论文 | Teaching Algorithmic Reasoning via In-context Learning

这篇论文《通过上下文学习教授算法推理》探讨了如何通过上下文学习&#xff08;In-context Learning, ICL&#xff09;有效训练大型语言模型&#xff08;LLMs&#xff09;以进行算法推理。以下是从多个角度对这项工作的详细解读&#xff1a; 1. 问题陈述与研究动机 算法推理的…

Json 类型与多值索引 — OceanBase 4.3.2 AP 功能体验

本文来自 2024年OceanBase技术征文大赛——“让技术被看见 | OceanBase 布道师计划”的用户征文。也欢迎更多的技术爱好者参与征文&#xff0c;赢取万元大奖。和我们一起&#xff0c;用文字让代码跳动起来&#xff01; 参与2024年OceanBase技术征文大赛>> MySQL在5.7.8…

FPAGA学习~问题记录

1.Error: concurrent assignmentto a non-netstart is not permitted&#xff08;错误&#xff1a;不允许并发分配到非网络‘start’&#xff09; 原因&#xff1a;wire 或reg 类型不匹配引起的&#xff0c;assign与wrie搭配使用&#xff0c;而reg一般在always、initial语句块中…

微服务系列四:热更新措施与配置共享

目录 前言 一、基于Nacos的管理中心整体方案 二、配置共享动态维护 2.1 分析哪些配置可拆&#xff0c;需要动态提供哪些参数 2.2 在nacos 分别创建共享配置 创建jdbc相关配置文件 创建日志相关配置文件 创建接口文档配置文件 2.3 拉取本地合并配置文件 2.3.1 拉取出现…