乐趣区

Redis-60-除了多线程别忘了这个牛逼特性


起源:urlify.cn/mYVVNf

Redis 6.0 的新个性也是在一步步的探讨和优化中确定的。很多的个性曾经在之前的 RC 等版本中介绍过了。然而正式 GA 版中也有一些新的变动:

  • SSL
  • ACL: 更好,命令反对
  • RESP3
  • Client side caching: 从新设计
  • Threaded I/O
  • Diskless replication on replicas
  • Cluster support in Redis-benchmark and improved redis-cli cluster support
  • Disque in beta as a module of Redis: 开始侵入音讯队列畛域
  • Redis Cluster Proxy
  • 反对 RDB 不再应用时可立刻删除,针对不落盘的场景
  • PSYNC2: 优化的复制协定
  • 超时设置反对更敌对
  • 更快的 RDB 加载,20% ~ 30% 的晋升
  • STRALGO,新的字符串命令,目前只有一个实现 LCS (longest common subsequence)

@antirez 提到只是 Redis 历史上最大的一次版本更新,所以审慎倡议在利用的产品中还是多多测试评估,并且承诺一旦遇到大的 bug 就会紧急公布 6.0.1 版。果不其然,一天后就公布了 6.0.1 版,修复了一个 allocator 的 bug,这个 bug 是为了优化而引入的,当初临时去掉了。

I just released Redis 6.0.1. Unfortunately there was a bug in Redis 6.0.0 introduced just a few days before the release, that only happens when using the non-default allocator (libc malloc in this case triggers it). Optimization reverted, 6.0.1 released. Sorry for the issue.

本文次要关注 Client side caching(客户端缓存) 这一个性。

smallnest/RESP3 是 Redis RESP3 协定的解析库,你能够应用它和 Redis 底层通信,或者包装它实现新版的 Redis client 库或者 Redis Server 端。

一年前,当 @antirez 加入完纽约 Redis 大会后,5:30 就在旅店中醒来了,面对曼哈顿街头的漂亮风景,在芸芸众生中考虑 Redis 的将来。包含客户端缓存。

其实,客户端缓存个性是收到 Redis Conf 2018 的 Ben Malec 的影响,一下子关上了 @antirez 思路。咱们晓得,很多公司应用 Redis 做缓存零碎,并且很好的进步了数据拜访的性能,然而很多企业为了进一步应答热点数据,还是会在 redis 的 client 端缓存一部分热点数据,用来应答吃瓜事件。比方在微博咱们常常遇到的是明星出轨、明星分分合合、突发事件等等,每年都会有几次突发的事件,微博除了应用 Redis 做缓存防止间接拜访数据库,还会在后面加更多的 cache 层,比方 L1 cache 等,采纳 memcached 等产品作为热数据的缓存。那么就有一个问题,如何可能及时的同步这些 cache 和 redis 的数据呢?Ben 提供了十分有意思的想法。

伫立在曼哈顿的街头,@antirez 陷入了深思,起初回到旅馆他开始实现初版的客户端的缓存。当然,最终 Redis 6.0 中实现和这个初版的实现差异很大,然而很是显然,从客户端的演化过程中咱们还是能看到 @antirez 对这个个性所在的衡量(trade off)。对于这个历史本文不做太多的介绍,因为咱们更关注于这个个性最终是什么样子的。

Redis 实现的是一个服务端帮助的客户端缓存,叫做tracking。客户端缓存的命令是:

CLIENT TRACKING ON|OFF [REDIRECT client-id] [PREFIX prefix] [BCAST] [OPTIN] [OPTOUT] [NOLOOP]

tracking 开启时,Redis 会 ” 记住 ” 每个客户端申请的 key,当 key 的值发现变动时会发送生效信息给客户端 (invalidation message)。生效信息能够通过 RESP3 协定发送给申请的客户端,或者转发给一个不同的连贯(反对 RESP2+ Pub/Sub)。当播送模式(broadcasting) 开启时,参加 tracking 的客户端会收到它通过前缀订阅的 key 的相干的告诉,即便它没申请过对应的 key。同时还提供了 OPTINOPTOUT 等模式。

生效音讯:当一个 key 的数据有批改的时候,须要通知客户端它以前缓存的数据生效了,这时 redis 会被动发送一条生效音讯

  • REDIRECT : 将生效音讯转发给另外一个客户端。当咱们不应用 RESP3 而是应用老的 RESP2 和 Redis 通信时,client 自身不反对解决生效音讯,所以能够开启一个反对 Pub/Sub 客户端解决生效音讯。当然如果客户端反对 RESP3 也能够将生效音讯转发给另外一个客户端。这个 cace 咱们放在最初演示。
  • BCAST: 应用播送模式开始tracking。在这种模式下客户端须要设置将 track 的 key 的前缀,这些 key 的生效音讯会播送给所有参加的客户端,不论这些客户端是否申请 / 缓存额这些 key。不开始播送模式时,Redis 只会 track 那些只读命令申请的 key,并且只会报告一次生效音讯。
  • PREFIX : 只利用了播送模式,注册一个 key 的前缀。所有以这个前缀开始的 key 有批改时,都会发送生效音讯。能够注册多个前缀。如果不设置前缀,那么播送模式会 track 每一个 key。
  • OPTIN: 当播送模式没有激活时,失常 不会 track 只读命令的 key,除非它们在CLIENT CACHING yes 之后被调用。
  • OPTOUT: 当播送模式没有激活时,失常 track 只读命令的 key,除非它们在 CLIENT CACHING off 之后被调用。
  • NOLOOP: 不发送 client 本人批改的 key。

上面让咱们一一介绍每个选项。

测试环境搭建

首先让咱们介绍 RESP3 协定相干的选项,REDIRECT <id>放在最初介绍。

在尝试之前,你首先须要装置一个 redis 6.x 的版本,目前时 6.0.1。在官方网站上有源代码的下载,编译装置也很简略:

make distclean
make
make test
sudo make install

置信很快就有编译好的二进制包能够下载。

启动 server, 它会在 6379 端口启动一个服务:

redis-server

应用 redis-cli 拜访, 默认拜访本机的 6379 实例:

redis-cli

当然你能够通过 -h 查看额定的参数配置,比方应用其它端口等等,这里咱们应用最简略的例子,重点是理解客户端缓存的个性。

有时候为了更好的察看 redis 的返回后果,咱们应用 telnet 而不是 redis-cli 作为 client 连贯 redis,因为 redis-cli 对后果做了解决,尤其是生效音讯,你可能无奈观测到。

BCAST 播送模式 (client tracking on)

启动 redis server:

启动 redis-cli:

当然,咱们应用 telnet 来测试,不便察看 redis 的返回后果,方才 redis-cli 用来更新 key 值,辅助测试。连贯上之后发送 hello 3 开启 RESP3 协定:

➜  ~ telnet localhost 6379
Trying ::1...
Connected to localhost.
Escape character is '^]'.
hello 3
%7
$6
server
$5
redis
$7
version
$5
6.0.1
......

之后尝试开启 tracking 并读取 a 的值:

client tracking on
+OK
set a 1
+OK
get a
$1
1

这个时候如果应用 redis-cli 作为另外一个 client 更新 a 的值,telnet 这个 client 应该能取得告诉:

127.0.0.1:6379> set a 2
OK

察看 telnet,它收到了一个生效音讯:

>2
$10
invalidate
*1
$1
a

留神它采纳 RESP3 中的 PUSH 类型(>)。

如果这个应用你再应用 redis-cli 更新 a 的值,telnet 不会再收到生效音讯。除非 telnet client 再 get a 一次,从新tracking a 的值。

能够随时勾销tracking:

client tracking off

tracking 特定前缀的 key (client tracking on)

下面的形式会 tracking 所有的 key,如果你只想跟踪特定的 key, 目前 redis 提供了一种形式,也就是前缀匹配的形式。你能够只 tracking 特定前缀的 key。它值利用了播送模式。

应用 telnet client 设定前缀和开启 tracking:

hello 3.......
client tracking on prefix a bcast
+OK
client tracking on prefix user bcast
+OK

咱们 tracking 两个前缀,以 a 结尾的所有的 key 和以 user 结尾的所有的 key, 所有 a 结尾的所有的 key 和以 user 结尾的所有的 key(包含 auser)的 key 变动时它应该都收到音讯。

而后咱们应用 redis-cli 更新三个 key: abcuser:32432723213feed:6532343243432:

127.0.0.1:6379> set abc 100
OK
127.0.0.1:6379> set user:32432723213 good
OK
127.0.0.1:6379> set feed:6532343243432 abc
OK

telnet client 收到 abcuser:32432723213的生效音讯, 而不会收到 feed:6532343243432 的生效音讯:

>2
$10
invalidate
*1
$3
abc>2
$10
invalidate
*1
$16
user:32432723213

你能够通过 client tracking off 进行客户端缓存。目前貌似不能只进行对单个的前缀的 tracking。即便你应用client tracking off prefix user 也是勾销对所有的 key 的tracking

......
} else if (!strcasecmp(c->argv[2]->ptr,"off")) {disableTracking(c);
} else {......

抉择退出

如果应用 OPTIN, 能够有抉择的开启tracking。只有你发送client caching yes 之后的下一条的只读命令的 key 才会 tracking, 否则 其它的只读命令中的 key 不会 tracking

首先咱们开始 optin,读取 a 的指,这个时候应用 redis-cli client 批改 a 的值为 1000,咱们并没有收到a 的生效音讯。

client tracking on optin
+OK
get a
$1
2

接下来咱们发送client caching yes,紧接着获取 a 的值,这个时候如果再批改 a 的值,你就能够收到一条 a 的生效音讯:

client caching yes  
+OK  
get a  
$4  
1000  
>2  
$10  
invalidate  
*1  
$1  
a

必须是紧跟着 client caching yes 吗? 是的,比方发送上面的命令,只会tracking b, 而不是 a:

client caching yes  
+OK  
get b  
_  
get a  
$4  
2000

抉择退出

如果应用 OPTOUT, 你也能够有抉择的退出tracking。只有你发送client caching off 之后的下一条的只读命令的 key 才会进行 tracking, 否则 其它的只读命令中的 key 都会被 tracking

能够看到它和 OPTIN 正好相同,你能够依据你的场景来抉择。

比方上面的例子,开启 OPTOUT 之后,对任意的 key 的变动都收到生效音讯:

client tracking on optout  
+OK  
get a  
$4  
3000  
>2  
$10  
invalidate  
*1  
$1  
a

这个时候如果咱们想排除 b 这个 key,能够只针对它进行设置:

client caching no  
+OK  
get b  
$1  
3

之后对 b 的变动并不会收到 b 的生效音讯。

留神 : OPTINOPTOUT是针对的非 BCAST 场景,也就是只有你发送了 key 的只读命令后,才会跟踪相应的 key。而播送模式是无论你是否发送过 key 的只读命令,只有 redis 批改了 key,都会发送相应 key(或者匹配前缀的 key)的生效音讯。

NOLOOP

失常设置时,生效音讯是发给所有参加的 client,然而如果设置了NOLOOP, 则不会发送给更新这个 key 的 client。

client tracking on bcast noloop  
+OK  
set a 1  
+OK  
client tracking off  
+OK  
client tracking on bcast  
+OK  
set a 1  
+OK  
>2  
$10  
invalidate  
*1  
$1  
a

留神,勾销 tracking 只需调用 client tracking off 即可。

REDIRECT

最初,让咱们看一下转发音讯的解决。这是为了兼容 RESP2 协定一个解决形式,将生效音讯转发给另外一个 client。

首先咱们查看 redis-cli 的 client id:

127.0.0.1:6379> client list
id=4 addr=127.0.0.1:61017 fd=8 name= age=33103 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client user=default

应用 telnet 连贯 redis, 查看 client id:

client id
:12

telnet 客户端开启订阅生效音讯:

SUBSCRIBE __redis__:invalidate  
*3  
$9  
subscribe  
$20  
__redis__:invalidate  
:1

而后咱们就能够将 redis-cli 的生效音讯转发给 telnet client:

client tracking on bcast redirect 12
127.0.0.1:6379> set a 1000
OK

能够看到 telnet 客户端收到了生效音讯:

*3  
$7  
message  
$20  
__redis__:invalidate  
*1  
$1  
a

如果你要转发的目标 client 开启了 RESP3 协定,你就不须要 RESP3 Pub/Sub 了,因为 RESP3 原生反对 Push 音讯。

redis 的 tracking feature 的实现代码在:tracking.c。

退出移动版