一种关于缓存数据何时更新的解决思路

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 为什么写? 和大家一样,我有每天逛逛博客园的习惯,今天在博客园看到了“一只攻城狮”写的《初遇 Asp.net MVC 数据库依赖缓存那些事儿》。该朋友利用.Net的SqlCacheDependency缓存依赖,解决了缓存数据何时更新的问题。

为什么写?

和大家一样,我有每天逛逛博客园的习惯,今天在博客园看到了“一只攻城狮”写的《初遇 Asp.net MVC 数据库依赖缓存那些事儿》。该朋友利用.Net的SqlCacheDependency缓存依赖,解决了缓存数据何时更新的问题。

但是该思路具有一定的局限性,如:要利用数据库的存储过程,来通知客户端更新缓存,这就离不开微软的Sql Server那套体制,如果利用别的数据库,恐怕就没有那么好实现了。且存储过程需要在数据库中执行,不利于将业务向服务程序转移。

 

程序员比较忌讳造轮子,相信程序员写博客也是如此,因此,我还是想站在巨人的肩膀上,借用“一只攻城狮”在《初遇 Asp.net MVC 数据库依赖缓存那些事儿》写的背景,来引出我想说的内容,如果“一只攻城狮”觉得有何不妥之处,请联系我做下架处理。

 

 

--------------------------------------------------------------引用开始-----------------------------------------------

最近做一个非常简单的功能,就是使用ajax请求的方式从服务端请求一段下拉表的数据。

  以前也有做过这个功能,只不过这次做这个功能的时候冒出了一个想法:

  我请求的这段数据它是一段相对比较固定的数据,也就是说它不怎么改变,也许几个月才会改变一次。由于这种数据的变化周期很长,所以以前做这种功能的时候,会使用缓存进行优化,可以直接从缓存中读取数据,避免每一次接收了ajax请求后都要向数据库要数据,减少服务器与数据库之间的交互,减轻数据库服务器的压力。但是问题来了,数据的变化周期再长终究是要变化的,当数据库中的数据变化的时候你就要对旧有的缓存内容进行移除(remove)操作。

                 .......................{中间省略XXX字,中间作者大致讲诉了设置了缓存定期过期}.................................

  缓存定期过期有一个坏处:在还没到达过期时间的这段时间里,请求的数据依然是原来的缓存中数据,如果数据库数据在这期间进行了更新,那么缓存数据和数据库中的数据并不一致。

  其中设置的绝对过期时间点要根据实际的数据刷新的可容忍度来进行设定,而恰好在我的这个应用场景中的可容忍度最不能把握,它要求的是 当数据库中的数据改变以后,缓存中对应的数据在下一次请求结束后一定要马上跟着改变,当然你也可以把过期时间尽可能的调小,调到一秒。当然,这样的话还是要频繁的向数据库进行请求,那不是背离了我们原本使用缓存优化的目的了吗?

 

  所以现在的问题是:有没有一种方法能让数据库和服务器程序建立一种联系,这种联系好比是一种“心灵感应”,当数据库表中的数据发生变化的时候,马上就能让服务器中的对应的缓存项“感应”到这个变化,从而让原来的缓存项失效呢?

 

--------------------------------------------------------------引用结束------------------------------------------

我的做法

  综上所述,客户端(或浏览器)缓存数据的痛点在于,数据何时更新?如何让客户端知道,服务端数据变了?

  分四步走。

第一步,初次请求数据时

客户端在初次请求数据时,会把客户端想要的数据连同数据的版本号(数据上次的更新时间)一起发送给客户端,数据版本号时存在Redis数据库中的,我们知道,Redis中的数据存储在内存中且读取数据比关系型数据库快的不是一点点。

客户端收到数据后,会把收到的数据和数据版本号缓存下来。

 

第二步,当数据库数据更新时

当数据库数据更新时,服务端在更新关系型数据库的同时会把Redis的数据版本号更新为当前时间。

第三步,客户端用数据时:

客户端需要使用缓存数据时,会向服务端索要数据版本号(也就是数据上次的更新时间),如果该数据版本号与客户端缓存的数据版本号一致,那么,客户端缓存的数据时安全可用的,如果不一致,那么说明数据已经更新了,客户端把新的版本号缓存下来并重新获取。那么,执行第四步。

第四步,重新获取数据

重新获取数据时,就不用携带版本号了,客户端在第三步时已经获取并缓存下来了。

 

利弊

好处:

1.当请求的数据量交大但是变动又不频繁时,客户端与服务端不必频繁地交换大型数据,只需交换数据版本号即可。

2.数据版本号存储在Redis数据库中,不仅读取速度快,而且数据量小,所以响应快,交换成本低。

3.该思路通用性强,适合任何类型的关系型数据库与Nosql数据库搭配使用。

弊端:

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
相关文章
|
1月前
|
缓存 数据库
16- 什么是缓存雪崩 ? 怎么解决 ?
# 16 - 缓存雪崩及其解决方案 缓存雪崩是指大量缓存在同一时刻失效,导致数据库承受巨大压力。原因在于键的过期时间设定相同。解决方法是在键的过期时间中加入随机因素,避免同时失效。
19 2
|
缓存 Java 数据库连接
|
18天前
|
缓存 流计算
缓存命中率和过期机制的一般思路
【4月更文挑战第20天】缓存命中率是评估缓存效果的关键,目标是达到90%以上,但某些频繁的小请求场景可能无法实现。过期机制可采用定时删除(精确但开销大)、延迟队列(精确但有队列开销)、懒惰删除(简单但时间不精确)或定期删除(简单但性能损耗不可控)。
19 4
|
5月前
|
缓存 NoSQL API
Redis缓存更新策略与缓存穿透、雪崩等问题的解决
一、缓存更新策略 1、三种策略 内存淘汰:redis自带的内存淘汰机制 过期淘汰:利用expire命令给数据设置过期时间 主动更新:主动完成数据库和缓存的同时更新
|
8月前
|
存储 缓存 NoSQL
【Redis从头学-15】三个通俗例子带你理解Redis缓存击穿、缓存穿透、缓存雪崩并从思路引导三者的解决方案
【Redis从头学-15】三个通俗例子带你理解Redis缓存击穿、缓存穿透、缓存雪崩并从思路引导三者的解决方案
52 0
|
10月前
|
缓存
什么是缓存雪崩 ? 怎么解决 ?
什么是缓存雪崩 ? 怎么解决 ?
54 0
|
10月前
|
存储 缓存 NoSQL
【Java项目】布隆过滤器解决缓存穿透问题以及布隆过滤器删除困难问题
【Java项目】布隆过滤器解决缓存穿透问题以及布隆过滤器删除困难问题
197 0
|
10月前
|
存储 缓存 NoSQL
项目实战典型案例1——redis只管存不管删除 让失效时间删除的问题
项目实战典型案例1——redis只管存不管删除 让失效时间删除的问题
64 0
|
10月前
|
存储 缓存 NoSQL
【项目实战典型案例】01.redis只管存不管删除让失效时间删除的问题
【项目实战典型案例】01.redis只管存不管删除让失效时间删除的问题
|
10月前
|
缓存 监控 容灾
缓存雪崩 ? 怎么解决
缓存雪崩是指当缓存中的大量数据同时失效或者某些原因导致无法使用时,所有的请求都会直接访问数据库,造成数据库压力剧增,甚至导致系统崩溃。下面将详细介绍缓存雪崩的解决方案。
103 0