黑马redis

news2025/1/20 3:37:38

Redis的多IO线程只是用来处理网络请求的,对于读写操作命令Redis仍然使用单线程来处理

Redisson分布式锁实现15问

文章目录

  • 主线程和IO线程是如何协作的
  • Unix网络编程中的五种IO模型
  • Linux世界一切皆文件
  • 生产上限制keys *、flushdb、flushall等危险命令
    • keys * 遍历查询100W数据花费时长
    • 配置禁用这些命令
  • BigKey案例
  • 缓存更新策略
    • Redis内存不足的缓存淘汰策略
    • 先删缓存再操作数据库
      • 理想情况
      • 多线程竟态条件下
      • 多线程竟态条件下
    • 先操作数据库再删除缓存【胜出】
      • 理想情况
    • 总结
  • 项目实践【黑马点评】
    • 目标
    • 缓存一致性
    • 缓存穿透
      • 缓存穿透解决方案调研
      • 实战解决商铺信息缓存穿透
      • 总结
    • 缓存雪崩
    • 缓存击穿
      • 缓存击穿解决方案调研
      • 实战解决缓存击穿
        • 互斥锁(setnx)
  • 优惠券秒杀-单机锁
    • 全局唯一ID
      • 自增ID存在的问题
      • 分布式ID的实现
    • 实战优惠券秒杀
      • 总结
  • 优惠券秒杀-分布式锁
    • 自定义的分布式锁
    • 将单机 synchronized 替换为自定义分布式锁
    • 分布式锁误删问题🍖
      • 问题原因分析
      • 代码实现
    • 判断锁标识和释放锁非原子性🥩
    • 存在的问题
      • 锁不可重入
      • 不可重试
      • 超时释放
      • 主从一致性
  • Redis集群方案
    • 主从复制—全量同步、增量同步
      • 全量同步
      • 增量同步
      • 面试题
    • 哨兵模式
      • 服务状态监控
      • redis集群(哨兵模式)脑裂
      • 面试题
    • 分片集群
      • 分片集群结构
      • 分片集群结构——数据读写
      • 存在的问题
      • 面试题1
      • 面试题2
  • Big Key
    • 大key的影响
    • 大key的查找
    • 删除大key注意事项
    • 大key的处理
    • 分拆方案
      • 一、单个简单的key存储的value很大
      • 二、value中存储过多的元素
      • 方案一:使用时间戳作为附加属性
      • 方案二:通过在 `key` 拼接上基于时间分拆
      • 代码解释
        • 方案一代码解释
        • 方案二代码解释

主线程和IO线程是如何协作的

  • 阶段一:服务端和客户端建立Socket连接,并分配处理线程
    首先,主线程负责接收建立连接请求,当有客户端请求和实例建立Socket连接时,主线程会创建和客户端的连接,并把 Socket放入全局等待队列中。紧接着,主线程通过轮询方法把Socket连接分配给IO线程

  • 阶段二:IO线程读取并解析请求
    主线程一旦把Socket分配给IO线程,就会进入阻塞状态,等待IO线程完成客户端请求读取和解析。因为有多个IO线程在并行处理,所以,这个过程很快就可以完成。

  • 阶段三:主线程执行请求操作
    等到IO线程解析完请求,主线程还是会以单线程的方式执行这些命令操作
    在这里插入图片描述

  • 阶段四:IO线程回写Socket和主线程清空全局队列
    当主线程执行完请求操作后,会把需要返回的结果写入缓冲区,然后,主线程会阻塞等待IO线程,把这些结果回写到Socket中,并返回给客户端。和IO线程读取和解析请求一样,IO线程回写Socket时,也是有多个线程在并发执行,所以回写Socket的速度也很快。等到IO线程回写Socket完毕,主线程会清空全局队列,等待客户端的后续请求。
    在这里插入图片描述

Unix网络编程中的五种IO模型

Blocking IO - 阻塞IO

NoneBlocking IO - 非阻塞IO

IO multiplexing - IO多路复用 ★★★

signal driven IO - 信号驱动IO(偏C)

asynchronous IO - 异步IO(偏C)

Linux世界一切皆文件

文件描述符、简称FD,句柄

FileDescriptor:
文件描述符(File descriptor)是计算机科学中的一个术语,是一个用于表述指向文件的引用的抽象化概念。文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统

I/O 的读和写本身是堵塞的,比如当 socket 中有数据时,Redis 会通过调用先将数据从内核态空间拷贝到用户态空间,再交给 Redis 调用,而这个拷贝的过程就是阻塞的,当数据量越大时拷贝所需要的时间就越多,而这些操作都是基于单线程完成的

生产上限制keys *、flushdb、flushall等危险命令

keys * 遍历查询100W数据花费时长

在这里插入图片描述

配置禁用这些命令

redis.conf 在 SECURITY 这一项中

rename-command keys ""
rename-command flushdb ""
rename-command FLUSHALL ""

BigKey案例

多大算Big
参考《阿里云Redis开发规范》

在这里插入图片描述

缓存更新策略

在这里插入图片描述

Redis内存不足的缓存淘汰策略

  • noeviction:当内存使用超过配置的时候会返回错误,不会驱逐任何键
  • allkeys-lru:加入键的时候,如果过限,首先通过LRU算法驱逐最久没有使用的键
  • volatile-lru:加入键的时候如果过限,首先从设置了过期时间的键集合中驱逐最久没有使用的键
  • allkeys-random:加入键的时候如果过限,从所有key随机删除
  • volatile-random:加入键的时候如果过限,从过期键的集合中随机驱逐
  • volatile-ttl:从配置了过期时间的键中驱逐马上就要过期的键
  • volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键 allkeys-lfu:从所有键中驱逐使用频率最少的键
    在这里插入图片描述
    在这里插入图片描述

先删缓存再操作数据库

理想情况

在这里插入图片描述

多线程竟态条件下

在这里插入图片描述

多线程竟态条件下

好巧不巧,缓存失效了,此时线程2要采用先更新数据库再删除缓存的策略,但由于更新数据库没有线程1查询数据库快,所以查到的还是未更新前的旧值10;
线程2更新完毕之后删除了redis缓存,线程1获取时间片后又将10写回了缓存,导致数据库缓存不一致的情况
在这里插入图片描述

先操作数据库再删除缓存【胜出】

理想情况

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

总结

给缓存设置过期时间,定期清理缓存并回写,是保证最终一致性的解决方案

我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。
也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存,达到一致性,切记,要以数据落库DB为准

项目实践【黑马点评】

目标

在这里插入图片描述

缓存一致性

com.sddp.service.impl.ShopServiceImpl#update
事务保证原子性,如果在微服务系统中,这两步不在一个方法当中,甚至不在一个服务当中,那么就需要mq消息通知删除缓存的服务,可以借助TCC来保证分布式事务的原子性
在这里插入图片描述

缓存穿透

缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。如果被恶意用户利用,对服务器会造成负载,严重会导致服务不可用
常见的解决方案有两种:

com.sddp.service.impl.ShopServiceImpl#queryById

在这里插入代码片

缓存穿透解决方案调研

在这里插入图片描述

实战解决商铺信息缓存穿透

如果提交的商铺id本身就是瞎写的,查询数据库之后必然没有数据,那此时,redis则将此id存在redis并赋值为null,下次在查询此id时直接走redis返回null即可
在这里插入图片描述

总结

在这里插入图片描述

缓存雪崩

TTL随机数分散降低机率
Redis宕机:利用集群提高服务的可用性
快速失败、拒绝服务

在这里插入图片描述

缓存击穿

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂下图第 2 步比较耗时,导致多线程访问的时候短时间为写入缓存,期间的流量都打到DB上了)的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。
在这里插入图片描述

缓存击穿解决方案调研

互斥锁:CP(强一致)
逻辑过期:AP(高可用)
在这里插入图片描述
在这里插入图片描述

实战解决缓存击穿

多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁 来锁住它。

其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。

后面的线程进来发现已经有缓存了,就直接走缓存


/**
 * @auther zzyy
 * @create 2021-05-01 14:58
 */
@Service
@Slf4j
public class UserService {
   
    public static final String CACHE_KEY_USER = "user:";
    @Resource
    private UserMapper userMapper;
    @Resource
    private RedisTemplate redisTemplate;
 
    /**
     * 业务逻辑没有写错,对于小厂中厂(QPS《=1000)可以使用,但是大厂不行
     * @param id
     * @return
     */
    public User findUserById(Integer id)
    {
   
        User user = null;
        String key = CACHE_KEY_USER+id;
 
        //1 先从redis里面查询,如果有直接返回结果,如果没有再去查询mysql
        user = (User) redisTemplate.opsForValue().get(key);
 
        if(user == null)
        {
   
            //2 redis里面无,继续查询mysql
            user = userMapper.selectByPrimaryKey(id);
            if(user == null)
            {
   
                //3.1 redis+mysql 都无数据
                //你具体细化,防止多次穿透,我们业务规定,记录下导致穿透的这个key回写redis
                return user;
            }else{
   
                //3.2 mysql有,需要将数据写回redis,保证下一次的缓存命中率
                redisTemplate.opsForValue().set(key,user);
            }
        }
        return user;
    }
 
 
    /**
     * 加强补充,避免突然key失效了,打爆mysql,做一下预防,尽量不出现击穿的情况。
     * @param id
     * @return
     */
    public User findUserById2(Integer id)
    {
   
        User user = null;
        String key = CACHE_KEY_USER+id;
 
        //1 先从redis里面查询,如果有直接返回结果,如果没有再去查询mysql,
        // 第1次查询redis,加锁前
        user = (User) redisTemplate.opsForValue().get(key);
        if(user == null) {
   
            //2 大厂用,对于高QPS的优化,进来就先加锁,保证一个请求操作,让外面的redis等待一下,避免击穿mysql
            synchronized (UserService.class){
   
                //第2次查询redis,加锁后
                user = (User) redisTemplate.opsForValue().get(key);
                //3 二次查redis还是null,可以去查mysql了(mysql默认有数据)
                if (user == null) {
   
                    //4 查询mysql拿数据(mysql默认有数据)
                    user = userMapper.selectByPrimaryKey(id);
                    if (user == null) {
   
                        return null;
                    }else{
   
                        //5 mysql里面有数据的,需要回写redis,完成数据一致性的同步工作
                        redisTemplate.opsForValue().setIfAbsent(key,user,7L,TimeUnit.DAYS);
                    }
                }
            }
        }
        return user;
    }
}

在这里插入图片描述

互斥锁(setnx)
public boolean tryLock(String key){
   
    Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);
    

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

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

相关文章

JDK 并发编程工具类详解:CountDownLatch、Semaphore、Exchanger、CyclicBarrier 和 Phaser

在 Java 并发编程中,JDK 提供了一些强大的工具类来帮助开发者处理线程间的同步和通信问题。这些工具类主要包括 CountDownLatch、Semaphore、Exchanger、CyclicBarrier 和 Phaser,它们都位于 java.util.concurrent 包下,统称为 JUC&#xff0…

实现RAGFlow-0.14.1的输入框多行输入和消息框的多行显示

一、Chat页面输入框的修改 1. macOS配置 我使用MacBook Pro,chip 是 Apple M3 Pro,Memory是18GB,macOS是 Sonoma 14.6.1。 2. 修改chat输入框代码 目前RAGFlow前端的chat功能,输入的内容是单行的,不能主动使用Shift…

电子商务人工智能指南 4/6 - 内容理解

介绍 81% 的零售业高管表示, AI 至少在其组织中发挥了中等至完全的作用。然而,78% 的受访零售业高管表示,很难跟上不断发展的 AI 格局。 近年来,电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

基于STM32F103RCT6的PS2手柄控制舵机转向小车

一、PS2 (1)当接收器上的绿灯常亮时,证明手柄和接收器配对成功,可以正常进行数据通讯。如果手柄和接收器断开了,按手柄上的START键即可恢复配对; (2)当手柄上的MODE指示灯没有点亮的…

电脑投屏到电脑:Windows,macOS及Linux系统可以相互投屏!

本篇其实是电脑远程投屏到另一台电脑的操作介绍。本篇文章的方法可用于Windows,macOS及Linux系统的相互投屏。 为了避免介绍过程中出现“这台电脑”投屏到“那台电脑”的混乱表述,假定当前屏幕投出端是Windows系统电脑,屏幕接收端是Linux系统…

软件测试环境搭建与测试流程

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 1.软件测试环境搭建 思考: 在什么条件下做软件测试?怎么做软件测试? 1.1 搭建测试环境前 确定测试目的 功能测试&#xff…

实战 | C# 中使用YOLOv11实现实例分割 (步骤 + 源码)

导 读 本文主要介绍在C#中使用YOLOv11实现实例分割,并给详细步骤和源码。 C# YOLO11实例分割——本文实现效果:

C#窗体程序学生管理

代码如下: public static string constr "Data SourceFUSHUAI;Initial Catalogproduct;Integrated SecurityTrue"; public static SqlConnection con new SqlConnection(constr); private void Form1_Load(object sender, EventArgs e) { gettable…

特朗普画像

任务内容 Description 特朗普当选了,网上流传着很多段子,也出了特朗普的头像。有人说,特朗普 的头像像一团云。所以今年马云去了美国和特朗普谈中美企业的发展。那么你能帮 忙打印出特朗普的头像吗? 抽象派认为,特朗普…

【Linux 篇】Docker 启动和停止的精准掌舵:操控指南

文章目录 【Linux篇】Docker 启动和停止的精准掌舵:操控指南前言docker基本命令1. 帮助手册 2. 指令介绍 常用命令1. 查看镜像2. 搜索镜像3. 拉取镜像4. 删除镜像5. 从Docker Hub拉取 容器的相关命令1. 查看容器2. 创建与启动容器3. 查看镜像4. 启动容器5. 查看容器…

Android环境搭建

Android环境搭建 第一步:安装 Homebrew 执行以下命令来安装 Homebrew: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"检测是否安装成功: brew --version第二步:安装 No…

【调试工具】USB 转 UART 适配器(USB 转 TTL)

「USB 转 TTL 转换器」是错误的叫法&#xff0c;正确的叫法应该为 「USB 转 UART 适配器」。 Device connection 注意端口的交叉连接&#xff0c;Device1_TX<---->Device2_RX USB-to-UART adapter GND 记得接地。 使用&#xff1a; 当 TX,RX 需要电平为 0-3.3V 时&am…

Stable Diffusion核心网络结构——U-Net

本文详细详细介绍Stable Diffusion核心网络结构——U-Net&#xff0c;作用&#xff0c;架构&#xff0c;加噪去噪过程损失函数等。 目录 Stable Diffusion核心网络结构 SD模型整体架构初识 U-Net模型 【1】U-Net的核心作用 【2】U-Net模型的完整结构图 &#xff08;1&#xff0…

利用【AOP+自定义注解】实现项目中【日志记录】

利用AOP自定义注解实现日志记录 需求: 日志记录 操作日志记录,类似如下 思路:AOP自定义注解 AOP面向切面编程,利用 一种称为"横切"的技术&#xff0c;剖开封装的对象内部&#xff0c;并将那些影响了 多个类的公共行为抽取出封装到一个可重用模块&#xff0c;并将其…

JAVA-二叉树的概念和性质

目录 一.树形结构 1.1 概念 1.2 树的概念(重要)​编辑 补充&#xff1a;高度和深度的区别 1.3 树的应用 二. 二叉树&#xff08;重点&#xff09; 2.1 概念 2.2 两种特殊的二叉树 2.3 二叉树的性质 2.4 选择题 一.树形结构 1.1 概念 树是一种 非线性 的数据结构&…

SSM虾米音乐项目2--分页查询

1.分页查询的底层逻辑 首先根据用户输入的流派&#xff0c;进行模糊查询根据查询的数据进行分页需要前端用户提供pageNo(当前页数)和pageSize(每页的数据量)并且要从后端计算count(总数据量)和totalPage(总页数)&#xff0c;以及startNum(每页开始的记录)从而将对应的页面数据…

debian编译失败

A、缘由和分析 debian的代码在删除该路径下的2个包后&#xff0c; 重新全编&#xff0c;编译不过的问题。 至于我为什么删除这2个包&#xff0c;这是因为在sdk第一次编译时一些文件已经打包进去了&#xff0c;我现在的修改无法更新进img中&#xff0c;而现在我的项目中不需要…

Thonny IDE + MicroPython + ESP32 + A9G 发短信打电话

A9G模块的使用说明 详见该博客&#xff1a;a9gdfgdfhguyiuh-CSDN博客 接线 ESP32 DEVKIT_C A9G GND GND D23 RX A9G开发板用板载MiniUSB&#xff08;安卓口&#xff09;供电 代码 from machine import UART # 导入串口模块 # import timeUART0 UART1 UART2 TX …

在GITHUB上传本地文件指南(详细图文版)

这份笔记简述了如何在GITHUB上上传文件夹的详细策略。 既是对自己未来的一个参考&#xff0c;又希望能给各位读者带来帮助。 详细步骤 打开目标文件夹&#xff08;想要上传的文件夹&#xff09; 右击点击git bash打开 GitHub创立新的仓库后&#xff0c;点击右上方CODE绿色按…

沈阳工业大学《2024年827自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《沈阳工业大学827自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2024年真题 Part1&#xff1a;2024年完整版真题 2024年真题