redis (2) 一文读懂redis的四种模式 客户端分析 以go-redis为例

目录

单实例(Standalone)

概括

  • 最简单的部署方式,单个redis实例,所有数据存储到单个redis实例中
  1. 优势:部署简单。性能最高,单点写入,无数据一致性问题,无网络开销,延迟最低,调试和监控也相对简单
  2. 劣势:单点故障,无法扩展
  3. 适用于开发测试或者小规模的应用

介绍

  • 单点redis的读速度是110000次/s,写速度大概是80000多次/s

主从(Master-Slave)

概括

  • 一主多从,读写分离
  1. 优势:提高读性能,数据备份
  2. 劣势:手动故障转移、写入单点
  3. 适用于读多写少的场景

介绍

  • 这种模式下,如果主节点挂了,从节点晋升为主节点,客户端访问redis实例的连接地址需要修改。由此引入了哨兵模式

哨兵(Sentinel)

概括

  • 主从基础上增加哨兵节点
  1. 优势:自动故障转移,服务发现
  2. 功能:监控、通知、自动切换、配置提供
  3. 适用于需要高可用的中型项目

介绍

  • 哨兵集群不存储数据,只负责监控数据面实例和建立连接,哨兵节点会不停的确认下面的数据面节点是否正常(PING),这样相当于加了一层,可以实现故障转移

集群(Cluster)

概括

  • Redis官方分布式方案
  1. 特性:16384个哈希槽分片、水平扩展
  2. 优势:自动分片、故障转移、线性扩展
  3. 适用于大规模、高并发场景

介绍

  • redis集群的键空间被分成16384个哈希槽,key经过CRC16算法模16384,得到实际存储的槽位置,在映射到具体的集群节点

为什么是16384?

  1. 这个数是 2 14 2^{14} 214,2的幂次,方便进行位运算和分片计算
  2. 大小适中,既不会太少导致分片粒度太粗,也不会太多导致元数据开销过大
  3. 对于大型集群(100+节点),仍然能提供良好的分片粒度
  4. 16384bits = 2048 bytes = 2KB,集群节点间交换的槽位信息只有2KB,网络开销小
  5. // Redis源码中的注释(CRC16的输出是16位结果,使用低14位正好对应16384)
    /* We have 16384 hash slots. The hash slot of a given key is obtained
    /* as the least significant 14 bits of the crc16 of the key. */

为什么是CRC16?

  1. 计算速度快,现代CPU有专门的CRC指令
  2. 分布均匀
  3. 冲突概率适中
  • 读分配给slave节点,写分配给master节点,读写分离增加了并发能力
  • 水平扩容的场景中,哈希槽会重新计算,并将旧的数据迁移到新节点的哈希槽上

go-redis

  • 在go语言中,可以使用go-redis来集成redis客户端

    go get github.com/redis/go-redis/v9

  • 使用也非常简单,建议使用NewUniversalClient来创建一个客户端,它会根据配置来选择合适的创建出来的客户端实例,如单机模式、集群模式等

go 复制代码
// NewUniversalClient returns a new multi client. The type of the returned client depends
// on the following conditions:
//
//  1. If the MasterName option is specified with RouteByLatency, RouteRandomly or IsClusterMode,
//     a FailoverClusterClient is returned.
//  2. If the MasterName option is specified without RouteByLatency, RouteRandomly or IsClusterMode,
//     a sentinel-backed FailoverClient is returned.
//  3. If the number of Addrs is two or more, or IsClusterMode option is specified,
//     a ClusterClient is returned.
//  4. Otherwise, a single-node Client is returned.
func NewUniversalClient(opts *UniversalOptions) UniversalClient {
	if opts == nil {
		panic("redis: NewUniversalClient nil options")
	}

	switch {
	case opts.MasterName != "" && (opts.RouteByLatency || opts.RouteRandomly || opts.IsClusterMode):
		return NewFailoverClusterClient(opts.Failover())
	case opts.MasterName != "":
		return NewFailoverClient(opts.Failover())
	case len(opts.Addrs) > 1 || opts.IsClusterMode:
		return NewClusterClient(opts.Cluster())
	default:
		return NewClient(opts.Simple())
	}
}
相关推荐
古城小栈2 小时前
Go 语言 ARM64 架构优化:边缘计算场景适配
架构·golang·边缘计算
古城小栈2 小时前
Go 1.25 新特性实战:greenteagc 垃圾收集器性能调优
golang
Kiri霧2 小时前
Go 字符串格式化
开发语言·后端·golang
古城小栈2 小时前
2025 Go 语言生态:从云原生到边缘计算
云原生·golang·边缘计算
桃花岛主702 小时前
go-micro,v5启动微服务的正确方法
开发语言·后端·golang
Kiri霧2 小时前
Go 结构体高级用法
开发语言·后端·golang
不会写DN15 小时前
fmt 包中的所有 Print 系列函数
开发语言·后端·golang·go
小明的小名叫小明17 小时前
Go从入门到精通(28) -再谈GMP和starvation
网络·golang
Kiri霧18 小时前
Go包基础与使用指南
开发语言·后端·golang