高并发如何实现单用户信息查询接口

高并发如何实现单用户信息查询接口

故事情节

  • 产品:小李,有个单用户信息查询的功能,需要你实现一下
  • 小李:这还不简单,两分钟我给你实现
  • 两分钟过去…
  • 小李:欧克了,部署上线了
  • 运维:哪个傻蛋写的接口,导致MySQL宕机了
  • 小李一愣,他写的接口明明没有报错啊,这是怎么回事呢?
  • 产品:小李赶紧给我排查出来,否则这个月的奖金一分都没有
  • 小李:这这这,我不知道什么问题啊
  • 小李纳闷中,思来思去不知道什么问题如何解决…
  • 小李:老黄,只能求你出马了,这个月我的奖金全部都给你
  • 老黄听到小李的请求,他微微一笑,答应了下来
  • 老黄:么得问题了
  • 老黄耐心地指导小李修复了这个错误,并对代码进行了优化和完善
  • 小李听得认真,心里暗自发誓要吸取教训,以后在工作中更加严谨细致。而这次经历也让他对老黄产生了更深的敬意和信任
  • 最终,小李成功排查并解决了问题,产品顺利上线运行。产品部门的领导对他的表现给予了肯定和赞赏,而他也因为自己的努力和进步获得了全额的奖金

小李写的代码:

Service层:
直接查询MySQL返回数据

 public UserQueryRespDTO queryUserByUserId(Long userId) {
    LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
            .eq(UserDO::getUserId, userId);
    List<UserDO> userDOList = userMapper.selectList(queryWrapper);
    UserDO userDO = CollUtil.isNotEmpty(userDOList) ? userDOList.get(0) : null;
    UserQueryRespDTO userQueryRespDTO = new UserQueryRespDTO();
    BeanUtil.convert(userDO, userQueryRespDTO);
    return userQueryRespDTO;
}

流程图:
在这里插入图片描述

http 请求直接打到 MySQL 数据库,不宕机才怪嘞

老黄写的代码:

Service层:

  1. 先读取 Redis 缓存,数据存在直接返回用户
  2. 数据不存在,读取 MySQL 数据库,加上双重判定锁,减轻获得分布式锁后线程访问数据库压力
  3. 读取到 MySQL 数据,缓存到 Redis 并且返回
  4. 读取数据为NULL,缓存空对象到 Redis 中,并设置一个较短的过期时间(防止缓存穿透)
public UserQueryRespDTO queryUserByUserId(Long userId) {
    UserDO userDO = distributedCache.safeGet(
            USER_INFO_KEY + userId,
            UserDO.class,
            () -> {
                LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
                        .eq(UserDO::getUserId, userId);
                List<UserDO> userDOList = userMapper.selectList(queryWrapper);
                return CollUtil.isNotEmpty(userDOList) ? userDOList.get(0) : null;
            },
            30,
            TimeUnit.MINUTES,
            null,
            null,
            key -> {
                // 缓存空对象,解决缓存穿透。也可以使用布隆过滤器。
                distributedCache.put(key, new UserDO(), 5, TimeUnit.MINUTES);
            });
    UserQueryRespDTO userQueryRespDTO = new UserQueryRespDTO();
    BeanUtil.convert(userDO, userQueryRespDTO);
    return userQueryRespDTO;
}

第二行distributedCache.safeGet方法

public <T> T safeGet(String key, Class<T> clazz, CacheLoader<T> cacheLoader, long timeout, TimeUnit timeUnit,
                     RBloomFilter<String> bloomFilter, CacheGetFilter<String> cacheGetFilter, CacheGetIfAbsent<String> cacheGetIfAbsent) {
    T result = get(key, clazz);
    // 缓存结果不等于空或空字符串直接返回;通过函数判断是否返回空,为了适配布隆过滤器无法删除的场景;两者都不成立,判断布隆过滤器是否存在,不存在返回空
    if (!CacheUtil.isNullOrBlank(result)
            || Optional.ofNullable(cacheGetFilter).map(each -> each.filter(key)).orElse(false)
            || Optional.ofNullable(bloomFilter).map(each -> !each.contains(key)).orElse(false)) {
        return result;
    }
    RLock lock = redissonClient.getLock(SAFE_GET_DISTRIBUTED_LOCK_KEY_PREFIX + key);
    lock.lock();
    try {
        // 双重判定锁,减轻获得分布式锁后线程访问数据库压力
        if (CacheUtil.isNullOrBlank(result = get(key, clazz))) {
            // 如果访问 cacheLoader 加载数据为空,执行后置函数操作
            if (CacheUtil.isNullOrBlank(result = loadAndSet(key, cacheLoader, timeout, timeUnit, true, bloomFilter))) {
                Optional.ofNullable(cacheGetIfAbsent).ifPresent(each -> each.execute(key));
            }
        }
    } finally {
        lock.unlock();
    }
    return result;
}

流程图:
在这里插入图片描述

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

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

相关文章

git checkout进行更改分支

git clone https://gitee.com/yaleguo1/minit-learning-demo.git下载代码。 cd minit-learning-demo/进入目录里边。 ls -l看一下当前分支的内容。 git checkout geek_chapter02更改分支到geek_chapter02。 ls -l看一下目录里边的内容。

Python 自动化之收发邮件(二)

发邮件之Windows进程监控 文章目录 发邮件之Windows进程监控前言一、基本内容二、基本结构三、库模块四、函数模块1.进程监控2.邮件发送 五、程序运行模块1.获取时间2.用户输入3.进程监控3.1进程启动发邮件3.2进程停止发邮件 总结 前言 上一篇简单写了一下如何进行邮件的收发操…

NXP应用随记(四):eMios阅读随记-整体功能概述

目录 1、eMios IP介绍 2、时钟结构 3、通道类型 4、功能介绍 5、中断与DMA 6、EMIOS -通道分配建议(针对S32K312) 1、eMios IP介绍 Emios是什么&#xff1f;eMIOS提供了独立的通道(UCs)&#xff0c;您可以配置这些通道来为不同的功能生成或测量时间事件。 每个eMIOS实例最…

智能插座是什么

智能插座 电工电气百科 文章目录 智能插座前言一、智能插座是什么二、智能插座的类别三、智能插座的原理总结 前言 智能插座的应用广泛&#xff0c;可以用于智能家居系统中的电器控制&#xff0c;也可以应用在办公室、商业场所和工业控制中&#xff0c;方便快捷地实现电器的远…

锁--07_2---- index merge(索引合并)引起的死锁

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 案例分析生产背景死锁日志表结构执行计划 EXPLAN为什么会用 index_merge&#xff08;索引合并&#xff09;为什么用了 index_merge就死锁了解决方案注&#xff1a;M…

算法训练营Day14

#Java #二叉树层次遍历 #反转二叉树 开源学习资料 二叉树的层次遍历&#xff1a;力扣题目链接 二叉树的层次遍历很好理解&#xff1a; 就是从根结点一层一层地往下遍历&#xff08;同一层&#xff0c;从左到右&#xff09;&#xff1a; 迭代的方式很好理解&#xff1a;就是…

Netty常见的设计模式

简介 设计模式在软件开发中起着至关重要的作用&#xff0c;它们是解决常见问题的经过验证的解决方案。而Netty作为一个优秀的网络应用程序框架&#xff0c;同样也采用了许多设计模式来提供高性能和可扩展性。在本文中&#xff0c;我们将探讨Netty中使用的一些关键设计模式&…

TS系列-keyof的妙用

案例1 1、如果&#xff0c;有一个接口&#xff0c;某个变量的类型&#xff0c;是这个接口的 key &#xff1f; keyof 后面可以跟 一个对象类型或者一个接口类型keyof 是把后面 对象或者接口 的 键 都提取出来&#xff0c;组成一个联合类型 interface IStudentAttr {name: stri…

【LeetCode刷题笔记(6-1)】【Python】【三数之和】【哈希表】【中等】

文章目录 三数之和题目描述示例示例1示例2示例3 提示解决方案1&#xff1a;【三层遍历查找】解决方案2&#xff1a;【哈希表】【两层遍历】 结束语 三数之和 三数之和 题目描述 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! …

nodejs微信小程序+python+PHP血液中心管理平台的设计与实现-计算机毕业设计推荐

在二十一世纪的今天&#xff0c;我国献血总量已经不容小觑&#xff0c;在全国人民的不懈努力下&#xff0c;贫血、缺血的病人已经有了足够的血液保障。与此同时&#xff0c;采血工作和血液入库、出库等工作也日愈繁重。为进一步提高采血工作和血液中心的工作效率&#xff0c;开…

【算法与数据结构】376、LeetCode摆动序列

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题难点在于要考虑到不同序列的情况&#xff0c;具体来说要考虑一下几种特殊情况&#xff1a; 1、上…

提前预警,时刻守护:迅软DLP的数据安全先锋

许多数据泄密事件的发生&#xff0c;往往都是由于没有在案发事前做好安全保护&#xff0c;使得重要信息被随意攻击、盗取、泄密。比起在危机发生后亡羊补牢&#xff0c;更重要的是应该在案发之前未雨绸缪。迅软DLP作为迅软股份研发的“重磅选手”&#xff0c;可为政企单位在一切…

物联网智能仓库解决方案

物联网智能仓库解决方案是一种基于物联网技术的仓库管理系统&#xff0c;通过自动化设备、智能化管理系统和大数据分析等技术&#xff0c;实现仓库的智能化运营和管理。 物联网智能仓库解决方案包括&#xff1a; 仓库设备自动化&#xff1a;通过自动化设备和技术&#xff0c;实…

OpenHarmony关于修改系统横屏导致启动视频显示不全问题解决

前言 OpenHarmony源码版本&#xff1a;4.0release 开发板&#xff1a;DAYU / rk3568 前段时间写的设置OpenHarmony启动视频&#xff0c;在竖屏状态下是正常的&#xff0c;但是横屏状态下显示不全。 链接直达&#xff1a;OpenHarmony 设备启动Logo和启动视频替换指南-CSDN博…

docker小白第四天

docker小白第一天 什么是镜像 1、是一种轻量级、可执行的独立软件包&#xff0c;它包含运行某个软件所需的所有内容&#xff0c;我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等)&#xff0c;这个打包好的运行环境就…

基于轻量级yolov5-seg全系列【n/s/m/l/x】参数模型开发构建工业场景下不同参数量级的滚珠丝杠传动表面缺陷分割检测系统

工业场景下的滚珠丝杠传动表面缺陷分割检测系统在我们前面的博文中已经有了相关的开发实践了&#xff0c;感兴趣的话可以自行阅读即可&#xff1a; 《助力工业生产质检&#xff0c;基于轻量级yolov5-seg开发构建工业场景下滚珠丝杠传动表面缺陷分割检测系统》 前文主要是以se…

【PS】修改 图片 文字

删除文字 1&#xff1a;框选要修改的文字 选择-色彩范围 调整色彩容差能看见字体的时候就OK&#xff08;记住用吸管吸取文字颜色&#xff09; 2&#xff1a;选择-修改-扩展-像素2 3&#xff1a;编辑-内容识别填充 现在文字去除了。 用污点画笔修复工具&#xff0c;对缺陷进行…

四十七、Redis分片集群

目录 一、分片集群结构 二、散列插槽 1、Redis如何判断某个key应该在哪个实例&#xff1f; 2、如何将同一类数据固定的保存在同一个Redis实例&#xff1f; 三、集群伸缩 四、故障转移 1、当集群中有一个master宕机时 &#xff08;1&#xff09;自动转移 &#xff08;2&…

[渗透测试学习] Codify - HackTheBox

首先nmap扫描端口 nmap -sV -sC -p- -v --min-rate 1000 10.10.11.239扫出来三个端口&#xff0c;22端口为ssh服务&#xff0c;80端口有http服务&#xff0c;3000端口为nodejs框架 尝试访问下80端口&#xff0c;发现页面重定向 将该域名添加到hosts里 sudo vim /etc/hosts 成…

MySQL数据库的基础概念

目录 顾名思义&#xff0c;数据库是用于存储数据的&#xff0c;那这些数据被存储在哪呢&#xff1f; 文件也能存储数据&#xff0c;那在这个基础上&#xff0c;为什么还要搞出一个数据库来存储数据呢&#xff1f; MySQL的客户端登录/退出指令、服务端的启动/关闭指令 数据…