【八股文】Redis

news2024/11/24 7:01:25

1.Redis有哪些数据类型

  • 常用的数据类型,String,List,Set,Hash和ZSet(有序)
    • String:Session,Token,序列化后的对象存储,BitMap也是用的String类型,
      • BitMap:不仅可以用做布隆过滤器,也经常用于记录签到打卡,方便记录打卡的连续天数。
    • ZSet:微信步数排行榜,段位排行榜,可以用Redis里的相关命令解决,底层用的是跳表,实现简单,插入删除快,区间查询快。
    • Set的应用场景:存放的数据不重复,文章和动态点赞

2.Redis内存管理(数据淘汰策略)

  • 为什么要数据淘汰策略:会给缓存数据设置一个过期时间,如果一直查询数据,存入到内存里面,会导致out of memory。比如expire key 60,60秒过后过期。还有比如验证码60秒失效,也可以用过期时间。
  • Redis的内存淘汰机制
    • volatile-lru(业务中有置顶数据,例如博客置顶),从已设置过期时间的数据集中选择最近最少使用的淘汰。
    • volatile-ttl,从已设置过期时间的数据集中挑选将要过期的数据淘汰
    • volatile-lfu(有短时高频访问的数据),从已设置过期时间的数据集中挑选最不常用的key。
    • volatile-random,从已设置过期时间的数据集中随机挑选
    • allkeys(所有的缓存数据中,当内存不足时),allkeys-lru(业务没有冷热区分),allkeys-random,allkeys-lfu
    • noeviction(默认):禁止驱除数据,当内存不足时,新写入的操作会报错。

3.Redis生产问题

  • 缓存穿透:就是大量请求的key不合理,当我们查询数据库时,会先去查询缓存,缓存没有,再去查数据库,但数据库也没有,这样会对数据库造成很大的压力。(穿透就是有些能过去,有些过不去)

    • 场景:比如黑客估计创造了一些非法的key,导致大量请求落到数据库
    • 解决一:布隆过滤器,将所有可能得到的值先放到布隆过滤器中(位数组和随机映射函数),当用户请求过来,先判断用户发来的请求值是否存在布隆过滤器中。不存在直接返回错误信息,如果存在则判断缓存中是否有数据,没有就去数据库查,然后插入到缓存,并返回给用户。
    • 解决二:接口限流,对异常频繁访问的行为,直接将ip拉入黑名单
  • 缓存击穿:在请求大量的热点数据,但这部分数据在缓存中已经失效,然后会将大量的请求打在数据库上,给数据库带来巨大的压力。(这部分热点数据都失效了)

    • 场景:比如秒杀活动,某个秒杀商品的数据在缓存中突然过期,就会大量的线程对该商品请求落到数据库上。
    • 解决一:设置过期时间长,逻辑过期,高可用,不保证数据绝对一致
    • 解决二:设置热点数据提前预热,将其放到缓存并设置合理过期时间
    • 解决三:在请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求落到数据库上。强一致,性能差。
  • 缓存雪崩:缓存在同一时间大面积失效,导致大量请求直接落到数据库上,对数据库造成了巨大的压力。
    - 解决一:采用Redis集群(哨兵模式)
    - 解决二:限流,Nginx和Spring cloud gateway
    - 解决三:缓存预热,程序启动或在运行中,主动将热点数据加载到缓存中,(使用定时任务Spring Task,定时出发缓存预热逻辑)
    - 解决四:给不同的key的TTL添加随机值。这样不会同一时间大面积失效。

  • 如何做到数据库和Redis缓存里面的数据库一致:(强一致性的业务)

    • 延迟双删:
      • 定义:延迟双删是一种用于处理高并发场景下缓存与数据库数据一致性的策略。它的核心思想是在更新数据库之前,先从缓存中删除旧数据,然后更新数据库,最后经过一段延迟时间后再次尝试删除缓存中的数据。
      • 原因:在高并发场景下,直接更新数据库后立即删除缓存可能会导致读请求在缓存未更新前获取到脏数据。延迟双删通过引入延迟机制,给数据库更新留出时间,减少脏数据的产生。
    • 分布式:读多写少的业务
      • 共享锁:读锁readmeLock,加锁之后,其他线程可以共享读操作,但不能写操作
      • 排他锁:独占锁writerLock,加锁之后,其他线程阻塞读写操作
      • 读数据时添加共享锁,写数据时添加排他锁。
  • 异步通知保证数据的最终一致性(短暂不一致是允许的),也可以用Canal的异步通知。

    • 使用MQ中间件,更新数据之后,通知缓存删除。保证MQ的可靠性。
    • 利用Canal中间件,不需要修改业务代码,伪装为MySQL的一个从节点,Canal通过读取binlog数据更新缓存。
  • Redis 持久化

    • RDB(Redis数据快照),把内存中的所有数据记录到磁盘中,当Redis出现故障重启后,从磁盘读取快照文件,恢复数据。Redis内部有触发RDB机制,save 900 1,900秒内,如果至少有一个key被修改,就执行bgsave。
      • RDB执行原理,bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据(页表)。完成fork后读取内存数据并写入RDB文件。
        • fork技术采用copy-on-write技术:当进程执行读操作时,访问共享内存。当主进程执行写操作时,则会拷贝一份数据,执行写操作。
      • 页表:记录虚拟地址与物理地址的映射关系,因为主进程不能直接访问物理内存,只能通过页表来访问。
    • AOP(追加文件),Redis处理的每个写命令都会记录到AOF文件,可以看作命令日志文件。但是AOF文件默认是关闭的,需要修改redis.conf配置文件来开启AOF。
      • appendonly yes 开启AOF
      • appendsync always 表示每次执行一次写命令,同步刷新新盘,可靠性高,性能差
      • appendsync everysec,性能适中,会丢失1s数据
      • appendsync no 操作系统控制何时将缓冲区内存写回磁盘,性能最好,可能会丢失大量数据
      • 缺点:AOF文件会比RDB文件大的多
        • 解决办法:使用bgrewriteaof命令,让AOF文件执行重写功能,用最少的命令达到相同的效果。

        #AOF文件比上次文件增长超过多少百分比则触发重写
        auto-aof-rewrite-percentage 100
        #AOF文件体积最小多大以上才触发重写
        auto-aof-rewrite-min-size 64mb

  • 数据过期策略

    • set name heima 10(10秒后过期)
    • 惰性删除
      • 设置了key的过期时间后,在需要key时,检查是否过期,如果过期直接删除
      • 对CPU友好,只有使用到key的时候才会去检查key
      • 对内存不友好,如果一个key已经过期,但是一直没有使用,那么会一直存在内存中
    • 定期删除
      • 每过一段时间,对一些key进行检查,删除过期的key
      • 定期清理的两种模式,FAST模式(不固定,两次清理时间不超过2ms,一次清理不超过1ms)和SLOW模式(定时任务,每次清理不超过25ms)。
      • 惰性删除配合定期删除
    • RDB和AOF各有优点,如果对数据安全性要求较高,会结合使用,下面是他们的对比
RDBAOF
持久化方式定时对整个内存做快照记录每一次执行的命令
数据完整性不完整,两次备份之间会丢失相对完整,取决于刷盘策略
文件大小会有压缩,文件体积小记录命令,文件体积大
宕机恢复速度很快
数据恢复优先级低,因为数据完整性不如AOF高,因为数据完整性更高
系统资源占用高,大量CPU和内存消耗低, 主要是磁盘IO资源,但AOF重写时占用大量CPU和内存资源
使用场景可以容忍分钟的数据丢失,追求更快的启动速度对数据安全性要求较高

4.Redis 分布式锁

  • 如何实现:
    • 背景:集群情况下的定时任务、抢单、幂等性场景。
    • 出现异常的情况,当两个线程同时查询库存时,刚好库存有一张优惠卷,然后都判断是否需要扣减库存,判断通过库存变为-1,存在的超卖现象。
      在这里插入图片描述
    • 不能使用synchronized锁,synchronized锁可以解决同一个JVM下的线程互斥,解决不了多个JVM下的线程互斥,如果通过Nginx反向代理部署到多个服务器上,用synchronized锁不能解决问题。
    • 分布式锁:如果获取锁成功,则会在分布式锁中添加一条记录,证明线程1中已经有锁了,其他线程会出现阻塞状态,直到释放锁,其他线程才能获取锁。形成互斥的效果
    • 实现:setnx命令,set if not exists如果不存在就set
      • 获取锁:set Lock value NX EX 10,添加锁,NX互斥,EX是过期时间(设置值和过期时间放在一条命令一起执行,因为执行该命令不保证原子性。加上失效时间避免死锁)
      • 释放锁:del key
      • 如何设置控制锁的有效时长,也就是当业务执行完成时,才释放锁,而不是还没执行完就释放了锁。
        • 给锁续期:Redisson实现分布式锁,会另外开一个线程去监控watch dog(看门狗),是否需要给过期时间给续期。如果锁的过期时长是releaseTime=30s,则会每隔releaseTime / 3,也就是10s都会重新续期30s。默认是每个10秒续期一次。
        • 同时Redisson还会设置一个while循环来等待该锁释放后,其他线程不断尝试获取锁。这样在高并发的情况下,增加分布式锁的使用性。lua脚本保证命令执行的原子性。在这里插入图片描述
        • 分布式锁是可重入的,多个锁重入需要判断是否是当前线程,在Redis中使用的hash结构来存储线程信息和重入的次数,value值存的是线程id和重入次数。
        • 解决主从数据一致性的问题:RedLock红锁(不推荐,性能太低)。如果业务中的强一致性,使用zookeeper来实现分布式锁。

其他考点

  • Redis集群有哪些方案?
    • 主从复制:主节点负责写操作,其他节点负责读操作,并且要保证主节点将数据同步给从节点。以提高Redis的并发能力。master主节点,slave从节点。
      • 主从全量同步:在这里插入图片描述
      • 主从增量同步(slave 重启或后期数据变化)在这里插入图片描述
    • 哨兵的作用:来实现主从集群的自动故障修复。主要是当主节点宕机后,就失去了写的操作。
      • 监控,Sentinel会不断检查主节点和从节点是否按预期工作
      • 自动故障修复:如果主节点出现故障,那么会将其中一个从节点升级为主节点。
      • 通知:会将故障信息推送给Redis客户端
      • 原理:在这里插入图片描述
    • 哨兵模式容易出现脑裂问题在这里插入图片描述
    • 总结在这里插入图片描述
  • 分片集群结构
    • 主从和哨兵模式可以解决高可用和高并发读的问题
      • 出现问题:不能解决海量数据存储和高并发写的问题。
      • 解决方案:集群中采用多个主节点,每个主节点保存不同数据。每个master可以有多个salve节点。master之间通过ping检测彼此之间的状态。在这里插入图片描述
      • 哈希槽(Redis分片集群中数据是怎样存储和读取的?)在这里插入图片描述
  • Redis是单线程的,但为什么还那么快?
    • Redis是纯内存操作的,而MySQL是存入磁盘,所以Redis执行速度非常快。
    • 采用单线程,避免不必要的线程上下文切换
    • 使用I/O多路复用模型,非阻塞IO
      • Redis的瓶颈是网络延迟,I/O多路复用模型主要实现了高校的网络请求。
      • 用户空间和内核空间:用户空间只能执行受限的命令,当要调用系统资源时,需要通过内核空间提供的接口访问。Linux为提高IO效率,会在用户空间和内核空间中加入缓存区,写数据:用户缓冲区-》内存缓存区-》硬件设备,读数据刚好相反。
      • 阻塞IO模型:阻塞等待数据,阻塞读数据
      • 非阻塞IO模型:recvfrom操作会理解返回结构,不会阻塞用户线程。(CPU使用率暴增)
      • IO多路复用模型:select,poll和epoll
    • Redis的网络模型在这里插入图片描述
    • 总结在这里插入图片描述

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

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

相关文章

案例:LVS+Keepalived集群

目录 Keepalived 原理 Keepalived案例 双机高可用热备案例 配置 修改配置文件 测试 严格模式测试 修改配置文件 测试 模拟故障测试 LVSKeepalived高可用 案例拓扑图 初步配置 关闭服务 主调度器配置 健康状态检查的方式 调整内核参数 从调度器配置 服务器池…

失业后才会明白,职场上有4个扎心的现象

最近一段时间,因为疫情的原因,很多企业都在经历着前所未有的困难,其中就包括华为这样的大型企业。 任正非在接受媒体采访的时候表示:“全球经济持续衰退,未来3到5年内都不可能转好……把寒气传递给每个人。 这句话一…

python中的魔术方法(特殊方法)

文章目录 1. 前言2. __init__方法3. __new__方法4. __call__方法5. __str__方法6. __repr__方法7. __getitem__方法8. __setitem__方法9. __delitem__方法10. __len__方法11. 富比较特殊方法12. __iter__方法和__next__方法13. __getattr__方法、__setattr__方法、__delattr__方…

深度学习DeepLearning Inference 学习笔记

神经网络预测 术语 隐藏层神经元多层感知器 神经网络概述 应当选择正确的隐藏层数和每层隐藏神经元的数量,以达到这一层的输出是下一层的输入,逐层变得清晰,最终输出数据的目的。 在人脸识别的应用中,我们将图片视作连续的像…

【Java 第九篇章】多线程实际工作中的头大的模块

多线程是一种编程概念,它允许多个执行路径(线程)在同一进程内并发运行。 一、多线程的概念和作用 1、概念 线程是程序执行的最小单元,一个进程可以包含多个线程。每个线程都有自己的程序计数器、栈和局部变量,但它们…

Motionface ai工具有哪些?

Motionface Android/PC 用一张静态含有人脸相片来生成一个能说会唱的虚拟主播。使用简单便捷,极致的流畅度体验超乎您的想象。 免费下载 Respeak PC电脑软件 任意视频一键生成虚拟主播,匹配音频嘴型同步,保留原视频人物神态和动作&#xff0c…

核显硬刚RTX 4070,AMD全新APU杀疯了

这年头,一台平民玩家低预算主流桌面电脑主机是什么配置? Intel i5 12400F CPU、B760 主板、NVIDIA RTX 4060 显卡、双 8G DDR4 内存、1T 固态硬盘的组合,想必相当具有代表性了吧! 但仔细掰开后我们不难发现,这套不到…

生物信息学入门:Linux学习指南

还没有使用过生信云服务器?快来体验一下吧 20核心256G内存最低699元半年。 更多访问 https://ad.tebteb.cc 介绍 大家好!作为一名生物信息学的新人,您可能对Linux感到陌生,但别担心,本教程将用简单明了的方式&#xff…

Cache结构

Cache cache的一般设计 超标量处理器每周期需要从Cache中同时读取多条指令,同时每周期也可能有多条load/store指令会访问Cache,因此需要多端口的Cache L1 Cache:最靠近处理器,是流水线的一部分,包含两个物理存在 指…

解决windows安装docker desktop打开报错问题

下载docker windows版本: https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe?utm_sourcedocker&utm_mediumwebreferral&utm_campaigndd-smartbutton&utm_locationmodule 正常安装,然后运行,弹出这个报错: 试了…

力扣 两数之和

致每一个初学算法的你。 题目 时间复杂度&#xff1a;O(N^2)&#xff0c; 空间复杂度&#xff1a;O(1) 。 class Solution {public int[] twoSum(int[] nums, int target) {int n nums.length;for (int i 0; i < n; i) {for (int j i 1; j < n; j) {if (nums[i] …

RK3568平台开发系列讲解(文件系统篇)Linux内核中 文件的三个数据结构

在内核中,与文件描述符相关的三个主要数据结构分别是: 文件描述符表(进程级):这是每个进程所拥有的数据结构,用于维护进程中打开的所有文件描述符。每个 fd 在这个表中都有一个对应的条目,指向更底层的文件表示结构。 打开文件列表(系统级):这是一个全系统范围内的数…

DC-5靶场实战模拟

信息收集 端口和网段信息&#xff1a;使用nmap扫描 //扫描网段中存货的主机 nmap -sP 192.168.10.0/24 //进行对主机进行猜测-》发现接口&#xff1a;80存活 nmap -sV 192.168.10.245 目录信息 &#xff1a;使用dirbuster 指纹信息 找漏洞 发现web 中contact有提交界面进行…

[设备] 关于手机设备中几种传感器的研究

一、手机设备中三位坐标系概念 X轴的方向&#xff1a;沿着屏幕水平方向从左到右&#xff0c;如果手机如果不是是正方形的话&#xff0c;较短的边需要水平 放置&#xff0c;较长的边需要垂直放置。Y轴的方向&#xff1a;从屏幕的左下角开始沿着屏幕的的垂直方向指向屏幕的顶端Z轴…

linux操作——yum、systemctl、firewall、hostname、、、

一、什么是yum yum是一种在Linux操作系统中使用的软件包管理器。它可以用来从软件仓库中下载、安装、更新和删除软件包。yum可以自动解决软件包之间的依赖关系&#xff0c;并且可以方便地查找和安装各种软件。在大多数基于Red Hat的Linux发行版中&#xff0c;如CentOS和Fedora&…

牛客 JZ31.栈的压入,弹出序列 C++写法

牛客 JZ31.栈的压入&#xff0c;弹出序列 C写法 思路&#x1f914;&#xff1a; 创建一个栈&#xff0c;push压入序列&#xff0c;然后用栈顶跟弹出序列比&#xff0c;如果一样就出栈并且继续比较&#xff0c;不一样就再次push入栈&#xff0c;直到压入序列走完&#xff0c;如果…

部署伪分布式 Hadoop集群

部署伪分布式 Hadoop集群 一、JDK安装配置1.1 下载JDK1.2 上传解压1.3 java环境配置 二、伪分布式 Hadoop 安装配置2.1 Hadoop 下载2.2 上传解压2.3 Hadoop 文件目录介绍2.4 Hadoop 配置2.4.1 修改 core-site.xml 配置文件2.4.2 修改 hdfs-site.xml 配置文件2.4.3 修改 hadoop-…

【从零开始一步步学习VSOA开发】URL 资源标识

URL 资源标识 概念 在 VSOA 的世界里&#xff0c;所有的差异化均得到统一&#xff0c;所有的硬件、软件服务均提供统一的资源标签 URL。类似 http://&#xff0c;VSOA 的 URL 以 vsoa:// 开始。下面通过 2 个例子介绍 VSOA 统一资源标识的好处&#xff1a; 匹配规则 URL 标…

Modbus poll和Modbus Mbslave的使用

读取Modbus Mbslave中的数据 首先创建COM1和COM2端口 然后 using System.IO.Ports; ​ namespace 通信 {internal class Program{static void Main(string[] args){Console.WriteLine("Hello, World!");SerialPort serialPort new SerialPort("COM1",960…

前缀和专题

板子&#xff1a; &#xff08;占坑&#xff09; Leetcode 238. 除自身以外数组的乘积 优化前&#xff1a;使用前后缀数组记录 class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int n nums.size();vector<int> pre(n, 1),…