Redis - Redis 6.0 新特性之客户端缓存

news2024/9/27 7:22:15

1. 为什么需要客户端缓存

antirez 写了一篇有关客户端缓存设计的想法:《Client side caching in Redis 6》。antirez 认为,Redis 接下来的一个重点是配合客户端,因为客户端缓存显而易见的可以减轻 Redis 的压力,速度也快很多。实际上,几乎每个大公司都有实现这种应用端缓存的机制,antirez 想通过 server 端的一些设计来减少客户端缓存实现的复杂度和成本,甚至不惜在 Redis 协议上做修改。

1.1 低延迟和大规模提供数据服务

如果我们需要快速存储和快速缓存,那么我们需要在客户端内部存储一部分信息。它是以低延迟大规模提供数据服务理念的自然延伸。几乎每个非常大的公司已经这样做了,现在来看,这是最终能承受负载的唯一途径。

一起来看个例子:为了能够提高数据访问性能,进一步应对热点数据,很多公司会在 Redis 的 client 端缓存一部分热点数据,来应对大众所热衷的「吃⽠事件」。比如:「时间管理大师」、「我从来没觉得我这么欠打过」…

1.2 其他 cache 层

除了使⽤ Redis 缓存避免直接访问数据库以外,还会加更多的 cache 层,⽐如采⽤ Memcachced 作为热点数据的本地缓存:

  1. 先去 Memcachced 中查询数据,命中直接返回;
  2. Memcachced 未命中,则再从 Redis 查询,命中则返回数据,并在 Memcachced 保存这个数据;
  3. Redis 未命中,则去 MySQL 中查询,并依次设置到 Redis 和 Memcachced 中。

2. Redis 中的客户端缓存

在 Redis 官方文档是这么定义客户端缓存的:Server-assisted, client-side caching in Redis(Redis 服务端协助的客户端缓存)。

客户端缓存是一种用于创建高性能服务的技术。它利用应用程序服务器上可用的内存(与数据库节点相比,这些服务器通常是不同的计算机),直接在应用程序端存储数据库信息的一些子集。

需要获取某些数据时,应用程序向 Redis 数据库访问这些数据:

在这里插入图片描述

当使用客户端缓存时,应用程序会将获取的数据存储在应用程序内存中,无需再次网络访问 Redis:

在这里插入图片描述

虽然应用程序内存被当做本地缓存使用的可能性不大,但与通过网络直接访问数据库相比,访问本地计算机缓存所需要的时间要少几个数量级。

2.1 什么样的数据集应该被客户端缓存

  1. 我们不应该缓存不断变化的键;

  2. 我们不该缓存很少请求的键;

  3. 我们希望缓存经常请求并以合理速率更改的键。对于没有稳定变化速度的例⼦,⽐如不断被 INCR 修改的全局计数器,就不应该缓存。

2.2 客户端缓存的两个主要优点

  1. 低延迟提供数据访问

  2. 更少的请求到数据库系统,允许它以更少的节点数提供相同的数据集。

3. 缓存的数据一致性问题

上面已经介绍了客户端缓存的大体流程,但这种模式存在 “数据一致性问题” 。例如,在上面的应用程序在本地缓存了 user:1234 的信息后,“没对象的指针” 可能会将她的用户名在 Redis 服务端更新为 “Flora”。然而,该应用程序可能会继续为用户提供旧用户名:没对象的指针

网上有很多数据一致性的解决方案,这里就不再赘述了。下面一起来看一下 Redis 是怎么处理客户端缓存数据的吧。

4. Redis 客户端缓存的实现原理

Redis 实现的是一个服务端协助客户端缓存(Server-assisted, client-side caching),叫做:Tracking。有两种模式:

  • 普通(默认)模式下,Redis 会记住每个客户端请求的 key,当 key 值发生变化时会发送失效信息(invalidation messages)给客户端。

  • 广播模式下,Redis 不会记录客户端请求的 key,因此这种模式在服务器端不消耗任何内存。相反,客户机订阅 key 的前缀,如 object: 或 user: ,并且在每次接触与该前缀匹配的 key 时收到一条通知消息。

4.1 普通模式

4.1.1 实现思路

  1. 客户端可以根据需要启用 tracking ;

  2. 启用 tracking 后,服务端会记住每个客户端在连接生命周期内请求的 key(通过发送有关此类 key 的读命令);

  3. 当 key 发生变化时(客户端修改、key 过期失效、最大内存策略被逐出等),所有启动了 tracking 且可能缓存了该 key 的客户端都会收到一条失效消息通知;

  4. 当客户端售后无效消息时,需要删除响应的 key,以免提供过时的数据。

4.1.2 一起看一个该模式下的实例:

Client 1 -> Server: CLIENT TRACKING ON
Client 1 -> Server: GET foo
(The server remembers that Client 1 may have the key "foo" cached)
(Client 1 may remember the value of "foo" inside its local memory)
Client 2 -> Server: SET foo SomeOtherValue
Server -> Client 1: INVALIDATE "foo"

4.1.3 Redis 是如何实现

这从表面上看起来很不错,但如果有一个 10K 连接的客户端需要长时间请求数百万个 key,那么服务器最终会存储很多信息。为此,Redis 使用如下思想来限制服务端使用的内存和处理实现该功能的数据结构的CPU成本:

  • Server 端将 Client 端访问的 key 以及该 key 对应的客户端ID的列表信息储存在全局唯一的表 - TrackingTable(Invalidation Table - 失效表)。当表中插入了新的 key,且超过设置的最大记录数 - tracking-table-max-keys,则会(随机)删除旧 tracking 的 key(即使这个 key 未被修改),并向客户端发送 invalidation message(失效消息)。

  • 每个 Redis 客户端都有一个唯一的ID,TrackingTable 会存储每个 Client ID。如果客户端断开连接,缓存失效,则会清除该ID对应的记录。

  • 有一个键命名空间不按数据库编号划分。因此,如果客户端正在缓存 foo 数据库 2 中的 key,而其他一些客户端更改了 foo 数据库 3 中 key 的值,则仍会发送无效消息。这样我们就可以忽略数据库编号,从而减少内存使用和实现复杂性。

可以通过 redis.config 文件的 tracking-table-max-keys 属性设置记录 key 的最大值:

# 在广播模式下使用 key tracking 时,服务器端未使用任何内存,此设置无用。
tracking-table-max-keys 1000000

在这里插入图片描述

4.2 广播模式(BCAST)

当⼴播模式 (broadcasting) 开启时,服务端不会记录给定客户端访问了哪些键,不消耗服务端的任何内存。

在广播模式下,服务端会给客户端广播所有 key 的失效情况,不过,这样做了之后,如果 key 被频繁修改,服务端会发送大量的失效广播消息,这就会消耗大量的网络带宽资源

所以,在实际应用时,我们会让客户端注册希望跟踪的 key 的前缀,当带有注册前缀的 key 被修改时,服务端会把失效消息广播给所有注册的客户端。

和普通模式不同,在广播模式下,即使客户端还没有读取过 key,但只要它注册了要跟踪的 key,服务端都会把 key 失效消息通知给这个客户端。我们在实际应用时,会给同一业务下的 key 设置相同的业务名前缀,所以,我们就可以非常方便地使用广播模式。

4.2.1 广播模式的主要行为

  • 客户端使用该选项启用客户端缓存BCAST,使用该选项指定一个或多个前缀 PREFIX。例如:CLIENT TRACKING on REDIRECT 10 BCAST PREFIX object: PREFIX user:。如果没有指定前缀,则前缀默认为空字符串,因此客户端将收到每个被修改的 key 的失效消息。相反,如果使用一个或多个前缀,则只有与指定前缀之一匹配的 key 才会在失效消息中发送。

  • 服务器不在 invalidation table 中存储任何内容。相反,它使用不同的 Prefixes Table,其中每个前缀都与一个客户端列表相关联。

  • 没有两个前缀可以跟踪键空间的重叠部分。例如,不允许使用前缀 “foo” 和 “foob”,因为它们都会触发为 “foobar” 的 key 使之无效。仅使用前缀 “foo” 就足够了。

  • 每次修改与任何前缀匹配的 key 时,订阅该前缀的所有客户端都将收到无效消息。

  • 服务端消耗的 CPU 与注册前缀的数量成正比。如果你只有几个,很难看出有什么区别。使用大量前缀,CPU 成本会变得相当大。

  • 在这种模式下,服务端可以执行优化,为订阅给定前缀的所有客户端创建单个回复,并向所有客户端发送相同的回复。这有助于降低 CPU 使用率。

在这里插入图片描述

4.3 重定向模式

普通模式和广播模式,需要客户端使用 RESP 3 协议,它是 Redis 6.0 新启⽤的协议。

对于使用 RESP 2 协议的客户端来说,就需要使用另一种模式,也就是重定向模式(redirect)。

在重定向模式下,想要获得失效消息通知的客户端,就需要执行订阅命令 SUBSCRIBE(subscribe 订阅),专门订阅用于发送失效 key 消息的频道 redis:invalidate。同时,再使用另外一个客户端,执行 CLIENT TRACKING(client tracking 客户跟踪)命令,设置服务端将失效消息转发给使用 RESP 2 协议的客户端。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/170409.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android从开机到APP启动流程——基于Android9.0

Android从开机到APP启动流程——基于Android9.0 一、 Zygote进程启动流程 二、 System Server启动流程 三、 ActivityManagerService启动流程 四、 Launcher App (Home Activity)启动流程 五、 Zygote fork()子进程,子进程入口为ActivityThread.main() 六、 Acti…

第02讲:使用kubeadm搭建k8s集群的准备工作

官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/ kubeadm 是官方社区推出的一个用于快速部署 kubernetes 集群的工具,这个工具能通过两条指令完成一个 kubernetes 集群的部署: 第1步、创建一个 Master 节点 kubeadm init第2步&#x…

记录一次mysql慢查询的优化过程

前言 业务上线后经常报查询超时,数据库使用的是阿里云的RDS,mysql版本是5.6.16-log,有几条统计数据的查询语句执行很慢,有的甚至执行一次需要10多秒,简直无法忍受。 查看了超时时间,默认为0 show variables…

【微信小程序-原生开发】实用教程03-自定义底部导航(含自定义tabBar导航高亮需点击两次的解决方案)

开始前,请先完成底部导航的开发,详见 【微信小程序-原生开发】实用教程02-添加全局页面配置、页面、底部导航 https://sunshinehu.blog.csdn.net/article/details/128705866 显然,纯文字的底部导航有点low,还是需要有图标的才酷…

新手编写IntelliJ IDEA插件

需求目的可能你会想什么场景会需要用到插件开发,其实插件开发算是一种通用的解决方案,由服务平台定义标准让各自使用方进行自需的扩展。这就像我们非常常用的 P3C 代码检查插件、代码审计插件、脚手架工程创建插件、自动化API提取插件、单元测试统计插件…

TOF相机国产、非国产统计参数对比分析

TOF相机国产、非国产统计参数对比分析 Kinect v2 Kinect v2是Microsoft在2014年发售的,如图1-1所示。相比于Kinect v1在硬件和软件上作出了很大的进化,且在深度测量的系统和非系统误差方面表现出更好的性能。 Kinect v2中一共有三个摄像头&#xff0c…

Linux学习笔记【part2】网络配置与远程登录

Linux基础篇学习笔记 1.网络连接模式 VMware 提供了三种网络连接模式: ① 桥接模式 桥接模式:虚拟机直接连接外部物理网络的模式,主机起到了网桥的作用。在这种模式下,虚拟机可以直接访问外部网络,并且对外部网络是…

vue3利用keepAlive缓存页面

场景介绍 项目中经常会有这么一个需求,一个表单页面,可能需要跳转其他页面拿到对应的数据,再跳回表单页面,但是之前填写过的数据还在。而某些页面跳这个表单页面的时候,是不需要缓存,因为他是新增&#xf…

通过Facebook建立反链:SEO角度

最近我有一个朋友的网站做得很不错,每天都在增加反链。反链对于网站来说,好处是显而易见的,能够提升搜索引擎对网站的认可度,增强用户对网站的信任度。另外一个方面的好处是,反链可以提高流量(或者转化率&a…

想考个PMP证书,要怎么报考?

pmp 报考条件没他们说的那么难,什么 4500/7500 个小时的项目管理经验,这个条件看起来很难,其实项目无处不在,画一幅画,做一餐饭,都能算一个项目,这 4500个小时、7500 个小时很快就达到了。一、报…

三十、Kubernetes中kube-proxy三种工作模式详解

1、概述 在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。 为了解决这个问题,kubernetes提供了Service资源&…

2023-01-18 ClickHouse之聚合功能源码分析

前言 聚合分析是从海量数据中提取数据的基本方法,对于OLAP数据库而言,聚合分析是其关键能力之一,ClickHouse在这方面也做了很多设计和优化,正如ClickHouse在文档中所述: 本文将分析展示ClickHouse的聚合功能的工作原理…

NFS 导出的共享信息披露漏洞问题解法

输入:shoumount -e, 如果有目录信息,则说明有NFS 导出的共享信息披露漏洞。 如果处理了就应显示如下图: 解法如下: 1)备份需要修改的文件 cp /etc/hosts.allow /etc/hosts.allowbak cp /etc/hosts.deny…

前端js实现文件多次添加累加上传和选择删除(django+js)

前言 原本的多文件上传功能在选择文件时,只能通过同一范围的鼠标框选或者ctrl/shift多选取选择文件,这样选择文件很不灵活,而且在确定之后如果漏选了文件,再次点击上传按钮时会清空表单里的文件信息,只能重复之前的操…

springcloudalibaba整合nacos

文章目录1.版本配置2.搭建项目2.1idea新建项目2.2项目依赖2.3测试初始项目2.4项目的配置文件3.nocas的配置文件4.进行测试4.1准备测试的文件4.2测试nacos安装: nacos下载安装 1.版本配置 2.搭建项目 2.1idea新建项目 选择springcloudalibaba和springboot版本 spr…

Minecraft 1.19.2 Forge模组开发 10.3D动画盔甲

Minecraft 1.16.5模组开发3D盔甲 Minecraft 1.12.2模组开发3D盔甲 Minecraft 1.18.2模组开发3D动画盔甲 我们本次在1.19.2的版本中实现具有动画效果的3D盔甲 效果演示效果演示效果演示 1.首先,为了实现这些效果,我们需要首先使用到一个模组:geckolib…

剖析栈和队列OJ题

1.括号匹配问题给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。有效字符串需满足:1.左括号必须用相同类型的右括号闭合。2.左括号必须以正确的顺序闭合。3.每个右括号都有一个对应…

【阅读笔记】c++ Primer Plus——第八章

函数探幽 c内联函数 为了提高程序运行速度而做的改进编译的最终产物是可执行程序——由一组机器语言指令组成。运行程序时,操作系统将这些指令载入到计算机内存中,因此每条指令都有特定的内存地址。然后计算机开始逐步执行指令。执行到函数调用的时候&…

一道编程劝退题,检测你是否适合干编程

前言大家都知道要想成为一名优秀的开发工程师,需要数学基础好,即你要有很强的逻辑思维能力,这里有一道美国斯坦福大学出的一道逻辑思维的测试测试,检测你的逻辑思维能力,大家可以看看自己逻辑能力怎么样。题目有一个抽…

<队列>的概念结构实现【C语言版】

1.队列的概念及结构 队列对于临时数据的处理也十分有趣,它跟栈一样都是有约束条件的数组(或者链表)。区别在于我们想要按什么顺序去处理数据,而这个顺序当然是要取决于具体的应用场景。 你可以将队列想象成是电影院排队。排在最…