架构学习笔记——缓存篇

架构篇17:高性能缓存架构 本篇我们来分析下缓存的架构设计要点。 阅读详情

服务器缓存,是由计算机硬件系统中的缓存扩展而来,是一种大幅度提高读取速度的机制。在架构设计实践中,缓存往往用于在高并发场景下缓解数据库压力。


目录


1.缓存的应用场景

类似于硬件系统中的缓存,应用架构中的缓存的作用同样是加速读的速度。此外,缓存系统往往独立于数据库,因此缓存与数据库中的数据在到达下一个同步时间节点前,两者的数据可能会产生不一致的情况。综上两点,缓存的应用场景主要是以下两点:

  • 系统的读请求数量远大于写请求数量
  • 系统对实时数据一致性的要求不是非常高

2.缓存系统设计模式及其问题

根据不同缓存系统在设计时,面对读请求和写请求不同的数据访问、更新操作次序,分为三种模式:

  • Cache Aside Pattern
  • Read/Write Through Pattern
  • Write Behind Caching

2.1 Cache Aside Pattern

Cache Aside Pattern,即缓存旁路模式,是最常用的缓存设计模式。

2.1.1 Cache Aside Read

缓存旁路模式的读请求按照命中与否分为两种,如下图:

  • 缓存命中:直接从缓存中读取数据并返回
  • 缓存失效:从数据库中读取数据,放到缓存中并返回
Created with Raphaël 2.1.2 读请求 缓存命中 从缓存读 响应 从数据库读 写入缓存 yes no
2.1.2 Cache Aside Write

缓存旁路模式的写请求,是先更新数据库,再淘汰缓存,如下图:

Created with Raphaël 2.1.2 写请求 更新数据库 淘汰缓存 结束(或返回ACK)
2.1.3 缓存淘汰与更新的取舍

在缓存旁路模式的写请求中,进行的操作是淘汰缓存,那么为什么不是更新缓存呢?考虑并发写场景,如果是更新缓存的话,可能会发生以下情况:

Created with Raphaël 2.1.2 调用方 调用方 服务 服务 数据库 数据库 缓存 缓存 write_req A write_req B A.update_db B.update_db B.update_cache A.update_cache

两个写请求A和B并发执行,在更新数据库时,先执行了A更新后B更新,此时数据库内的数据为B更新后的结果;在更新缓存时,先执行了B更新,后执行了A更新,此时缓存内的数据为A更新后的结果,与数据库内的数据发生不一致。发生这个问题后,在一段时间内(缓存过期,或是下一个写请求到来),调用方获取到的数据全都是脏数据。

2.1.4 先淘汰缓存再更新数据库的问题

如果将缓存旁路模式的写请求的顺序交换,变成先淘汰缓存,再更新数据库会发生什么问题呢?考虑并发读写场景,先淘汰缓存再更新数据库,可能会发生以下情况:

Created with Raphaël 2.1.2 调用方 调用方 服务 服务 缓存 缓存 数据库 数据库 write_req A read_req B A.evict_cache B.read_cache(failed) B.read_db A.update_db B.write_cache

两个请求:写请求A和读请求B并发执行。写请求A先淘汰缓存,随后读请求B访问缓存必然读不到数据,需要从数据库读取数据。随后,读请求B先于写请求A从数据库中读到数据,并将数据放入缓存中,随后写请求B更新了数据库。此时,缓存中为写请求A更新前的数据,而数据库中是写请求A更新后的数据,两者发生数据不一致问题。同样的,在一段时间内,调用方获取到的数据全都是脏数据。

2.1.5 读写并发数据不一致

同样是并发读写的情况,缓存旁路模式似乎也会存在数据不一致问题:

Created with Raphaël 2.1.2 调用方 调用方 服务 服务 缓存 缓存 数据库 数据库 write_req A read_req B B.read_cache(failed) B.read_db A.update_db A.evict_cache B.write_cache

发生了数据不一致的问题,缓存里是读请求B从数据库中读到并写入的旧数据,数据库中是写请求A更新后的数据。

对于数据库而言,读请求(select操作)相较于写请求(update)快得多;在上述案例中,读请求必须先于写请求从数据库中读到数据,再晚于写请求淘汰缓存,同时发生的概率很低。可以通过设置一个较小的缓存过期时间,或是使用数据库日志订阅工具订阅binlog实现延时淘汰缓存,来减少会从缓存中读到脏数据的时间。

2.2 Read/Write Through Pattern

Read/Write Through Pattern,即读/写穿透模式。在读/写穿透模式中,缓存具有更多的“自主权”,服务仅从缓存中取数据而不访问数据库,由缓存自己负责更新、淘汰数据以维持数据一致性。

2.2.1 Read Through

读穿透按照命中与否分为两种,如下图:

  • 缓存命中:直接从缓存中读取数据并返回
  • 缓存失效:通知缓存从数据库取数据更新缓存,再从缓存中读取
Created with Raphaël 2.1.2 读请求 缓存命中 从缓存读 响应 缓存读数据库 开辟缓存块存数据 从缓存读 响应 yes no
2.2.2 Write Through

写穿透类似于读穿透,同样分为缓存命中和缓存失效两种情况,如下图:

  • 缓存命中:直接更新缓存,由缓存负责更新数据库
  • 缓存失效:直接更新数据库
Created with Raphaël 2.1.2 写请求 缓存命中 更新缓存 同步到数据库 结束(或返回ACK) 更新数据库 yes no

2.3 Write Behind Caching Pattern

Write Behind Caching Pattern,类似于linux内核中页缓存的write back机制,是由缓存保持数据,并批量异步更新到数据库中的模式。这种设计模式在设计上缓存与数据库在大部分时间都是不一致的,但是所有的请求只读缓存,所以对服务整体而言不会读到脏数据。

2.3.1Read
Created with Raphaël 2.1.2 读请求 缓存命中 响应 开辟缓存块 从数据库读 写入缓存块 响应 yes no
2.3.2 Write

写请求与读请求类似,同样要根据命中缓存与否开辟新的缓存块:

Created with Raphaël 2.1.2 写请求 缓存命中 更新缓存 结束(或返回ACK) 开辟缓存块 写入缓存 yes no
2.3.3 开辟缓存块

在开辟缓存块时,考虑到存在这种情况:缓存的空间已被用尽,需要淘汰掉部分缓存来缓存新的数据(如redis使用的是LRU算法)。此时,需要考虑被淘汰的数据是否已经在数据库中存在,需要进行一次判定:

Created with Raphaël 2.1.2 开辟缓存块 缓存块为空 开辟完成 原数据更新到数据库 yes no

3. 缓存系统常见问题

3.1 缓存穿透

缓存穿透是指,某一个本不存在的key被高并发访问,导致服务不断访问数据库,但由于返回空结果集而不放入到缓存中,使得缓存失去意义。

  • 缓存空对象:即服务器返回空结果集时依然放入缓存中,设置值为空标识符(可以是null(如果允许)、空字符串、空对象、空集合等)
  • 黑名单:使用黑名单机制过滤不存在的key,使得不存在的key直接被挡在服务外

3.2 并发缓存失效读请求

在服务并发较高的时候,如果一个key在失效以后被多次并发访问,会发生在数据库上出现一个高并发读的情况,如下图:

Created with Raphaël 2.1.2 调用方 调用方 服务 服务 缓存 缓存 数据库 数据库 read_req A A.read_cache(failed) A.read_db read_req B B.read_cache(failed) B.read_db read_req ... A.write_cache

可见,在第一个到达的读请求从数据库中读到数据并放入缓存之前,期间所有的读请求全部都会访问数据库获取数据,一方面使得数据库的压力陡然增加,另一方面大量消耗了服务的性能,使得服务对其他读请求的执行效率降低。

解决这一问题的主要方法是,缓存查询操作上锁,将后到的相同读请求阻塞,直到第一个读请求将数据库中的数据更新到缓存中,如下图:

Created with Raphaël 2.1.2 调用方 调用方 服务 服务 缓存 缓存 数据库 数据库 read_req A A.read_cache(failed) A.read_db read_req B locked read_req ... locked A.write_cache B.read_cache(succeeded) ....read_cache(succeeded)

锁虽然阻塞了后续一段时间内所有的读请求,但时间上总的时间并没有发生变化,因为后续所有的读请求都成功访问了缓存,可以直接从缓存中读取数据返回。

3.3 缓存雪崩

缓存雪崩是指很多key在同一时间过期,导致在高并发到来时缓存失效,所有的压力都压在数据库上。针对这一问题分两类情况讨论:可预期高并发和不可预期高并发。

  • 在可预期高并发场景下(如双十一的秒杀、游戏维护开服),既然高并发的到来使可预期的,那么就可以通过预先缓存的方式应对高并发。
  • 在不可预期的高并发场景下,优化的方向是避免大量的key在同一时间过期。可以通过添加随机变量的方式来避免集中过期的情况,即失效时间=基础失效时间+随机值,这样每一个缓存的过期时间就会相互错开,从而避免集中失效的情况发生。

3.4 数据库主从同步间隔导致数据不一致

在数据库主从、主库只负责写、从库只负责读的场景下,亦容易发生缓存数据不一致问题,场景如下:

Created with Raphaël 2.1.2 调用方 调用方 服务 服务 数据库_主 数据库_主 缓存 缓存 数据库_从 数据库_从 write_req A read_reqB A.update_db A.evict_cache B.read_cache(failed) B.read_db B.write_cache db.synchronize

两个并发请求:写请求A和读请求B,A更新数据库后淘汰缓存,此时B读取缓存失败,从从库中读到尚未同步的旧数据并写入缓存中,缓存与数据库发生不一致。

这个场景的优化方向是减少数据不一致情况存在的时间。使用数据库日志订阅工具订阅从库的binlog日志,当从库的日志更新时,使用订阅工具淘汰缓存中的数据。这样可以保证间隔大于主从数据库同步间隔的读请求一定不会读到脏数据,这个同步时间可以根据需求设置为一个很短的时间,MySQL的默认同步时间间隔是1分钟。

4. 总结

缓存本质上是一种为了提高访问效率而牺牲强一致性的设计,因此针对有强一致性要求的系统,使用缓存是不那么合适的;同样的,针对于频繁写的系统也是不适合使用缓存的。缓存的不一致性主要表现在并发读写的场景下,尤其是数据库层使用了主从读写分离的架构。

关于缓存的效果,一定是命中率越高越好,在缓存的key不是由运维人员根据请求分析后自主决定的情况下,决定缓存命中情况的主要是缓存的失效时间(过期时间)。失效时间太短,就可能导致每过一段时间同一个key就需要到数据库中查询一遍,使命中率降低;失效时间太长,就可能导致缓存中大量的key既不被访问又不失效,内存资源被大量浪费,同时新的key在缓存时需要使用LRU之类的算法重新分配内存空间,导致缓存性能的下降。


参考文献

  1. http://www.cnblogs.com/llzhang123/p/9037346.html
  2. https://mp.weixin.qq.com/s/4J3oM1j5hcLq4w4TdSEMPg
  3. https://blog.cdemi.io/design-patterns-cache-aside-pattern/
  4. https://www.jianshu.com/p/d96906140199
  5. https://docs.microsoft.com/en-us/azure/architecture/patterns/cache-aside
  6. http://www.cnblogs.com/llzhang123/p/9037346.html
  7. https://www.cnblogs.com/dinglang/p/6133501.html
  8. https://www.cnblogs.com/uglyliu/p/6223253.html
  9. https://www.jianshu.com/p/8a032aa3a8e9
常见缓存架构原理 互联网公司在缓存架构上是区分很大的,往往是根据企业的业务量来进行选择的,可以看如下图 在传统的小型互联网公司,采用网页静态化技术,freemarker来加快用户的体验速度,从来来提升响应,但是如果出现了缓存血崩,缓存击穿那么对数据库将会造成很大的压力,可能导致整个架构无法使用 一 缓存击穿   缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写... 阅读详情

相关推荐

基于R语言的现代贝叶斯统计学方法(贝叶斯参数估计、贝叶斯回归、贝叶斯计算)实践

贝叶斯统计学是一门基本思想与传统基于频率思想的统计学完全不同的统计学方法;它以其灵活性和先进性在现代的统计学中占据着重要的地位。贝叶斯统计学是开展科学研究不可缺少的重要手段,但是,因为其思想、技术和方法都与传统统计学有着较大区别;且其计算中涉及马尔科夫、蒙特卡罗和吉布斯采样等现代计算方法,对使用者经验和能力构成了很大的挑战。

AAIshangyanxiu的博客 681

旁路缓存(Cache-aside)

1)什么是旁路缓存 旁路缓存策略以数据库(Hbase,redis)中的数据为准,缓存中的数据是按需加载的,它可以分为读策略和写策略。 读策略: 从缓存中读取数据;如果缓存命中,则直接返回数据;如果缓存不命中,则从数据库中查询数据;查询到数据后,将数据写入到缓存中,并且返回给用户。 写策略: 更新数据库中(HBASE,Redis)的记录;删除缓存记录。 2)缓存和数据库的数据一致性问题 错误一:先失效缓存,后更新数据库 1)请求A删除缓存数据 2)请求B查询缓存,未命中 3)请求B往数

Asunakiritolove的博客 1万+

一文解读DeepSeek训练数据集

本文重点以DeepSeek为例,详细介绍预训练数据集相关内容。大语言模型LLM(如DeepSeek、ChatGPT、文心一言等)的“智慧”源于它们学习的海量数据集。简单来说,数据集就是模型的“知识库”,通常由互联网公开的文本、图片、视频等。这些数据需满足两个特点:规模大和多样性。规模大是指数据量可达千亿级词汇,让模型学习复杂规律;多样性则涵盖多领域(如科技、文学)、多语言、多形式(对话、新闻),帮助模型适应不同场景。例如,训练数据中既有百科知识,也有日常对话,模型才能既解答专业问题,又能闲聊。

u013891230的博客 7090

【架构师之路】深入了解架构中常见的4种缓存模式及其实现

Cache-Aside(旁路缓存)模式,又叫(懒加载)模式,在这种模式下,缓存的读取和写入由应用程序直接管理。应用程序首先尝试从缓存中读取数据,若缓存未命中,则从数据库中加载数据并将其存储在缓存中;对于更新操作,应用程序直接更新数据库,并更新或删除缓存中的相关数据。Read-Through 模式下,缓存层自动管理数据的读取。当应用程序请求数据时,缓存层会先检查缓存,如果缓存命中则直接返回数据;如果缓存未命中,则缓存层自动从数据库加载数据,并将数据存入缓存。Cache-Aside模式中,

代码时光 3963

从安装Eclipse 开始 开发第一个 CDS View

一篇超级简单快速的 创建CDS VIEW 入门步骤介绍文章。

IT小职员 4250

Dobot Magician机械臂二次开发指南:如何利用Python脚本和I/O接口实现自动化任务

本文详细介绍了Dobot Magician机械臂的二次开发方法,重点讲解如何通过Python脚本和I/O接口实现高级自动化任务。内容包括开发环境搭建、运动控制API解析、I/O接口应用以及典型场景实现,帮助开发者充分发挥Dobot Magician的潜力,适用于工业自动化、教育科研等领域。

weixin_26968079的博客 267

Redis之旁路缓存

Redis之旁路缓存Redis作为缓存中间件早已深入人心,但我们有没有想过Redis为什么能作为缓存呢?Redis到底怎样使用缓存呢?本篇文章详细聊聊。Redis为什么能作为缓存聊Redis为什么能作为缓存前先需要清楚缓存的作用,我们在很多场景都有接触过缓存就如Redis本身的输入输出缓存、复制缓冲区、复制积压缓存区等等,又如操作系统本身的LLC,page cache缓存等等,这些缓存的主要作用是什么呢?是在一个多层次系统中平衡上下级系统的速度差异。这里以操作系统为例说明,操作系统的存储结构一般为CPU、内

zzf1233的博客 2688

PPPoE上网配置不求人:华为路由器命令行操作指南(2023最新版)

本文提供2023年最新的华为路由器PPPoE上网配置命令行操作指南。通过详细的步骤讲解,从连接设备、创建拨号接口、绑定PPPoE客户端到配置内网与NAT,手把手教你完成配置,并附有验证排错方法,助你轻松实现稳定上网。

s4t5u6v的博客 682

旁路缓存模式(Cache-Aside Pattern)如何保证一致性的问题

经典缓存模式:旁路缓存模式 (Cache-Aside Pattern)读缓存:接收用户读请求 --> 从缓存中查询数据 --> 命中缓存数据直接返回 --> 未命中则从数据库中查询数据。写缓存:接收用户写请求 --> 先写入数据库 --> 再写入缓存。读/写穿透模式 (Read/Write Through)将缓存操作(具体来说是数据读写操作)封装成一个缓存服务(Cache Provider),所有数据的读写操作都调用这个缓存服务。

AHAO的博客 3651

基于LightGBM和多模型融合的量化交易研究:沪深300为例【附代码】

📊 数据科学与大数据专业 | 数据分析与模型构建 | 数据驱动决策✨ 专业领域:数据挖掘与清洗大数据处理与存储技术机器学习与深度学习模型数据可视化与报告生成分布式计算与云计算数据安全与隐私保护💡 擅长工具:Python/R/Matlab 数据分析与建模Hadoop/Spark 大数据处理平台SQL数据库管理与优化Tableau/Power BI 数据可视化工具TensorFlow/PyTorch 深度学习框架✅数据科学与大数据技术毕业论文【数据】

lagougongzuoshi的博客 1671

搭建ipv6并发代理池

我开了个知识星球,把将本期搭建写成shell脚本已放到了里面,有需要的小伙伴可以自行去取,jd的参数,阿里bxet纯算、快手滑块,Pdd—Anti,ikuai,b站login之-极验3文字,某音ab,瑞数456vmp补环境等等,主要是某些大佬加我问成品,很多人都打着白嫖的手段去加我好友为目的,问完基本就以后没有任何的交集,这样的交好友雀氏没有任何意义。不如我直接开个星球,里面直接放我逆向的成品以及逆向的思路,这样大家各取所需,我也有点收益,意义更明确点,免得浪费大家的时间。我是pve下的ubuntu。

weixin_44697518的博客 1473

三种缓存模式

【代码】三种缓存模式。

weixin_44645022的博客 1199

WS2812和homeassistant握手

本文学习了WS2812和homeassistant握手,后期会分享更多有趣物联网的操作从而实现对外部世界进行感知,充分认识这个有机与无机的环境,科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。...

vor234的博客 814

全网推荐的《MySQL性能调优与架构设计》笔记,MySQL性能调优入门看这篇就够了

作为最为流行的开源数据库软件之一,MySQL 数据库软件已经是广为人知了,同时项目中几乎无处不在,面试时又100%会问到的技术点,非MySQL莫属了。因此在这里给大家准备了这篇《MySQL性能调优与架构设计》学习笔记。

weixin_51702416的博客 2万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

高性能web系统架构方案

第一部分 客户端篇 1.压缩js、css,将js的引入放在</html>之前; 2.合并一个页面下的js/css文件,压缩传输.(SquishIt)相关博文 3.ajax技术应用.ajax可以做到精准定量的请求,可以减少非必须资源的请求和重复请求. 4.页面压缩传输技术(将页面数据进行压缩.IIS支持gzip压缩) 5.统一将js/css 图片等放到一个单独的服务器上. ...

weixin_30355437的博客 131

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

六、企业级架构缓存篇之memcached

六、企业级架构缓存篇之memcached

weixin_61428407的博客 1936

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

《多级缓存架构设计与实现全解析》

本文全面介绍了多级缓存架构的设计与实现,通过JVM进程缓存(Caffeine)、Redis缓存、Nginx本地缓存和Tomcat缓存的四级架构,显著提升系统性能。详细讲解了Lua在OpenResty中的应用、Nginx业务逻辑开发、缓存预热策略及Canal实现数据库与缓存同步的方案。该系统能有效降低数据库压力,提高响应速度,保证数据最终一致性,适用于高并发场景。文章涵盖从理论到实践的完整实现过程,包括缓存分类比较、Caffeine API使用、Lua语法基础、负载均衡优化等关键技术点。

yh云想的博客 2597

Java 架构 19:缓存架构设计(本地缓存 + 分布式缓存)

本文探讨了Java应用中本地缓存与分布式缓存的协同架构设计。通过Caffeine实现高性能本地缓存(微秒级响应),结合Redis构建分布式共享缓存,形成多级缓存防御体系。文章详细介绍了: 缓存价值:降低数据库压力,提升系统吞吐(案例显示性能提升25倍) 架构设计:本地缓存(L1)处理80%请求,Redis(L2)处理19%,数据库仅1% 技术实现: Caffeine集成与智能淘汰策略 Redis部署与Spring Boot整合 完整商品缓存示例代码 监控优化:缓存命中率统计与性能调优建议 适用于中高级开发者

千淘万漉虽辛苦,吹尽狂沙始到金 2万+

Redis 多级缓存架构学习笔记

本文系统介绍了多级缓存架构设计,包含浏览器、OpenResty本地缓存、Redis分布式缓存、JVM进程缓存和数据库五层结构。重点分析了请求全链路流程和数据更新机制,通过Canal监听binlog实现缓存同步更新,采用主动删除策略保证最终一致性。该架构通过分层缓存显著提升性能,有效拦截70%以上请求,同时具备高可用、高扩展性特点,能应对高并发场景并降低数据库压力。文章还详细阐述了各层缓存的特点、作用及协同机制,为构建高性能系统提供了完整解决方案。

人工智能专业学生 1213

多级缓存架构 | 黑马Redis高级篇

黑马Redis教程-多级缓存笔记。全是硬核知识,这期真的学到很多,Nginx+lua本地缓存+redis+jvm的Caffeine实现的多级缓存架构,用canal实现缓存同步。

weixin_54232666的博客 5565

缓存架构方案:Caffeine + Redis 双层缓存架构深度解析

Caffeine是一个基于 Java 8 的高性能本地缓存库,底层采用支持自动加载、刷新、过期。高并发读写性能优秀。适用于热点数据快速访问场景。Redis支持持久化、集群部署、Lua脚本等高级功能。提供丰富的数据结构(String、Hash、List、Set、Sorted Set)。适用于跨节点共享缓存数据的场景。Caffeine + Redis 的双层缓存架构是一种兼顾高性能与一致性的缓存解决方案,特别适合微服务架构下需要快速响应且数据共享的业务场景。

weixin_50236329的博客 1842

16、CPU缓存架构

CPU高速缓存可以分为一级缓存,二级缓存,部分高端CPU还具有三级缓存,每一级缓存中所储存的全部数据都是下一级缓存的一部分,这三种缓存的技术难度和制造成本是相对递减的,所以其容量也是相对递增的。缓存一致性协议会通过处理器之间的通信,确保在一个处理器修改了某个数据后,其他处理器缓存中的该数据会被更新或者失效,从而保证在多个处理器同时对同一个数据进行操作时,它们所看到的数据始终是一致的。当特定数据被多个缓存共享时,处理器修改了共享数据的值,更改必须传播到所有其他具有该数据副本的缓存中。

sproutBoy的博客 2712

Redis缓存架构实战

本文探讨了Redis在高并发场景下的应用策略,重点分析了缓存热点数据的关键技术要点。文章首先介绍了基础案例工程,展示了缓存与数据库的增改查操作。随后提出数据冷热分离策略,通过设置缓存过期时间+续期机制来自动筛选热点数据。针对缓存击穿问题,建议采用随机过期时间分散key过期压力。对于缓存穿透问题,推荐缓存空值来缓解恶意请求攻击。全文围绕高并发场景下的Redis优化展开,提供了从架构设计到具体实现的解决方案。

西岭千秋雪的博客 1254

三级缓存架构

三级缓存架构是一种通过分层缓存设计来优化系统性能、降低数据库负载、提高数据访问效率的解决方案,尤其适用于高并发、高吞吐量的业务场景(如电商、社交平台、实时推荐等)。其核心思想是通过多级缓存逐层过滤请求,减少对底层存储的直接访问。三级缓存架构通过分层设计平衡性能、一致性与复杂度,是应对高并发场景的经典方案。实际应用中需结合业务特点灵活调整各级缓存策略,并辅以监控工具(如Prometheus + Grafana)持续优化命中率和响应时间。3. 广播失效本地缓存(如MQ通知)2. 读取分布式缓存。

保持热爱。 1779

多级缓存架构设计

应用 Nginx 本地内存Redis 缓存JVM 内存DB接入层 Nginx:处理入口流量,用作流量分发应用层 Nginx:接近业务层,处理业务逻辑,用作热点缓存的读取Nginx 作为高性能的 Web 服务器,经常被作为反向代理服务器用作负载均衡,这里多增加了一层应用层 Nginx,用来处理热点缓存数据,相比于 Tomcat 集群的本地内存来说,可承接的流量更高。

qq_45260619的博客 1234
下一篇: 机器学习笔记(一)——模型评估方法与性能度量
zeroized
博客等级 码龄10年 3粉丝 2原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值