Redis 客户端缓存
目录
Redis 客户端缓存
Abstract
之前存在问题
How
三种缓存模式:
Demo
默认模式
广播模式
转发模式(不要使用)
Abstract
这是redis6.0 的新特性
Redis 有其性能上限,并且访问 Redis 必然有一定的网络 I/O 以及序列化反序列化损耗。所以,往往会引入本地缓存,将最热的数据存储在本地,进一步加快访问速度。
客户端缓存是一种用于创建高性能服务的技术。它利用应用服务器(与数据库节点相比,应用服务器通常是不同的计算机)中的可用内存,以便将数据库信息的某些子集直接存储在应用程序端。
《Client side caching in Redis 6》中提到redis 接下来的一个重点是配合客户端,因为客户端缓存显而易见的可以减轻 redis 的压力,速度也快很多。大公司或多或少都有实现这种应用端缓存的机制,antirez 想通过 server 端的一些设计来减少客户端缓存实现的复杂度和成本,甚至不惜在 redis 协议上做修改。
之前存在问题
只使用 Redis 分布式缓存时,遇到数据更新时,应用程序更新完 MySQL 中的数据,可以直接将 Redis 中对应缓存失效掉,保持数据的一致性。
而进程内缓存的数据一致性比分布式的缓存面临更大的挑战。数据更新的时候,如何通知其他进程也更新自己的缓存呢?
如果按照分布式缓存的思路,我们可以设置极短的缓存失效时间,这样不必实现复杂的通知机制。
但是不同进程内的数据依然会面临不一致的问题,并且不同进程缓存失效时间不统一,同一个请求到了不同的进程,可能出现反复幻读的情况。
How
Ben 在 RedisConf18 给出了一个方案(视频和 PPT 链接在文末),通过 Redis 的 Pub/Sub,可以通知其他进程缓存对此缓存进行删除。如果 Redis 挂了或者订阅机制不靠谱,依靠超时设定,依然可以做兜底处理。
Antirez(Redis 的作者) 也正是听取 Ben 这个方案后,才决定在 Redis Server 支持客户端缓存的,因为在有服务端参与的情况下可以更好的处理上述这些问题。
三种缓存模式:
缓存模式 | 特征描述 | 优缺点 |
默认模式 | 1. 服务端会记录某个客户端具体访问过哪一些 key,当这些 key 对应的 值发生变化时,会发送失效消息给这些客户端。 2. 这个模式会在服务端消耗一些内存,但是发送失效消息的范围,被限 制在了客户端存储了的 key 的集合范围内 | 优点:省 CPU 和带宽 缺点:多用占内存 |
广播模式 | 1. 服务端不会再记录某个客户端访问了哪些 key。取而代之的是,客户 端需要订阅 key 的特定前缀,每当符合这个前缀的 key 对应的值发生 改变时,客户端都会收到通知消息 2. 这个模式下不消耗服务端的内存,但是会消耗更多的 CPU | 优点:少占用内存 缺点:多用占 CPU |
转发模式 | 1. 主要是为了兼容 resp2 协议,是一个过渡模式 | 优点:少占用内存 缺点:多用占 CPU |
在客户端缓存,redis 本身不提供在应用服务端缓存数据的功能,这个功能要由访问 redis 的业务端自己去实现。也就是说,redis 服务端只负责通知你,你缓存在应用服务本地的这个 key 已经作废了,至于你本地如何缓存的这些数据,redis 并不关心,也不可能去关心。
Demo
默认模式
前提:redis 6.x 版本+开启 RESP3 协议+开启 tracking 机制
1. 客户端 A 采用 telnet 模式连接上 redis,命令:telnet 127.0.0.1 6379
2. 开启 resp3 协议,命令:hello 3
3. 开启 tracking 机制,命令:client tracking on
4. 接下来,我们在客户端 A 中先执行 get key1,然后在客户端 B 中执行 set key1 newval,然后我们发现客户端 A 中收到了作废信息
广播模式
前提:redis 6.x 版本+开启 RESP3 协议+开启 tracking 机制
接下来,我们在客户端 B 中执行 set 任意 key 的值,然后我们发现客户端 A 中均能收到作废信息
转发模式(不要使用)
前提:redis 6.x 版本+开启 tracking 机制
1. 客户端 A 采用 telnet 模式连接上 redis,并订阅_redis_:invalidate 事件,命令:telnet 127.0.0.1 6379,subscribe _redis_:invalidate
2. 客户 B 上开启转发模式,命令:client tracking on bcast redirect 49
3. 这时候我们发现,在其它客户端修改的消息均能出现在客户端 A