希望在Redis集群中将读取查询负载均衡到主节点和备份节点上
首先
这篇文章是《朝日新闻》2023年圣诞日历的第12天的内容。?
我們將談論一般的Redis話題,但在這裡我們以AWS ElasticCache for Redis作為例子。
一般的的ElastiCache for Redis的架构
我认为在以集群模式运行ElastiCache时,通常会将最多5个读取实例部署在写入实例上。
Redis的構成問題
我认为在这种配置中,我们可以假设在主实例和副本实例之间以及副本实例之间都进行负载均衡。
然而,实际上,如果仅仅发送一个get命令,即使在应用程序中读取集群端点也不会进行负载均衡。
发送到读取实例的查询都会被重定向到写入实例。
在Amazon Cloudwatch上查看正在使用的ElastiCache的指标后,我们可以发现只存在主节点的GetTypeCmds数量。
在指标上看,阅读查询似乎都是针对主实例发出的。
※GetTypeCmds指标是一个用于计算在集群内发出的读取命令总数的指标。
The reason
如果在Redis中以集群模式运行,则所有查询都会发送到各个分片的主节点。因此,如果对副本发出查询,则通过重定向将其发送到主实例。
解决方案
正如Redis集群模式的参考文档所述,通过发出READONLY命令可以使此行为失效。
例如,在Go应用程序中使用go-redis实现时,可以通过设置cluster.go文件中的ClusterOptions结构体的Readonly属性来启用只读模式。
client := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{addr},
ReadOnly: true, // READONLYコマンドの発行
})
另外,顺便说一句,go-redis库提供了RouteByLatency和RouteRandomly两个选项,可以通过优先考虑延迟还是随机访问来控制副本的优先级。
client := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{addr},
ReadOnly: true, // READONLYコマンドの発行
// RouteByLatency: true, // READONLYコマンド発行時、レイテンシ低いレプリカにアクセス
// RouteRandomly: true, // READONLYコマンド発行時、ランダムにレプリカにアクセス
})
总结
虽然在Redis的文档中有提到,但由于发现某些相关产品并未进行Redis的负载均衡,因此我产生了疑问并进行了调查。
这个指南也被发布在 AWS 的 Re:Post 上,但是直到我调查才第一次听说。
https://repost.aws/ja/knowledge-center/elasticache-redis-client-readonly
当您启用集群模式时,如果希望通过复制来实现负载均衡,请尝试启用READONLY。
以下内容仅提供一种中文本地化的解释:
– “Can I speak to the manager, please?”
可以请问一下我可以见到经理吗?
– “I would like to make a reservation for two people.”
我想为两个人预订。
– “Could you please repeat that?”
请再说一遍好吗?
– “What time does the train depart?”
火车几点出发?
– “Sorry, I don’t understand.”
对不起,我不明白。
– “Could you help me with this?”
你能帮我一下吗?
– “Where is the nearest bathroom?”
最近的洗手间在哪里?
– “How much does this cost?”
这个多少钱?
– “I need directions to the nearest hospital, please.”
请告诉我最近的医院怎么走。
– “Could you recommend a good restaurant nearby?”
你能推荐附近的一家好餐馆吗?
附加
本部分旨在通過向副本發出讀取查詢來實現與主要資料庫的負載均衡,但與此相反,也存在一種僅意圖向主要資料庫發出查詢的命令(失效現有的READONLY),這種命令被稱為READWRITE命令。