全栈工程师修炼指南
熊燚(四火)
Oracle首席软件工程师
立即订阅
2286 人已学习
课程目录
已更新 43 讲 / 共 40 讲
0/4登录后,你可以任选4讲全文学习。
课前必读 (3讲)
开篇词 | 从成长角度看,为什么你应该成为全栈工程师?
免费
学习路径 | 怎样成为一名优秀的全栈工程师?
导读 | 如何学习这个专栏?
第一章 网络协议和 Web 接口 (6讲)
01 | 网络互联的昨天、今天和明天:HTTP 协议的演化
02 | 为HTTP穿上盔甲:HTTPS
03 | 换个角度解决问题:服务端推送技术
04 | 工整与自由的风格之争:SOAP和REST
05 | 权衡的艺术:漫谈Web API的设计
06 | 特别放送:北美大厂如何招聘全栈工程师?
第二章 欢迎来到 MVC 的世界 (7讲)
07 | 解耦是永恒的主题:MVC框架的发展
08 | MVC架构解析:模型(Model)篇
09 | MVC架构解析:视图(View)篇
10 | MVC架构解析:控制器(Controller)篇
11 | 剑走偏锋:面向切面编程
12 | 唯有套路得人心:谈谈Java EE的那些模式
13 | 特别放送:选择比努力更重要
第三章 从后端到前端 (7讲)
14 | 别有洞天:从后端到前端
15 | 重剑无锋,大巧不工:JavaScript面向对象
16 | 百花齐放,百家争鸣:前端MVC框架
17 | 不一样的体验:交互设计和页面布局
18 | 千言万语不及一幅画:谈谈数据可视化
19 | 打开潘多拉盒子:JavaScript异步编程
20 | 特别放送:全栈团队的角色构成
第四章 数据持久化 (7讲)
21 | 赫赫有名的双刃剑:缓存(上)
22 | 赫赫有名的双刃剑:缓存(下)
23 | 知其然,知其所以然:数据的持久化和一致性
24 | 尺有所短,寸有所长:CAP和数据存储技术选择
25 | 设计数据持久层(上):理论分析
26 | 设计数据持久层(下):案例介绍
27 | 特别放送:聊一聊代码审查
第五章 寻找最佳实践 (6讲)
28 | Ops三部曲之一:配置管理
29 | Ops三部曲之二:集群部署
30 | Ops三部曲之三:测试和发布
31 | 防人之心不可无:网站安全问题窥视
32 | 和搜索引擎的对话:SEO的原理和基础
33 | 特别放送:聊一聊程序员学英语
第六章 专题 (7讲)
34 | 网站性能优化(上)
35 | 网站性能优化(下)
36 | 全栈开发中的算法(上)
37 | 全栈开发中的算法(下)
38 | 分页的那些事儿
39 | XML、JSON、YAML比较
40 | 全栈衍化:让全栈意味着更多
全栈工程师修炼指南
登录|注册

21 | 赫赫有名的双刃剑:缓存(上)

四火 2019-10-28
你好,我是四火。
从今天开始,我们将继续在基于 Web 的全栈技术上深挖,本章我们介绍持久层。缓存是全栈开发中非常重要的一环,因此我把它放到了数据持久化系列的开篇。
缓存使用好了,会是一把无比锋利的宝剑,特别对于性能的提升往往是立竿见影的;但使用不好就会严重影响系统运行,甚至因为数据一致性问题造成严重的数据错误。这一讲,我将为你介绍缓存的本质以及缓存的应用模式。

缓存的本质

工作中,我们可能每周都会谈到缓存,我们见过各种各样的缓存实现,网上也有各种各样的解释和定义。可是,你觉得,到底什么是缓存呢?
我认为,缓存,简单说就是为了节约对原始资源重复获取的开销,而将结果数据副本存放起来以供获取的方式。
首先,缓存往往针对的是“资源”。我们前面已经多次提到过,当某一个操作是“幂等”的和“安全”的(如果不记得的话请重看 [第 04 讲]),那么这样的操作就可以被抽象为对“资源”的获取操作,那么它才可以考虑被缓存。有些操作不幂等、不安全,比如银行转账,改变了目标对象的状态,自然就难以被缓存。
其次,缓存数据必须是“重复”获取的。缓存能生效的本质是空间换时间。也就是说,将曾经出现过的数据以占据缓存空间的方式存放下来,在下一次的访问时直接返回,从而节约了通过原始流程访问数据的时间。有时候,某些资源的获取行为本身是幂等的和安全的,但实际应用上却不会“重复”获取,那么这样的资源是无法被设计成真正的缓存的。我们把一批数据获取中,通过缓存获得数据的次数,除以总的次数,得到的结果,叫做缓存的命中率。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《全栈工程师修炼指南》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(5)

  • 丁丁历险记
    1. Write-Back 的稳定性是靠中间件来处理的,kafka 是个不错的选择。
    2 读缓存还是数据库,还有个常用套路就是先查依赖(通常依赖的消耗更小,例如只在存储引擎层就可以搞定)
    3 画图工具不错。

    作者回复: 你好,能否进一步解释一下第 2 条?

    2019-11-27
    1
    1
  • Mandalorian
    请问下,Cache-Aside部分中,那个极小概率出现,设计中一般忽略的情形是怎样的?

    作者回复: R1 是读请求,R2 是更新请求:
    1. R1 读缓存,发现已失效,就从数据库里读出旧值 Va;
    2. R2 更新请求,将数据库里的值从 Va 更新为新值 Vb,并将缓存标记为失效;
    3. R1 将 Va 写回缓存,于是缓存中就有了一个过期值 Va,而数据库中是 Vb。

    我说这个情况极小概率出现的原因有这样几个:
    1. 需要缓存自身过期和数据更新几乎同时发生;
    2. 需要 R1 在读出旧值以后,R2 的更新操作全部完成,R1 才将旧值写入缓存,而众所周知从数据库中读数据并写入缓存的操作速度,通常情况下要远高于数据库更新并将缓存标记为失效的操作,因为写操作需要的要求更高,比如需要使用事务等等。当然,这说的是“通常情况”,并不是 说“一定”,不过出问题的概率是非常非常小的。

    2019-11-10
    1
    1
  • Geek_ef0311
    不知道自己想的对不对,高并发的时候会考虑用wirte-back(例如游戏中的某时刻抽奖) ,批量的时候用write/read through 等比较好

    作者回复: 就是 trade-off,write-back 带来高吞吐量的同事,会牺牲一定的一致性(数据库和缓存可能不一致)和持久性(可能存在掉电数据丢失),你说的“高并发的时候”,如果可以做出这样的牺牲,那么就可以考虑这个方法

    2019-11-25
  • pyhhou
    1. 在接下来的项目中会考虑用到 cache-aside 这种模式设计,cache 用的是 Redis,DB 用的是 MongoDB,感觉这种模式比较常见,相对来说不会那么复杂

    2. 根据文中的分析,cache-aside 比较稳健些,导致数据不一致的风险也相对较低,但是对于更新和写操作来说的话,相对较慢,原因也很好解释,这里面涉及了 cache 的访问、DB 的更新、以及 cache 的更新;write-back 的话对于更新和写操作来说效率会更高,吞吐量也更大,但是数据不一致的风险较大。效率和安全,这里又是一个权衡的话题(有点类似 HTTP 和 HTTPS)。个人觉得这两种模式差别主要在更新和写操作上,这就需要根据业务来分析了,如果业务中 95% 以上都是读请求,并且也没有那么高的性能要求,那么其实 cache-aside 就完全够用了,但是对于某些写高于读的系统(比如日志系统),而且要求高性能,那么可以考虑使用 write-back 这种模式
    2019-11-06
  • leslie
    数据写入缓存故而这就是日志的问题啊:现在其实许多数据库模型同样宕机就OVER,纠其根本原因还是许多的不严谨;日志是灾难恢复的主要手段。
           数据库内部查询同样是先看缓存是否有,没有再去重新查找;毕竟缓存速度>内存>磁盘。异步最大的难题是是事务性:这块非关系型数据库处理的都不好。
    2019-10-28
    3
收起评论
5
返回
顶部