来 DTDS 全球数字人才发展峰会,与刘润、叶军、快刀青衣畅聊成长>> 了解详情
写点什么

使用 Redis 查询缓存

2019 年 10 月 24 日

使用Redis查询缓存

当我开始搭建网站时,我并没有太注重性能。一旦你掌握一些基础知识,比如 HTML 和 CSS,或者你在后端使用的任何编程语言,性能就成了你担心的奢侈品。初学者的目标是建一个网站,能够从一个页面跳转到另一个页面,并确保它在服务器上看起来运行地很好。缓存和性能是我们后面要解决的问题。


有很多很好的理由来研究缓存解决方案。从 SEO(搜索引擎优化)的角度来看,谷歌会惩罚加载缓慢的网站。如果你的网站加载需要很长时间,网站排名可能会受到影响,这当然会对收入产生严重的影响。Google 的 John Mueller 说,页面加载时间超过两秒钟会“影响爬取”你的网站数据,他会寻找加载时间少于 2-3 秒的网站。另一个因素是加载缓慢的网站可用性影响。当我开始编码时,完全加载一个页面大约需要 8 秒钟是可接受的。只有花了更长的时间,你才会担心人们会放弃这个页面。如今,这个时间大约是两秒钟,可能会更少,具体取决于你所在的行业。


底线:你的网站越快,排名越好,访问者留下和互动的次数就越多。但是,直到我的客户打电话说他们的新网站“太慢”时,这个问题才引起我的注意。理性地分析,它上面有一些较大的图像,他们正在使用一个糟糕的托管平台。这也回到了 10 美元托管意味着你的网站运行在共享服务器上的一天。他们对服务器优化的想法是安装最新版本的 CPanel(yikes)。经过一番挖掘,我构建了一个基本的页面缓存系统,它运行得很好。客户很高兴,我开始学习一种新的技能,一切都很好。但很快我意识到,虽然页面级缓存是一个很好的工具,但它只是一个工具。


当页面缓存不足时

页面缓存的工作方式如下:一个请求传入,服务器处理它,然后存储结果 HTML。为了说明本篇博客的场景,让我们使用 Redis 的一个例子。下次有人请求我们的页面时,它将首先检查缓存。如果页面在缓存中存在,系统将使用该页面,而不是在服务器级别处理请求。


这种场景适用于不会改变太多的页面,例如条款和条件或隐私政策。这些页面的流量不同于主应用程序,后者可能具有基于用户的动态数据。


假设我们有一个充当用户目录并允许基于某种活动进行过滤的应用程序。用户可以查看人员列表并查看他们的电子邮件地址和电话号码。我们的应用程序使用 SQL 数据库,因此要获取该数据,我们需要一个简单的选择查询:


SELECT username,email, phone_number FROM users WHERE activity='baseball';
复制代码


在我们的应用程序中,假设活动是用户在注册时设置的列表。因此,人们可以看到的活动类型因用户而异。我们将活动列表存储在另一个表中,并且也需要此页面上的信息。


SELECT name, id FROMactivity_list WHERE user_id=1;
复制代码


在这种情况下,我们有一个需要针对当前用户运行的查询。该用户看到的数据是整个列表的一个子集,对于他们来说是唯一的。。考虑到这一点,我们无法缓存页面,因此我们需要缓存每个单独的查询。


查询缓存,而不是页面缓存

现在我们需要考虑何时缓存查询以及如何缓存。一个简单的解决方案是使用 Redis Hashes 存储我们的结果集。我们可以将数据存储为 JSON 编码字符串,当我们准备好之后,只需将其取出并在我们的代码库中使用它。


那么缓存是什么样子的呢?下面是一些伪代码:


> HGETuser-activity-list cacheif the result isnot nil return the result set else go to step 3run the query andsave the DB result set to a variableif the DB resultsize is > 0transform theresult set data to a JSON string> HSETuser-activity-list cache JSON string result setelse result set<= 0 throw error
复制代码


关于上面的伪代码,我应该指出,当然我们忽略了这实际上是会话存储模式的事实。在现实世界中,你不会只想在 Redis 中永久缓存这些查询,只有在用户登录并在你的站点上活动时才创建和存储这些查询。我在 Redis 中创建了这个通用的用户活动列表键,仅作为一个示例来演示理论并激发你如何在自己的代码中执行此操作的想法。


除此之外,我们的键名也不是最好的。“用户活动列表”的名称也同样仅适用于这个非常通用和狭窄的示例。对于实际的应用程序,你可能希望以一种更可预测的方式命名你的键名。如果我真的这么做的话,这个键就会在某个地方有用户名,这都是用户会话的一部分,这样就可以很容易地检索和使用。


继续,我们应该解决几个问题。首先,我们获取了用户活动列表,但是在我们运行此查询一次后,我们应该使查询过期,这样我们就不会冒险向用户显示一些相当陈旧的数据。我们可以通过几种不同的方式来解决这个问题。


写入时过期

假设此活动列表是用户自己更新的内容。她会去设置页面,摆弄一些东西,并保存更改。她每周只能这样做一次或每月一次。在这种情况下,我们可以保留缓存,直到用户更改某些内容:


1.用户添加“sportsball”列表并保存


2.为了响应用户的保存,我们取消了用户活动列表的链接


你可以按照自己喜欢的方式完成第一部分和第二部分。对于这个系统,我假装我们有办法注册/推送事件。那部分并不重要,但重要的是我们的系统每次更新时都会删除缓存。我们不需要担心重新缓存数据,因为这是原始函数的工作。


定时过期

在写入时过期可能并不适用于每个场景。在有些情况下,我们只希望缓存一定时间的查询。对于这些,我们可以使用 Redis 来过期我们的键。


让我们拿出第一个缓存解决方案,看看它里面的 Redis 是什么样子的:


1.> HGET 获取用户活动列表缓存


2.如果结果不是 nil 则返回缓存值,否则转到步骤 3


3.运行查询并将 DB 结果集保存到变量


4.如果 DB 结果大小> 0


5.将结果集数据转换为 JSON 字符串


HSET 用户活动列表缓存 JSON 字符串结果


EXPIRE 用户活动列表 100


这里的诀窍是第五步。设置键后,我们使用 Redis 设置该键的过期时间(以秒为单位)。Redis 将为我们删除 key,因此我们不必担心在我们的代码中管理它。


结论

在页面级缓存不起作用或效率低下的情况下,缓存数据库查询是一个很好的选择。我们可以使用 Redis 设置并获取带有保存查询值的哈希值,并返回这些值而不是命中数据库。这将极大地加速我们的网站访问速度。想一想:从数据库访问信息并将信息返回给用户的标准时间是 100 毫秒,而 Redis 的平均时间只有 2 毫秒。这是一个巨大的性能提升。


在我们虚构的应用程序中,如果用户每小时点击这个活动页面 1000 次,而我们每次都必须访问数据库,那就会加起来(这只用于一个查询)。想象一下,如果这个页面有 2-5 个查询?如果这些查询需要多个表的复杂联接,该怎么办?一个页面上的三个同步查询很容易花费 300 毫秒以上才能从数据库返回数据。在一个我们只有 2-3 秒钟来吸引用户注意力的世界中,为什么要把自己置于不利地位?


现在,假设我们可以从缓存 90% 的时间中检索数据。


在 Redis 中缓存查询可以使单个页面的访问时间从 300 毫秒缩小为 6 毫秒。访问整个网站,抓取数据需要花费的时间将从数分钟减少到仅几秒钟。这是一个性能提升,应该会让极大提升客户体验。


本文转载自公众号中间件小哥(ID:huawei_kevin)。


原文链接:


https://mp.weixin.qq.com/s/HSOh1tA3rI5oS_iUOwGQ7g


2019 年 10 月 24 日 16:03564

评论

发布
暂无评论
发现更多内容

云原生架构的基石

soolaugust

Docker 架构 Kubernetes 容器 云原生

系统不可用总结

不在调上

高效程序员的45个习惯:敏捷开发修炼之道(3)

石云升

读书笔记 敏捷开发 无限游戏

丐帮,少林,明教,武当!看看你数据分析的技能属于哪一派?

程序员生活志

为什么一旦自己创业了,很难再回到公司去坐班?

北柯

创业 互联网 创业心态 上班 上班族

区块链承兑商支付系统开发,usdt支付系统搭建

WX13823153201

Spring 为啥默认把bean设计成单例的?这篇讲的明明白白的

程序员生活志

程序范式的意义

soolaugust

架构 程序设计

云上安全工作乱如麻,等保2.0来一下

华为云开发者社区

安全 华为云 等保 云平台 多云服务

一个数据库管理员的自我救赎之路

华为云开发者社区

数据库 华为云 数据库迁移 企业上云 DRS

“庆俞年”大战,真正受损的不是李国庆

北柯

创业 合伙人 创业者 互联网人 当当网

搭载十代酷睿i7处理器,这台ROG冰刃4新锐拥有媲美台式游戏电脑的性能

最新动态

写代码爬取了某 Hub 资源,只为撸这个鉴黄平台!

程序员生活志

教程 Hub 资源

学习的深度 & 深度的学习

北风

学习

ST在keil下开发时候文件options配置的一些小技巧

良知犹存

嵌入式

nginx报错worker_connections are not enough

Java联盟

nginx

草脸识别,AI泡沫还是皇冠明珠?

郭华

人工智能 AI 商业 解决方案

大厂面试必读,JAVA进阶神书《深入理解Java虚拟机》第三版更新内容全曝光!

华章IT

JVM 虚拟机 周志明 Java虚拟机 jvm调优

nginx 报错 accept4 () failed (24:Too many open files)

Java联盟

nginx

ARTS week 4

锈蠢刀

Python3 for ... else ...陷阱

王坤祥

Python Python PEP

"工科生"的浪漫 百度大脑语言与知识技术峰会在七夕向你发出参会邀请

百度大脑

影响音视频延迟的关键因素(一):流媒体系统

ZEGO即构

TCP udp RTC HLS RTMP

spring Cloud Eureka Rest接口重写

xcbeyond

Java SpringCloud Eureka

跨域问题(CORS / Access-Control-Allow-Origin)

xcbeyond

Java CORS 跨域

错误的存储方案正吞噬你的成本

jinjin

我的敏捷历程 —— 兼评《敏捷整洁之道 - 回归本源》

FollowFlow

敏捷开发 Agile 极限编程 XP

SpreadJS 纯前端表格控件应用案例:集成 Odoo提升企业ERP表格功能

Geek_Willie

开源 SpreadJS Odoo

一个虚拟世界里栽树的公司及其启示

郭华

技术 商业模式 电影

为啥PHP in_array(0,['a', 'b', 'c']) 返回为true?

架构精进之路

php 弱类型语言

CRM往事丨三件事,所有SaaS的缩影

人称T客

「中国技术开放日·长沙站」现场直播

「中国技术开放日·长沙站」现场直播

使用Redis查询缓存-InfoQ