《Redis实战》一2.4 数据行缓存-阿里云开发者社区

开发者社区> 异步社区> 正文

《Redis实战》一2.4 数据行缓存

简介:
+关注继续查看

本节书摘来异步社区《Redis实战》一书中的第2章,第2.4节,作者: 【美】Josiah L. Carlson(约西亚 L.卡尔森)译者: 黄健宏 责编: 杨海玲,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.4 数据行缓存

到目前为止,我们已经将原本由关系数据库和网页浏览器实现的登录和访客会话转移到了Redis上面实现;将原本由关系数据库实现的购物车也放到了Redis上面实现;还将所有页面缓存到了Redis里面。这一系列工作提升了网站的性能,降低了关系数据库的负载并减少了网站成本。

Fake Web Retailer的商品页面通常只会从数据库里面载入一两行数据,包括已登录用户的用户信息(这些信息可以通过AJAX动态地载入,所以不会对页面缓存造成影响)和商品本身的信息。即使是那些无法被整个缓存起来的页面——比如用户账号页面、记录用户以往购买商品的页面等等,程序也可以通过缓存页面载入时所需的数据库行来减少载入页面所需的时间。

为了展示数据行缓存的作用,我们假设Fake Web Retailer为了清空旧库存和吸引客户消费,决定开始新一轮的促销活动:这个活动每天都会推出一些特价商品供用户抢购,所有特价商品的数量都是限定的,卖完即止。在这种情况下,网站是不能对整个促销页面进行缓存的,因为这可能会导致用户看到错误的特价商品剩余数量,但是每次载入页面都从数据库里面取出特价商品的剩余数量的话,又会给数据库带来巨大的压力,并导致我们需要花费额外的成本来扩展数据库。

为了应对促销活动带来的大量负载,我们需要对数据行进行缓存,具体的做法是:编写一个持续运行的守护进程函数,让这个函数将指定的数据行缓存到Redis里面,并不定期地对这些缓存进行更新。缓存函数会将数据行编码(encode)为JSON字典并存储在Redis的字符串里面,其中,数据列(column)的名字会被映射为JSON字典的键,而数据行的值则会被映射为JSON字典的值,图 2-1展示了一个被缓存的数据行示例。


1


程序使用了两个有序集合来记录应该在何时对缓存进行更新:第一个有序集合为调度(schedule)有序集合,它的成员为数据行的行ID,而分值则是一个时间戳,这个时间戳记录了应该在何时将指定的数据行缓存到Redis里面;第二个有序集合为延时(delay)有序集合,它的成员也是数据行的行ID,而分值则记录了指定数据行的缓存需要每隔多少秒更新一次。

使用JSON而不是其他格式 因为JSON简明易懂,并且据我们所知,目前所有拥有Redis客户端的编程语言都带有能够高效地编码和解码JSON格式的函数库,所以这里的缓存函数使用了JSON格式来表示数据行,而没有使用XML、Google的protocol buffer、Thrift、BSON、MessagePack或者其他序列化格式。在实际应用中,读者可以根据自己的需求和喜好来选择编码数据行的格式。

嵌套多个结构 使用过其他非关系数据库的用户可能会期望Redis也拥有嵌套多个结构的能力,比如说,一个刚开始使用Redis的用户可能会期盼着散列能够包含有序集合值或者列表值。尽管嵌套结构这个特性在概念上并无不妥,但这个特性很快就会引起类似以下这样的问题:“对于一个位于嵌套第5层的散列,我们如何才能对它的值执行自增操作呢?”为了保证命令语法的简单性,Redis并不支持嵌套结构特性。如果有需要的话,读者可以通过使用键名来模拟嵌套结构特性:比如使用键user:123表示存储用户信息的散列,并使用键user:123:posts表示存储用户最近发表文章的有序集合;又或者直接将嵌套结构存储到JSON或者其他序列化格式里面(第11章将介绍使用Lua脚本在服务器端直接以JSON格式或者MessagePack格式对数据进行编码的方法)。

为了让缓存函数定期地缓存数据行,程序首先需要将行ID和给定的延迟值添加到延迟有序集合里面,然后再将行ID和当前时间的时间戳添加到调度有序集合里面。实际执行缓存操作的函数需要用到数据行的延迟值,如果某个数据行的延迟值不存在,那么这个调度商品将会被移除。如果我们想要移除某个数据行已有的缓存,并且让缓存函数不再缓存那个数据行,那么只需要把那个数据行的延迟值设置为小于或等于0就可以了。代码清单2-7展示了负责调度缓存和终止缓存的函数。

代码清单2-7 schedule_row_cache()函数


q2


现在我们已经完成了调度部分,那么接下来该如何对数据行进行缓存呢?负责缓存数据行的函数会尝试读取调度有序集合的第一个元素以及该元素的分值,如果调度有序集合没有包含任何元素,或者分值存储的时间戳所指定的时间尚未来临,那么函数会先休眠50毫秒,然后再重新进行检查。当缓存函数发现一个需要立即进行更新的数据行时,缓存函数会检查这个数据行的延迟值:如果数据行的延迟值小于或者等于0,那么缓存函数会从延迟有序集合和调度有序集合里面移除这个数据行的ID,并从缓存里面删除这个数据行已有的缓存,然后再重新进行检查;对于延迟值大于0的数据行来说,缓存函数会从数据库里面取出这些行,将它们编码为JSON格式并存储到Redis里面,然后更新这些行的调度时间。执行以上工作的缓存函数如代码清单2-8所示。

代码清单2-8 守护进程函数cache_rows()


q1

通过组合使用调度函数和持续运行缓存函数,我们实现了一种重复进行调度的自动缓存机制,并且可以随心所欲地控制数据行缓存的更新频率:如果数据行记录的是特价促销商品的剩余数量,并且参与促销活动的用户非常多的话,那么我们最好每隔几秒更新一次数据行缓存;另一方面,如果数据并不经常改变,或者商品缺货是可以接受的,那么我们可以每分钟更新一次缓存。

在这一节中,我们学习了如何将数据行缓存到Redis里面,在接下来的一节中,我们将通过只缓存一部分页面来减少实现页面缓存所需的内存数量。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
spring-boot | 整合Redis缓存数据
spring boot 整合redis非常简单,首先创建spring boot的Maven项目,然后在pom.xml文件中引入redis的依赖。 引入redis的依赖 org.springframework.boot spring-boot-starter-data-redis 添加redis的配置文件 在application.properties里面设置redis的配置文件,spring boot会自动加载redis的配置文件,非常方便。
1912 0
处理亿级数据的“定时任务”,如何缩短执行时间?
一次性集中处理大量数据的定时任务,优化思路是:同一份数据,减少重复计算次数;分摊CPU计算时间,尽量分散处理(甚至可以实时),而不是集中处理;减少单次计算数据量。
555 0
PB 缓存数据指南
### 概述 在目前的支付宝客户端开发中, PB 格式已经是网络传输的序列化/反序列化方案的标配。但 PB 同时对我们 native 开发中的缓存实现也是有很大价值的。 ### 缓存方案对比 本人对比了如下几种客户端的缓存方案: * PB + DiskLruCache * Orml
2345 0
redis数据结构、持久化、缓存淘汰策略
redis数据结构、持久化、缓存淘汰策略Redis 单线程高性能,它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
927 0
数据湖实操讲解【 JindoTable 计算加速】第二十一讲:分层更高效,对 Hive 数仓进行热度/冷度统计
数据湖 JindoFS+OSS 实操干货 36讲 每周二16点准时直播! 扫文章底部二维码入钉群,线上准时观看~ Github链接: https://github.com/aliyun/alibabacloud-jindofs
181 0
穿越数据的变迁 - 如何使用阿里云Redis数据闪回进行按时间点的数据恢复
如何使用阿里云Redis数据闪回进行按时间点的数据恢复
2025 0
Redis 实战篇之搭建集群
Redis 集群简介 Redis Cluster 即 Redis 集群,是 Redis 官方在 3.0 版本推出的一套分布式存储方案。完全去中心化,由多个节点组成,所有节点彼此互联。Redis 客户端可以直接连接任何一节点获取集群中的键值对,不需要中间代理,如果该节点不存在用户所指定的键值,其内部会自动把客户端重定向到键值所在的节点。
1463 0
+关注
异步社区
异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。
12049
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载