1. 前言

说到Golang的Redis库,用到最多的恐怕是
redigo 和 go-redis。其中 redigo 不支持对集群的访问。
本文想聊聊go-redis 2个高级用法

2. 开启对Cluster中Slave Node的访问

在一个负载比较高的Redis Cluster中,如果允许对slave节点进行读操作将极大的提高集群的吞吐能力。

开启对Slave 节点的访问,受以下3个参数的影响

type ClusterOptions struct {
// Enables read-only commands on slave nodes.
ReadOnly bool
// Allows routing read-only commands to the closest master or slave node.
// It automatically enables ReadOnly.
RouteByLatency bool
// Allows routing read-only commands to the random master or slave node.
// It automatically enables ReadOnly.
RouteRandomly bool
...
}

go-redis 选择节点的逻辑如下

func (c *ClusterClient) cmdSlotAndNode(cmd Cmder) (int, *clusterNode, error) {
state, err := c.state.Get()
if err != nil {
return 0, nil, err
} cmdInfo := c.cmdInfo(cmd.Name())
slot := cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo)) if c.opt.ReadOnly && cmdInfo != nil && cmdInfo.ReadOnly {
if c.opt.RouteByLatency {
node, err := state.slotClosestNode(slot)
return slot, node, err
} if c.opt.RouteRandomly {
node := state.slotRandomNode(slot)
return slot, node, nil
} node, err := state.slotSlaveNode(slot)
return slot, node, err
} node, err := state.slotMasterNode(slot)
return slot, node, err
}
  • 如果ReadOnly = true,只选择Slave Node
  • 如果ReadOnly = true 且 RouteByLatency = true 将从slot对应的Master Node 和 Slave Node选择,选择策略为: 选择PING 延迟最低的节点
  • 如果ReadOnly = true 且 RouteRandomly = true 将从slot对应的Master Node 和 Slave Node选择,选择策略为:随机选择

3. 在集群模式下使用pipeline功能

Redis的pipeline功能的原理是 Client通过一次性将多条redis命令发往Redis Server,减少了每条命令分别传输的IO开销。同时减少了系统调用的次数,因此提升了整体的吞吐能力。

我们在主-从模式的Redis中,pipeline功能应该用的很多,但是Cluster模式下,估计还没有几个人用过。
我们知道 redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。如果我们使用pipeline功能,一个批次中包含的多条命令,每条命令涉及的key可能属于不同的slot

go-redis 为了解决这个问题, 分为3步
源码可以阅读 defaultProcessPipeline
1) 将计算command 所属的slot, 根据slot选择合适的Cluster Node
2)将同一个Cluster Node 的所有command,放在一个批次中发送(并发操作)
3)接收结果

注意:这里go-redis 为了处理简单,每个command 只能涉及一个key, 否则你可能会收到如下错误

err CROSSSLOT Keys in request don't hash to the same slot

也就是说go-redis不支持类似 MGET 命令的用法

一个简单的例子

package main

import (
"github.com/go-redis/redis"
"fmt"
) func main() {
client := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{"192.168.120.110:6380", "192.168.120.111:6380"},
ReadOnly: true,
RouteRandomly: true,
}) pipe := client.Pipeline()
pipe.HGetAll("1371648200")
pipe.HGetAll("1371648300")
pipe.HGetAll("1371648400")
cmders, err := pipe.Exec()
if err != nil {
fmt.Println("err", err)
}
for _, cmder := range cmders {
cmd := cmder.(*redis.StringStringMapCmd)
strMap, err := cmd.Result()
if err != nil {
fmt.Println("err", err)
}
fmt.Println("strMap", strMap)
}
}

GO-REDIS的一些高级用法的更多相关文章

  1. redis(二)高级用法

    redis(二)高级用法 事务 redis的事务是一组命令的集合.事务同命令一样都是redis的最小执行单元,一个事务中的命令要么执行要么都不执行. 首先需要multi命令来开始事务,用exec命令来 ...

  2. redis的Linux系统安装与配置、redis的api使用、高级用法之慢查询、pipline事物

    今日内容概要 redis 的linux安装和配置 redis 的api使用 高级用法之慢查询 pipline事务 内容详细 1.redis 的linux安装和配置 # redis 版本选择问题 -最新 ...

  3. 聊聊GO-REDIS的一些高级用法

    1. 前言 说到Golang的Redis库,用到最多的恐怕是redigo 和 go-redis.其中 redigo 不支持对集群的访问.本文想聊聊go-redis 2个高级用法 2. 开启对Clust ...

  4. Visual Studio 宏的高级用法

    因为自 Visual Studio 2012 开始,微软已经取消了对宏的支持,所以本篇文章所述内容只适用于 Visual Studio 2010 或更早期版本的 VS. 在上一篇中,我已经介绍了如何编 ...

  5. SolrNet高级用法(分页、Facet查询、任意分组)

    前言 如果你在系统中用到了Solr的话,那么肯定会碰到从Solr中反推数据的需求,基于数据库数据生产索引后,那么Solr索引的数据相对准确,在电商需求中经常会碰到菜单.导航分类(比如电脑.PC的话会有 ...

  6. sqlalchemy(二)高级用法

    sqlalchemy(二)高级用法 本文将介绍sqlalchemy的高级用法. 外键以及relationship 首先创建数据库,在这里一个user对应多个address,因此需要在address上增 ...

  7. Solr学习总结(六)SolrNet的高级用法(复杂查询,分页,高亮,Facet查询)

    上一篇,讲到了SolrNet的基本用法及CURD,这个算是SolrNet 的入门知识介绍吧,昨天写完之后,有朋友评论说,这些感觉都被写烂了.没错,这些基本的用法,在网上百度,资料肯定一大堆,有一些写的 ...

  8. 再谈Newtonsoft.Json高级用法

    上一篇Newtonsoft.Json高级用法发布以后收到挺多回复的,本篇将分享几点挺有用的知识点和最近项目中用到的一个新点进行说明,做为对上篇文章的补充. 阅读目录 动态改变属性序列化名称 枚举值序列 ...

  9. Redis Sentinel机制与用法说明【转】

    本文来自:https://segmentfault.com/a/1190000002680804 概述 Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Ma ...

随机推荐

  1. 《Python基础教程》第三章:使用字符串

    find方法可以在一个较长的字符串中查找子字符串.它返回子串所在位置的最左端索引.如果没有找到则返回-1 join方法用来在队列中添加元素,需要添加的队列元素都必须是字符串 >>> ...

  2. poj1734 Sightseeing trip[最小环]

    一个最小环裸题.最小环的两种求法dijkstra和Floyd直接参见这里我就是从这里学的,不想写了. 注意这里最重要的一个点是利用了Floyd的dp过程中路径上点不超过$k$这一性质,来枚举环上最大编 ...

  3. numpy的ndarray数组如何reshape成固定大小

    在做肺结节检测的时候,遇到dicom文件reshape之后尺寸大小不一.因为大下不一,numpy.reshape又无法重塑成指定大小的.最后还是在一个大牛的代码中找到了解决方法. VL = np.lo ...

  4. order-independent transparency & programmable blending

    Yang, McKee - OIT and Indirect Shadows(SIGGRAPH 2010 Advanced RealTime Rendering Course).pptx 最近又发现了 ...

  5. 解决nginx无法访问的问题

    解决nginx无法访问的问题 解决方案-->恢复Nginx默认配置: cd /usr/local/nginx/conf rm nginx.conf cp nginx.conf.default n ...

  6. Kafka、RabbitMQ、RocketMQ等消息中间件的介绍和对比(转)

    前言在分布式系统中,我们广泛运用消息中间件进行系统间的数据交换,便于异步解耦.现在开源的消息中间件有很多,前段时间产品 RocketMQ (MetaQ的内核) 也顺利开源,得到大家的关注. 概念MQ简 ...

  7. 前端Web浏览器基于Flash如何实时播放监控视频画面(四)之使用videoJs‘拉流’

    本片文章只是起到抛砖引玉的作用,能从头到尾走通就行,并不做深入研究.为了让文章通俗易懂,尽量使用白话描述. 0x001: 下载videoJs 对于Video.js 5.x及更低版本,Flash技术(v ...

  8. CDOJ 1256 打表+数组 统计

    昊昊爱运动 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit  St ...

  9. linux端口释放

    查看linux连接端口范围 cat /proc/sys/net/ipv4/ip_local_port_range 调低端口释放等待时间 echo 20 >  /proc/sys/net/ipv4 ...

  10. liunx 一些文件下载上传的命令

    xshell 上传 rz sftp 语法: put path/filename.txt Put -r path/文件夹 或者 put “path/filename.txt” Put -r “path/ ...