上海网站设计案例,国外 网站网站,高端网站设计公司名单,wordpress 相册 json前言
Redis在其6.0版本中加入了Client-side caching的支持#xff0c;开启该功能后#xff0c;Redis可以将指定的key-value缓存在客户端侧#xff0c;这样当客户端发起请求时#xff0c;如果客户端侧存在缓存#xff0c;则无需请求Redis Server端。
Why Client-side Cac…前言
Redis在其6.0版本中加入了Client-side caching的支持开启该功能后Redis可以将指定的key-value缓存在客户端侧这样当客户端发起请求时如果客户端侧存在缓存则无需请求Redis Server端。
Why Client-side Caching
------------- ----------
| | ------- GET user:1234 ------- | |
| Application | | Database |
| | ---- username Alice ------- | |
------------- ----------一些场景下Redis的一些热点数据需要高频访问但是并不会频繁的更新这种数据存储在Redis中会对Redis的读有一定的压力因此将这种数据存储在客户端侧进行缓存当需要读取时直接从客户端侧的内存中读取可以大幅度减轻Redis的读压力当数据发生变更时Redis Server通知Client更新Client Cache。
------------- ----------
| | | |
| Application | ( No chat needed ) | Database |
| | | |
------------- ----------
| Local cache |
| |
| user:1234 |
| username |
| Alice |
-------------Why Not Pub/Sub
在早期的Redis版本中一些业务场景我们一定也会考虑到将一些不常变化的热点数据存储在本地内存中使用例如Caffeine Cache等Localcache定时周期频率读取最新的值更新Localcache或者使用Redis Pub/Sub当key值发生更新时通知整个集群更新Localcache。
使用Pub/Sub对于旧版本Redis来说没有实现Client-side caching时是一种解决方案但是此种方案存在弊端
首先Pub/Sub不可靠如果部分集群中的Client没有收到Pub的通知Localcache可能没有更新
其次对网络压力巨大当Client Node非常多的时候网络可能会出现阻塞CPU压力也会增大同时Client端需要自行实现Localcache的更新逻辑。
How to use it
Redis Client-side Caching命令如下
CLIENT TRACKING ON | OFF [REDIRECT client-id] [PREFIX prefix [PREFIX prefix ...]] [BCAST] [OPTIN] [OPTOUT] [NOLOOP]客户端默认不开启 track 模式我们需要在获取执行指令之前执行开启命令
CLIENT TRACKING ON
OK
GET foo
bar默认情况下Client开启Tracking后Redis Server端会对所有的Client端请求查询的key开启Tracking当 key的值发现变化时会发送失效信息给客户端 (invalidation message)。
server - client: Invalidate foo默认情况下对所有的请求查询的key开启Tracking这显然是不合适的更多的场景下我们只希望追踪部分热点且不经常变化的keyRedis支持对仅对特定的key开启手动追踪
CLIENT TRACKING ON OPTIN // 开启特定key追踪选项CLIENT CACHING YES // get请求前加入该命令
OK
GET foo
bar手动追踪模式下需要用户在每次进行get命令之前执行追踪的命令这样的好处是非常的精确但是也有点繁琐Redis还提供了另一种追踪模式即广播模式
CLIENT TRACKING ON BCAST PREFIX object: PREFIX user:广播模式下需要用户指定需要追踪的key的前缀当key发生变化时Redis Server端会发出广播通知全部订阅了该前缀key的客户端。
需要注意的是在这个模式下如果用户没有指定PREFIX那么服务端会给客户端广播所有 key 的失效情况如果 key 被频繁修改服务端会发送大量的失效广播消息这就会消耗大量的网络带宽资源这是非常危险的一个行为需要特别注意。
How to implement?
上面的篇幅我们简单介绍了Redis的客户端侧缓存如何开启本小节我们来看一下Redis是如何实现的在展开这个问题之前我们可以思考一下如果我们是Redis的设计者我们该如何实现该功能
很简单我们会想到搞一个Array存一下嘛对吧O(∩_∩)O把需要追踪的key存一下当key收到set之类的命令后看一下Tracking Array中有没有如果有通知订阅的Client。
事实上对于手动追踪模式Redis的确是这样实现的Redis内部使用了Invalidation Table存储Tracking Key Data也可以叫做Tracking Table其内部使用LRU淘汰机制维护当Table内的key数量达到最大值会移除最老的记录同时触发该记录已过期的通知给客户端。
在Invalidation Table中Redis存储了Tracking key的指针地址与客户端之间的映射关系使用了一种基数树(radix tree)的数据结构因为键对象的指针就是内存地址也就是长整型数据。客户端缓存的相关操作就是对该数据的增删改查 对于广播模式实现的原理也是相似的不过Redis并不是使用Invalidation Table存储而是使用Prefixes Table存储key的前缀值与Client之间的关系 Problem
以上我们简单了解了Redis的Client-side caching的使用方式与实现机制这是一个非常好的功能可以帮助我们更加高效的使用Redis但是其也有对应的问题。
在Redis的官方文档中Client-side caching功能并未提及Master/Slave 与 Cluster集群模式的特别支持这意味着Client端需要对key的Tracking做出特别的适配而在Redis Cluster集群模式下连接状态信息是分散在不同的节点上的难以实现集中管理。
Redis的客户端Jedis、lettuce与Redisson均不提供Client-side caching相关支持lettuce的committer在Github中关于对Client-side caching问题做出了回复 There are a few challenges to address: Re-apply CLIENT TRACKING settings upon reconnect: While that is primary a resiliency feature, in Master/Replica or Cluster mode that is a must since we don’t get hold easily of cluster connections. We also need to apply tracking settings when creating a new connectionTopology changes: Whenever the topology changes, we need to adapt to that. Meaning also that we need to carry over tracking settings. More over, how does the migration path look like when in Redis Cluster a slot assignment gets migrated to a new node? What about the server side, does it carry over also all touched keys? I assume not so reconfiguration can cause dropped notifications since the new server is no longer aware of the key subscriptions from the old server. While this could be done (with a lot of effort) on the client side, I think that is too complex.Finally, I don’t have time to do that in the near future nor I see how I can do that alone in 2021. 有一些挑战需要解决 重新连接时重新应用客户端跟踪设置虽然这主要是一个弹性功能但在主/复制或群集模式下这是必须的因为我们不容易掌握群集连接。我们还需要在创建新连接时应用跟踪设置 拓扑变化每当拓扑结构发生变化时我们都需要适应这种变化。这也意味着我们需要沿用跟踪设置。此外当 Redis 集群中的插槽分配迁移到新节点时迁移路径是怎样的在服务器端是否也会继承所有被触及的密钥我认为不会因此重新配置可能会导致通知丢失因为新服务器不再知道旧服务器的密钥订阅。虽然这可以在客户端完成需要付出很多努力但我认为这太复杂了。 最后我近期没有时间去做这件事我也不知道 2021 年我如何能单独完成这件事。 对于我们普通开发者希望在生产环境中使用Client-side caching也许还需要观望后续Java Redis Client社区的支持情况。