29.【学习心得】学习心得-写缓存实现思路

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 【学习心得】学习心得-写缓存实现思路

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

image.png

前文如下:


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

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

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

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

27.【学习心得】学习心得-如何更新redis缓存

28.【学习心得】学习心得-写缓存


2.实现思路

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


看起来很简单,但该方案在具体实施过程中要考虑6个问题。


1)写请求与批量落库这两个操作同步还是异步?

2)如何触发批量落库?

3)缓冲数据存储在哪里?

4)缓存层并发操作需要注意什么?

5)批量落库失败了怎么办?

6)Redis的高可用配置。


2.1 写请求与批量落库这两个操作同步还是异步在回答这个问题前,先来对比一下同步与异步。


在回答这个问题前,先来对比一下同步与异步。


对于同步,写请求提交数据后,当前写操作的线程会等到批量落库完成后才开始启动。这种设计的优点是用户预约成功后,可在“我的预约”页面立即看到预约数据;缺点是用户提交预约后,还需要等待一段时间才能返回结果,且这个时间不定,有可能需要等待一个完整的时间窗。


对于异步,写请求提交数据后,会直接提示用户提交成功。这种设计的优点是用户能快速知道提交结果;缺点是用户提交完成后,如果查看“我的预约”页面,可能会出现没有数据的情况。


那到底应该使用哪种设计模式呢?下面再介绍下这两种设计模式的复杂度。


同步的实现原理是写请求提交数据时,写请求的线程被堵塞或者等待,待批量落库完成后再发送信号给写请求的线程, 这个线程获得落库完成的信号后,返回预约成功提示给用户。


不过,这个过程会引出一系列的问题,比如:

1)用户到底需要等待多久? 用户不可能无限期等待下去,此时还需要设置一个时间窗,比如每隔100毫秒批量落库一次。

2)如果批量落库超时了怎么办? 写请求不可能无限期等待,此时就需要给写请求线程的堵塞设置一个超时时间。

3)如果批量落库失败了怎么办? 是否需要重试?多久重试一次?

4)如果写请求一直堵塞,直到重试成功再返回吗?那需要重试几次? 这些逻辑其实与Spring Cloud组件、Hystrix请求合并功能(Hystrix 2018年已经停止更新)等类似。


如果使用异步的话,上面的第2)点、第4)点基本不用考虑,从复杂度的角度来看,异步比同步简单很多,因此项目直接选用异步的方式,预约数据保存到缓存层即可返回结果。


关于异步的用户体验设计,共有两种设计方案可供业务方选择。


1)在“我的预约”页面给用户一个提示:您的预约订单可能会有一定延迟。

2)用户预约成功后,直接进入预约完成详情页,此页面会定时发送请求去查询后台批量落库的状态,如果落库成功,则弹出成功提示,并跳转至下一个页面。其实,第一种方案在实际应用中也经常遇到,不过项目中主要还是使用第二种方案。因为在第二种方案中,大部分情况下用户是感受不到延迟的,用户体验比较好,而如果选择第一种方案,用户还要去思考:这个延迟是什么意思?是不是失败了?这无形中就影响了用户体验。


2.2 如何触发批量落库


关于批量落库触发逻辑,目前共分为两种。


1)写请求满足特定次数后就落库一次,比如10个请求落库一次。按照次数批量落库的优点是访问数据库的次数变为1/N,从数据库压力上来说会小很多。不过它也存在不足:如果访问数据库的次数未凑齐N次,用户的预约就一直无法落库。

2)每隔一个时间窗口落库一次,比如每隔一秒落库一次。按照时间窗口落库的优点是能保证用户等待的时间不会太久,其缺点是如果某个瞬间流量太大,在那个时间窗口落库的数据就会很多,多到在一次数据库访问中无法完成所有数据的插入操作(比如一秒内堆积了5000条数据),它们只能通过分批次来实现插入,这不就变回第一种逻辑了吗?


那到底哪种触发方式好呢?当时项目采用的方案是同时使用这两种方式。


具体实现逻辑如下。

1)每收集一次写请求,就插入预约数据到缓存中,再判断缓存中预约的总数是否达到一定数量,达到后直接触发批量落库。

2)开一个定时器,每隔一秒触发一次批量落库。


2.3 缓存数据存储在哪里


缓存数据不仅可以存放在本地内存中,也可以存放在分布式缓存中(比如Redis),其中最简单的方式是存放在本地内存中。


但是,Hystrix的请求合并也是存放在本地内存中,为什么不直接使用Hystrix?这是因为写缓存与Hystrix的请求合并有些不一样,请求合并更多考虑的是读请求的情况,不用担心数据丢失,而写请求需要考虑容灾问题:如果服务器宕机,内存数据就会丢失,用户的预约数据也就没有了。其实也可以考虑使用MQ来当缓存层,MQ的一个主要用途就是削峰,很适合这种场景。


不过这个项目选择了Redis,接下来需要考虑批量落库的设计了。批量落库主要是把Redis中的预约数据迁移到数据库中。而当新的数据一直增加时,批量落库可能会出现多个线程同时处理的情况,此时就要考虑并发性了。


2.4 批量落库失败了怎么办

在考虑落库失败这个问题之前,先来看看批量落库的实现逻辑。


1)当前线程从缓存中获取所有数据。因为每10条执行一次落库操作,不需要担心缓存中的数据量过多,所以也不用考虑将获得的数据分批操作了。

2)当前线程批量保存数据到数据库。

3)当前线程从缓存中删除对应数据(注意:不能直接清空缓存的数据,因为新的预约数据可能插入到缓存中了)。


以上各个步骤失败时的应对措施见表5-1。


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



相关实践学习
基于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
相关文章
|
6天前
|
SQL 缓存 关系型数据库
MySQL技能完整学习列表6、查询优化——3、查询缓存——4、SQL优化技巧
MySQL技能完整学习列表6、查询优化——3、查询缓存——4、SQL优化技巧
67 0
|
6天前
|
缓存 NoSQL Java
SpringCache通用缓存学习
SpringCache通用缓存学习
|
6月前
|
缓存 NoSQL 关系型数据库
【Redis 系列】redis 学习十二,redis 缓存穿透,缓存击穿,缓存雪崩
【Redis 系列】redis 学习十二,redis 缓存穿透,缓存击穿,缓存雪崩
|
8月前
|
消息中间件 缓存 NoSQL
程序员快来学习缓存层场景实战数据收集—技术选型思路及整体方案
根据以上业务场景,项目组提炼出了6点业务需求,并针对业务需求梳理了技术选型相关思路。 1)原始数据海量:对于这一点,初步考虑使用HBase进行持久化。 2)对于埋点记录的请求响应要快:埋点记录服务会把原始埋点记录存放在一个缓存层,以此保证响应快速。关于这一点有多个缓存方案,稍后展开讨论。 3)可通过后台查询原始数据:如果直接使用HBase作为查询引擎,查询速度太慢,所以还需要使用Elasticsearch来保存查询页面上作为查询条件的字段和活动ID。
|
11月前
|
缓存 NoSQL Java
redis 6.0新特性-客户端缓存学习总结
redis 6.0新特性-客户端缓存学习总结
244 0
|
缓存
学习Vue3 第二十章(keep-alive缓存组件)
有时候我们不希望组件被重新渲染影响使用体验;或者处于性能考虑,避免多次重复渲染降低性能。而是希望组件可以缓存下来,维持当前的状态。这时候就需要用到keep-alive组件。
89 0
|
缓存
jira学习案例89-react-query处理服务器缓存
jira学习案例89-react-query处理服务器缓存
69 0
jira学习案例89-react-query处理服务器缓存
|
缓存
jira学习案例90-用useQuery缓存列表
jira学习案例90-用useQuery缓存列表
82 0
jira学习案例90-用useQuery缓存列表
|
缓存 运维 监控
Redis学习(十):缓存穿透、缓存击穿和缓存雪崩
key对应的数据在数据源中并不存在,每次针对此key的请求从缓存获取不到,这些请求都会压入数据源中,从而可能压垮数据源。
112 0
Redis学习(十):缓存穿透、缓存击穿和缓存雪崩
|
SQL 存储 XML
Mybatis 高阶学习(映射文件深入、延迟加载、缓存、注解开发等)
Mybatis 高阶学习(映射文件深入、延迟加载、缓存、注解开发等)
274 0
Mybatis 高阶学习(映射文件深入、延迟加载、缓存、注解开发等)