26.【学习心得】学习心得-读缓存

本文涉及的产品
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
云原生内存数据库 Tair,内存型 2GB
简介: 【学习心得】学习心得-读缓存

文档参考:书名:《从程序员到架构师:大数据量、缓存、高并发、微服务、多团队协同等核心场景实战》-王伟杰

image.png

前文如下:


23.【学习心得】学习心得-冷热分离概述

24.【学习心得】学习心得-如何分离冷热数据

25.【学习心得】学习心得-基于MySQL的分表分库


1.业务场景:如何将十几秒的查询请求优化成毫秒级


每个电商系统都有个商品详情页。一开始这个页面很简单,只包括商品的图片、介绍、规格、评价等。刚开始,这个页面打开很快,系统运行平稳可靠。


后来,页面中加了商品推荐,即在商品详情页后面显示一些推荐商品的列表。


再后来,页面中加入了最近成交情况,即显示一下某人在什么时候下单了。接着,页面中又加入了优惠活动,即显示这个商品都可以参加哪些优惠活动。


……当时这个系统里面有5万多条商品数据,数据量并不大,但是每次用户浏览商品详情页时都需要几十条SQL语句,经常出现十几秒才能打开详情页的情况。这样的用户体验当然不好。


一个解决办法——分布式缓存,先将所有的缓存数据集中存储在同一个地方,而非重复保存到各个服务器节点中,然后所有的服务器节点都从这个地方读取数据。


那么这个统一存储缓存数据的地方需要使用什么技术呢?这就涉及接下来要讲的缓存中间件技术选型问题了。


2. 缓存中间件技术选型(Memcached,MongoDB,Redis)


先将目前比较流行的缓存中间件Memcached、MongoDB、Redis进行简单对比,见表4-1。

网络异常,图片无法展示
|


比较Redis和Memcached,并从中做出选择。目前,Redis比Memcached更流行,这里总结一下原因,共3点。


(1)数据结构 举个例子,在使用Memcached保存List缓存对象的过程中,如果往List中增加一条数据,则首先需要读取整个List,再反序列化塞入数据,接着再序列化存储回Memcached。而对于Redis而言,这仅仅是一个Redis请求,它会直接帮助塞入数据并存储,简单快捷。


(2)持久化 对于Memcached来说,一旦系统宕机数据就会丢失。因为Memcached的设计初衷就是一个纯内存缓存。通过Memcached的官方文档得知,1.5.18版本以后的Memcached支持Restartable Cache(可重启缓存),其实现原理是重启时CLI先发信号给守护进程,然后守护进程将内存持久化至一个文件中,系统重启时再从那个文件中恢复数据。不过,这个设计仅在正常重启情况下使用,意外情况还是不处理。而Redis是有持久化功能的。


(3)集群 这点尤为重要。Memcached的集群设计非常简单,客户端根据Hash值直接判断存取的Memcached节点。而Redis的集群因在高可用、主从、冗余、Failover等方面都有所考虑,所以集群设计相对复杂些,属于较常规的分布式高可用架构。


3.缓存何时存储数据


使用缓存的逻辑如下。

1)先尝试从缓存中读取数据。

2)若缓存中没有数据或者数据过期,再从数据库中读取数据保存到缓存中。

3)最终把缓存数据返回给调用方。


这种逻辑唯一麻烦的地方是,当用户发来大量的并发请求时,它们会发现缓存中没有数据,那么所有请求会同时挤在第2)步,此时如果这些请求全部从数据库读取数据,就会让数据库崩溃。

数据库的崩溃可以分为3种情况。


1)单一数据过期或者不存在,这种情况称为缓存击穿。解决方案:第一个线程如果发现Key不存在,就先给Key加锁,再从数据库读取数据保存到缓存中,最后释放锁。如果其他线程正在读取同一个Key值,那么必须等到锁释放后才行。关于锁的问题前面已经讲过,此处不再赘述。


2)数据大面积过期或者Redis宕机,这种情况称为缓存雪崩。解决方案:设置缓存的过期时间为随机分布或设置永不过期即可。


3)一个恶意请求获取的Key不在数据库中,这种情况称为缓存穿透。比如正常的商品ID是从100000到1000000(10万到100万之间的数值),那么恶意请求就可能会故意请求2000000以上的数据。这种情况如果不做处理,恶意请求每次进来时,肯定会发现缓存中没有值,那么每次都会查询数据库,虽然最终也没在数据库中找到商品,但是无疑给数据库增加了负担。这里给出两种解决办法。


比如正常的商品ID是从100000到1000000(10万到100万之间的数值),那么恶意请求就可能会故意请求2000000以上的数据。这种情况如果不做处理,恶意请求每次进来时,肯定会发现缓存中没有值,那么每次都会查询数据库,虽然最终也没在数据库中找到商品,但是无疑给数据库增加了负担。这里给出两种解决办法。


①在业务逻辑中直接校验,在数据库不被访问的前提下过滤掉不存在的Key。

②针对恶意请求的Key存放一个空值在缓存中,防止恶意请求骚扰数据库。


4)最后说一下缓存预热。上面这些逻辑都是在确保查询数据的请求已经过来后如何适当地处理,如果缓存数据找不到,再去数据库查询,最终是要占用服务器额外资源的。那么最理想的就是在用户请求过来之前把数据都缓存到Redis中。这就是缓存预热。其具体做法就是在深夜无人访问或访问量小的时候,将预热的数据保存到缓存中,这样流量大的时候,用户查询就无须再从数据库读取数据了,将大大减小数据读取压力。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4月前
|
SQL 缓存 关系型数据库
MySQL技能完整学习列表6、查询优化——3、查询缓存——4、SQL优化技巧
MySQL技能完整学习列表6、查询优化——3、查询缓存——4、SQL优化技巧
94 0
|
3月前
|
存储 缓存 算法
数据结构和算法学习记录——总结顺序表和链表(双向带头循环链表)的优缺点、CPU高速缓存命中率
数据结构和算法学习记录——总结顺序表和链表(双向带头循环链表)的优缺点、CPU高速缓存命中率
38 0
|
1月前
|
缓存 JavaScript
Vue学习之--------编程式路由导航、缓存路由组件、新的钩子函数(4)(2022/9/5)
这篇文章介绍了Vue中编程式路由导航的方法,包括使用`$router.push`、`$router.replace`、`$router.forward`、`$router.back`和`$router.go`进行路由跳转和历史记录操作,以及如何利用`<keep-alive>`组件缓存路由组件,和Vue Router新增的两个生命周期钩子`activated`和`deactivated`的用法及其在项目中的应用和测试结果。
Vue学习之--------编程式路由导航、缓存路由组件、新的钩子函数(4)(2022/9/5)
|
3月前
|
缓存 负载均衡 NoSQL
Redis系列学习文章分享---第十四篇(Redis多级缓存--封装Http请求+向tomcat发送http请求+根据商品id对tomcat集群负载均衡)
Redis系列学习文章分享---第十四篇(Redis多级缓存--封装Http请求+向tomcat发送http请求+根据商品id对tomcat集群负载均衡)
64 1
|
3月前
|
存储 缓存 NoSQL
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
70 1
|
3月前
|
缓存 NoSQL Java
Redis系列学习文章分享---第四篇(Redis快速入门之Java客户端--商户查询缓存+更新+双写一致+穿透+雪崩+击穿+工具封装)
Redis系列学习文章分享---第四篇(Redis快速入门之Java客户端--商户查询缓存+更新+双写一致+穿透+雪崩+击穿+工具封装)
52 0
|
4月前
|
存储 缓存 前端开发
学习和理解前端缓存
前端缓存通过存储重复资源提升网页加载速度,减少服务器压力,优化用户体验。它涉及静态资源(如图片、CSS、JS)的HTTP缓存,动态数据(使用`localStorage`、`IndexedDB`)缓存,用户登录态、页面状态管理,以及预加载缓存。实现方式包括HTTP缓存(强缓存、协商缓存),浏览器存储(localStorage、sessionStorage、IndexedDB),Service Worker和Cache API。在项目中,应根据资源特性和需求选择合适的缓存策略。
|
4月前
|
缓存 NoSQL Java
SpringCache通用缓存学习
SpringCache通用缓存学习
106 1
|
4月前
|
缓存 NoSQL Java
SpringCache通用缓存学习
SpringCache通用缓存学习
|
10月前
|
缓存 NoSQL 关系型数据库
【Redis 系列】redis 学习十二,redis 缓存穿透,缓存击穿,缓存雪崩
【Redis 系列】redis 学习十二,redis 缓存穿透,缓存击穿,缓存雪崩