Redis 高并发缓存架构实战与性能优化

前置知识

1、缓存击穿、缓存失效的基本概念
2、什么样的 数据 需要加分布式锁
3、课上代码

05-一线大厂Redis高并发缓存架构实战与性能优化

对于 公司 中 简单的增删改查 做 高性能处理 , 采用递进的方式一步步优化。

  1. 普通Redis用法: 新增、修改、删除设置缓存 , 查询是获取缓存 ,如果没获取到取数据库 。
  2. 实现简单的数据冷热分离: 采用 对 key 加 过期时间 、 查询时 做 缓存读延期 处理。( 这种 针对于 大规模 数据 , 如京东商品 可能 上亿, 但是 只有1% 的商品经常访问 。 )
  3. 对于数据的批量更新问题: 批量更新会导致大量数据的数据同时过期, ( 数据库压力可能增大,导致数据库抖动 这就是缓存击穿 )在设置过期时间时添加 随机过期时间 解决缓存击穿问题
  4. 解决缓存穿透问题: 如果数据已经删除,但是还有请求 到查询接口,数据库与Redis都查不到。 解决方案:设置空缓存,并设置一个相对较短的过期时间。( 即使有几十万 空数据缓存 , 那么 在 几分钟后都失效了,不会占用 缓存空间)
  5. 冷门数据缓存重建问题: DCL(double check look)机制实现缓存重建
  6. 使用分布式锁解决缓存数据库双写不一致
  7. 如果读多写少 使用读写锁 优化分布式锁,
  8. 优化DCL锁,使用tryLock(权衡使用与否)
  9. 对于单节点 redis 并发 差不多十万,如果是上百万并发同时访问redis 不一定能抗住,会导致缓存雪崩。需要本地缓存架构解决。

代码


@Service
public class ProductService {@Autowiredprivate ProductDao productDao;@Autowiredprivate RedisUtil redisUtil;@Autowiredprivate Redisson redisson;public static final Integer PRODUCT_CACHE_TIMEOUT = 60 * 60 * 24;public static final String EMPTY_CACHE = "{}";public static final String LOCK_PRODUCT_HOT_CACHE_PREFIX = "lock:product:hot_cache:";public static final String LOCK_PRODUCT_UPDATE_PREFIX = "lock:product:update:";public static Map<String, Product> productMap = new ConcurrentHashMap<>();@Transactionalpublic Product create(Product product) {Product productResult = productDao.create(product);redisUtil.set(RedisKeyPrefixConst.PRODUCT_CACHE + productResult.getId(), JSON.toJSONString(productResult),genProductCacheTimeout(), TimeUnit.SECONDS);return productResult;}@Transactionalpublic Product update(Product product) {Product productResult = null;//RLock updateProductLock = redisson.getLock(LOCK_PRODUCT_UPDATE_PREFIX + product.getId());RReadWriteLock readWriteLock = redisson.getReadWriteLock(LOCK_PRODUCT_UPDATE_PREFIX + product.getId());RLock writeLock = readWriteLock.writeLock();writeLock.lock();try {productResult = productDao.update(product);redisUtil.set(RedisKeyPrefixConst.PRODUCT_CACHE + productResult.getId(), JSON.toJSONString(productResult),genProductCacheTimeout(), TimeUnit.SECONDS);productMap.put(RedisKeyPrefixConst.PRODUCT_CACHE + productResult.getId(), product);} finally {writeLock.unlock();}return productResult;}public Product get(Long productId) throws InterruptedException {Product product = null;String productCacheKey = RedisKeyPrefixConst.PRODUCT_CACHE + productId;product = getProductFromCache(productCacheKey);if (product != null) {return product;}//DCLRLock hotCacheLock = redisson.getLock(LOCK_PRODUCT_HOT_CACHE_PREFIX + productId);hotCacheLock.lock();//boolean result = hotCacheLock.tryLock(3, TimeUnit.SECONDS);try {product = getProductFromCache(productCacheKey);if (product != null) {return product;}//RLock updateProductLock = redisson.getLock(LOCK_PRODUCT_UPDATE_PREFIX + productId);RReadWriteLock readWriteLock = redisson.getReadWriteLock(LOCK_PRODUCT_UPDATE_PREFIX + productId);RLock rLock = readWriteLock.readLock();rLock.lock();try {product = productDao.get(productId);if (product != null) {redisUtil.set(productCacheKey, JSON.toJSONString(product),genProductCacheTimeout(), TimeUnit.SECONDS);productMap.put(productCacheKey, product);} else {redisUtil.set(productCacheKey, EMPTY_CACHE, genEmptyCacheTimeout(), TimeUnit.SECONDS);}} finally {rLock.unlock();}} finally {hotCacheLock.unlock();}return product;}private Integer genProductCacheTimeout() {return PRODUCT_CACHE_TIMEOUT + new Random().nextInt(5) * 60 * 60;}private Integer genEmptyCacheTimeout() {return 60 + new Random().nextInt(30);}private Product getProductFromCache(String productCacheKey) {Product product = productMap.get(productCacheKey);if (product != null) {return product;}String productStr = redisUtil.get(productCacheKey);if (!StringUtils.isEmpty(productStr)) {if (EMPTY_CACHE.equals(productStr)) {redisUtil.expire(productCacheKey, genEmptyCacheTimeout(), TimeUnit.SECONDS);return new Product();}product = JSON.parseObject(productStr, Product.class);redisUtil.expire(productCacheKey, genProductCacheTimeout(), TimeUnit.SECONDS); //读延期}return product;}}

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

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

相关文章

Bazel构建工具介绍

Android开发我们主要用到的编译器是Java的Java编译器以及C/C++的gcc/clang编译器。对应Java层构建工具最初是Ant,后面Maven以及gradle;C/C++构建工具主要是make/cmake,做过系统开发或者chromeium,可能还用过ninjia、gclient、mm等。最近在编译Android平台的tensorflow lite…

Gobject tutorial 十一

参考&#xff1a;GObject – 2.0 Generic Value Container GValue结构体是一个变量容器,它包含一个类型成员和类型对应的值。其定义如下&#xff1a; /*** GValue:* * An opaque structure used to hold different types of values.** The data within the structure has pr…

ChatTTS源码部署

感谢阅读 默认已完成的操作准备工作下载源码安装依赖下载补丁(报错在运行) 界面展示(discord上有各种补丁&#xff0c;我的加了UI补丁和音色增强)提示词常用&#xff08;这个每个音基本都能生效&#xff09;语调类语速类情感类 默认已完成的操作 python版本>3.9 cuda版本的…

supersocket的app层源码解析

基础结构 #mermaid-svg-Q1MUtx0YWtvpRVNw {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Q1MUtx0YWtvpRVNw .error-icon{fill:#552222;}#mermaid-svg-Q1MUtx0YWtvpRVNw .error-text{fill:#552222;stroke:#552222;}#…

《化工管理》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问&#xff1a;《化工管理》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第一批认定学术期刊。 问&#xff1a;《化工管理》级别&#xff1f; 答&#xff1a;国家级。主办单位&#xff1a;中国石油和化学工业联合会 主管单位&…

国产操作系统上配置ssh互信 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统上配置ssh互信 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在国产桌面操作系统上配置SSH互信的文章。SSH&#xff08;Secure Shell&#xff09;是一种安全协议&#xff0c;用于在不安全的网络上安全地…

uniapp app分享页面到微信的功能方法

最近开发uniapp app项目时&#xff0c;有分享页面的功能需求&#xff0c;因此&#xff0c;给大家分享一下&#xff0c;在uniapp环境里&#xff0c;是如何分享页面到微信H5页面的。 如上图所示&#xff1a;app主体代码就是这样了&#xff0c;查看相应配置就可以&#xff0c;同时…

Swoole v6 能否让 PHP 再次伟大?

大家好&#xff0c;我是码农先森。 现状 传统的 PHP-FPM 也是多进程模型的的运行方式&#xff0c;但每个进程只能处理完当前请求&#xff0c;才能接收下一个请求。而且对于 PHP 脚本来说&#xff0c;只是接收请求和响应请求&#xff0c;并不参与网络通信。对数据库资源的操作…

图的最短路径算法:原理与实现

图的最短路径算法&#xff1a;原理与实现 在图论中&#xff0c;最短路径算法用于找到图中从一个顶点到另一个顶点的最短路径。常见的最短路径算法包括Dijkstra算法、Bellman-Ford算法和Floyd-Warshall算法。以下是每个算法的详细讲解及其Java实现。 1. Dijkstra算法 原理&am…

Android (已解决)Execution failed for task ‘:app:lint‘

文章目录 一、错误原因二、解决方法 一、错误原因 这个错误信息表示在执行 Lint 检查时发现了错误&#xff0c;导致构建过程被中断。Lint 是一个用于检测 Android 项目中潜在问题的工具&#xff0c;比如性能、安全性、可用性等方面的问题。当Lint检查到严重错误时&#xff0c;…

RabbitMQ如何保证消息可靠

解决办法&#xff1a; 1、做好消息确认机制&#xff08;pulisher、consumer[手动ACK]&#xff09; 2、每一个发送的消息都在数据库做好记录。定期将失败的消息再次发送一遍 消息确认机制&#xff1a; 生产者确认模式&#xff1a;确认消息是否发送到broker&#xff0c;失败…

20240627(26.4) 财经要闻汇总

重点关注 ► 发改委&#xff1a;我国金融规模体系已经很大了&#xff0c;但融资结构还有待改善。耐心资本的培育对于促进我国创业投资高质量发展和实现高水平科技自立自强至关重要。除了充分尊重市场规律以外&#xff0c;政府这只“有形的手”也可以发挥重要作用&#xff0c;引…

【FPGA-常见问题及解决方案】

1、VIVADO的License无法加载&#xff1a;license文件必须在英文路径&#xff1b; 2、例程代码路径不能过长&#xff0c;也不允许有中文路径&#xff01;&#xff01;&#xff01; 3、明明加载了license&#xff0c;license也正确&#xff0c;例程无法完成综合&#xff1a;这种情…

“北京到底有谁在啊”影视APP开发,解锁最简单的快乐

随着电视剧《玫瑰的故事》在腾讯视频APP热播&#xff0c;APP也增加了很多热度&#xff0c;一款丰富的影视APP&#xff0c;无论是热门大片、经典影视剧、还是最新综艺节目&#xff0c;能畅享无限精彩的影视内容&#xff01; 开发影视APP&#xff0c;需要专业的技术服务商来解决…

1500平方米气膜羽毛球馆的造价分析—轻空间

随着全民健身热潮的兴起&#xff0c;气膜羽毛球馆因其良好的空气质量、恒温恒湿的环境和快捷的建设速度&#xff0c;受到了越来越多人的欢迎。建造一个1500平方米的气膜羽毛球馆涉及多个方面的费用&#xff0c;包括场地准备、设备材料、安装施工、配套设施等。轻空间将详细分析…

【设计模式】【结构型7-1】【代理模式】【动态代理】【静态代理】

文章目录 代理模式静态代理第一步 创建接口第二步 创建需要代理的对象第三步 创建代理对象 使用 动态代理jdk动态代理cjlib动态代理 代理模式 代理 是结构型 通过继承&#xff0c;或者实现相同的接口来进行增强和监控 经典的使用 spring aop&#xff0c;mybatis dao层 静态代…

数据清洗的艺术:Python中的Pandas妙用

1. 引言 凡事总须研究&#xff0c;才会明白。在这信息泛滥的时代&#xff0c;数据如同一片混沌的荒原&#xff0c;若不经雕琢&#xff0c;便难以显现其真面目。而对于程序员而言&#xff0c;数据清洗的过程&#xff0c;正是从混沌到秩序的一次次锤炼。 2. 数据清洗的必要性 …

Docker制作Python项目镜像

Docker制作Python项目镜像 背景DockerfileDockerfile内容阐释 制作镜像迁移镜像启动容器 背景 在离线环境部署Python项目&#xff0c;出了需要安装对应版本的Python环境&#xff0c;还需要在项目启动前下载项目所需要的依赖。如果后面的迭代依赖有所更新&#xff0c;在离线环境…

AutoEncoder简介

1.介绍 作为一种无监督或者自监督算法&#xff0c;自编码器本质上是一种数据压缩算法。 编码器&#xff1a; 输入图像&#xff08;在这个例子中是一个28x28像素的数字“9”&#xff09;首先被输入到编码器中。编码器的任务是将这个输入压缩成一个更小的、密集的表示形式&…

docker配置国内镜像加速器

1、搜索阿里云 2、搜索容器镜像服务 点击管理控制台 配置镜像加速器