惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - abce

Redis 集群架构 Redis 的演进之路:从缓存到 AI 数据库(V1.0至8.4) Redis 缓存过期和删除策略 Redis 的 aof-use-rdb-preamble 及其工作原理 MySQL主从之间具有不同数据类型的列的复制 MySQL 如何存储临时文件 理解mysql中的 local_infile 变量 pbm 还原物理备份提示executable file not found in $PATH. stderr MySQL 日志报错:Got packets out of order MySQL 8.0 已废弃的功能 sqlserver 删除job失败 查看 percona server for mongodb 的版本 MySQL 8 的哈希连接 MySQL 8.0 克隆插件及其原理 有效管理 MongoDB 日志和系统资源 MySQL 保留字需要了解的内容 MongoDB 数据碎片处理 MongoDB 8.0 的复制 min_examined_row_limit 对慢查询日志的影响
Redis 如何通过槽优化分布式系统中的键值存储
abce · 2026-01-27 · via 博客园 - abce

Redis的槽位

Redis槽位是Redis集群(Redis的分布式实现)中使用的基本概念。Redis集群由多个节点组成,数据分布在这些节点上。为实现这种分布,Redis使用16384个哈希槽位,这些槽位作为数据的逻辑分区。

Redis中的每个键都会通过哈希机制映射到这16,384个槽位中的某个槽位。槽位的主要目的是确保数据均匀分布,使Redis在保持高性能的同时实现水平扩展。

槽位哈希机制

Redis采用一种简单而高效的哈希机制——循环冗余校验(CRC16)来确定给定键的存储槽位。计算公式如下所示:

slot = CRC16(key) % 16384

首先使用CRC16哈希:Redis为给定键计算CRC16校验和,生成唯一哈希值。然后进行取模运算:将哈希值除以16384,余数即为槽位编号。

该机制确保每个键值对可预测地映射至16384个槽位之一。槽位确定后,Redis集群将键值对路由至负责该槽位的特定节点。此过程高效可靠,既保证数据布局一致性,又最大限度降低了查找开销。

槽位与键值存储的关系

Redis本质上是一种键值存储系统。在此类存储中,数据以键值对的形式存储。例如:

> set user:01 "myabc"

此处user:01是键,myabc 是值。

槽位的分配

向Redis集群插入键值对时,系统会先对键进行哈希运算以确定其槽位,随后将数据路由至负责该槽位的节点。该过程对用户而言完全透明且无缝衔接。

假设有一个三主、三从的集群节点:

image (6)

现在,尝试在集群中插入一些键值对。

1.键:user:01

键的哈希值为:CRC16(user:01)=49839

槽位:49839%16384=687

节点:分配到主节点1(对应的槽位是0-5460)

2.键:order:02

键的哈希值为:CRC16(order:02)=27959

槽位:27959%16384=11575

节点:分配到主节点3(对应的槽位是10923-16383)

3.键:product:04

键的哈希值为:CRC16(product:04)=40106

槽位:40106%16384=7338

节点:分配到主节点2(对应的槽位是5461-10922)

当查询任何这些键时,Redis会将请求路由到相应的节点。

数据一致性

通过将键分配到特定槽位,Redis确保数据在集群中保持一致分布。这种方法还使扩展和重新平衡变得简单,因为槽位可以在节点间迁移而不会中断整个集群的运行。

槽位在Redis中的重要性

槽位不仅是理论概念,在Redis集群的实际运行中也发挥着关键作用。以下是槽位非常重要的原因:

1.数据分布

槽位确保数据在集群节点间均匀分布。这种均衡分布有助于防止单节点成为瓶颈,从而提升集群整体性能与可扩展性。

2.容错能力

Redis集群利用槽位实现数据复制以增强容错性。每个槽位可在不同节点存储多个副本。若某节点故障,持有相同槽位副本的其他节点可立即接管。

3.可扩展性

随着数据增长,可能需要向集群添加更多节点。Redis槽位通过在新节点间重新分配槽位,使水平扩展变得简单。

4.简化管理

借助槽位机制,Redis提供了高效的数据管理与定位方式。这种设计最大限度降低了分布式数据库的复杂性,确保查找和写入等操作快速完成。

Redis中槽位相关的操作

Redis提供若干命令用于管理集群中的槽位。以下是其中最常用的命令:

1.cluster keyslot:返回键值被分配到的槽位。

> cluster keyslot "user:01"
(integer) 687

2.cluster addslots:将槽位分配给特定节点。例如,将槽位 0-600 分配给某个节点:

cluster addslots 0-600

3.cluster moveslot:在节点间迁移槽位以实现集群负载均衡。

4.cluster nodes:列出集群中所有节点及其分配的槽位。

> cluster nodes
04c3b7bd9193003ef66eb9be3400a11d023578c3 192.168.137.3:6380@16380 slave b0457650c24ef93d0c11113879c91e18b530716a 0 1769392965530 3 connected
9cc35cc99d41818bd87994e45ddb6def2ce0ff09 192.168.137.4:6380@16380 slave 44ed369099e6634f96a6a0b2a2d8c67d6249e966 0 1769392968546 1 connected
b0457650c24ef93d0c11113879c91e18b530716a 192.168.137.5:6379@16379 master - 0 1769392966536 3 connected 10923-16383
c9f02a29526d4586c73b63de9d4ad4fb826f13cf 192.168.137.4:6379@16379 master - 0 1769392969551 2 connected 5461-10922
5cb355904a1fb4c4babf280f1a791eeed6e6003f 192.168.137.5:6380@16380 slave c9f02a29526d4586c73b63de9d4ad4fb826f13cf 0 1769392968000 2 connected
44ed369099e6634f96a6a0b2a2d8c67d6249e966 192.168.137.3:6379@16379 myself,master - 0 0 1 connected 0-5460

用键哈希标签优化槽位

Redis支持使用键哈希标签(key hash tags)优化槽位分配。哈希标签是键内用大括号{}包裹的子字符串。Redis通过该标签计算槽位而非整个键。

假设有以下两个键:

order:{01}:details
order:{01}:summary

由于哈希标签{01}完全相同,这两个键将被分配到同一槽位。此特性有助于确保相关键存储在同一槽位(即同一节点),从而减少跨节点通信。

> cluster keyslot order:{01}:details
(integer) 9191
> cluster keyslot order:{01}:summary
(integer) 9191

使用 Redis 槽位的最佳实践

为充分利用 Redis 槽位,请遵循以下最佳实践:

·精心设计键名:使用有意义的键名,并考虑使用哈希标签将相关键归入同一槽位。

·监控槽使用情况:使用监控工具检查槽位分布情况,确保集群内数据分布均衡。

·规划扩展方案:向集群添加节点时,需谨慎重新分配槽位以避免负载不均。

·利用复制机制:配置槽位复制以提升容错性并保障高可用性。

计算CRC16的值

def redis_crc16_table() -> list:
    """生成 Redis 使用的 CRC16 查找表"""
    table = []
    for i in range(256):
        crc = i << 8
        for _ in range(8):
            if crc & 0x8000:
                crc = (crc << 1) ^ 0x1021
            else:
                crc = crc << 1
            crc &= 0xFFFF
        table.append(crc)
    return table

def redis_crc16_lookup(data: bytes) -> int:
    """计算 Redis CRC16 值"""
    table = redis_crc16_table()
    crc = 0
    for byte in data:
        crc = ((crc << 8) & 0xFFFF) ^ table[((crc >> 8) ^ byte) & 0xFF]
    return crc

def calculate_redis_crc16_and_slot(input_str: str) -> tuple:
    """计算 Redis CRC16 值和对应的哈希槽"""
    # 计算 CRC16
    crc_value = redis_crc16_lookup(input_str.encode('utf-8'))
    
    # 计算哈希槽 (16384 个槽位)
    slot = crc_value % 16384
    
    return crc_value, slot

def main():
    """主函数:交互式计算 CRC16 和哈希槽"""
    print("=" * 50)
    print("Redis CRC16 和哈希槽计算器")
    print("=" * 50)
    print("输入要计算的键名(如:user:1001),输入 quit 退出")
    print("-" * 50)
    
    while True:
        # 获取用户输入
        user_input = input("\n请输入键名: ").strip()
        
        # 检查退出条件
        if user_input.lower() in ['quit', 'exit', 'q']:
            print("程序已退出")
            break
        
        # 检查空输入
        if not user_input:
            print("输入不能为空,请重新输入")
            continue
        
        # 计算并显示结果
        try:
            crc_value, slot = calculate_redis_crc16_and_slot(user_input)
            
            print(f"\n计算结果:")
            print(f"  键名: '{user_input}'")
            print(f"  CRC16值: {crc_value} (0x{crc_value:04X})")
            print(f"  哈希槽: {slot}")
            print(f"  验证命令: CLUSTER KEYSLOT \"{user_input}\"")
            
        except Exception as e:
            print(f"计算错误: {e}")

if __name__ == "__main__":
    main()