Redis集群(Cluster和Codis)

news2024/11/15 12:45:52

1.为什么使用集群?

        当我们遇到一个大数据量存储情况时,有两种解决方案:

        纵向扩容:升级单个redis实例的配置,包括增加内存容量、磁盘容量,以及使用更高的cpu配置。

        纵向扩容:简单直接。也存在一些问题:当使用RDB对数据进行持久化时,如果数据量增加,需要的内存也会增加,主线程fork子进程就可能阻塞;第二个问题就是硬件和成本的限制。

        横向扩容:横向增加当前redis实例的数量,降数据分配到多个实例中;

        现实情况下,在面对千万级甚至亿级别的流量的时候,很多大厂都是在千百台的实例节点组成的集群上进行流量调度、服务治理的。所以,使用集群模式,是业内广泛采用的模式。

下面简单说下横向扩容也就是Redis的Cluster集群模式以及Codis。

我们使用集群模式首先会想到两个问题:

        1.数据如何在多个实例之间分布的

        2.客户端怎么确定要访问的数据在哪个实例上

        3.hash槽重新分配时,接到请求如何处理

2.Redis Cluster

        2.1 数据在多实例间的分配

         简单的说Redis Cluster采用哈希槽(Hash Slot 简称slot)来处理数据和实例之间的映射关系,在Redis Cluster方案中,一个集群共有16384(为什么是这个数)个slot,每个键值对都会根据他的key,被映射到一个slot上。每个key通过CRC16算法计算一个16bit值然后对16384取模,来决定放到哪个slot,每个节点负责维护一部分槽以及slot所映射的键值数据。

        公式:slot = CRC16(key) & 16383

        为什么使用hash槽概念?(不使用一致性hash)参考:浅析一致性hash和hash槽_hash槽和一致性hash_蓝桉未与的博客-CSDN博客

        很容易添加或者删除节点:

        比如如果我想新添加个节点D, 我需要从节点 A, B, C中转移部分槽到D上即可.如果我像移除节点A,需要将A中得槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可

        由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。

        2.2 client定位数据节点

        既然我们知道了数据如何存储到hash槽的,那客户端又是如何知道要访问的数据在哪一个实例上的呢?

        在定位键值对数据时,所处的slot可以通过计算得到的,这个计算可以在客户端发送请求时来执行,但是还需要知道这个slot在哪个实例上。

        当客户端与集群建立连接后,实例就会把slot的分配信息发给客户端,同时redis的实例会把自己的slot信息向其他相连接的实例同步,来完成slot分配信息的扩散,所以每个实例就会知道所有的slot分配信息了。

        客户端接收到信息后,会吧hash槽信息缓存到本地,当客户端请求键值对是,会先计算键所对应的hash槽,然后就可以给相应的实例发送请求了。

        2.3 数据迁移

        在集群中实例和hash槽的对应关系并不是一成不变的,常见的变化有以下两个:

        1.新增或者删除实例,Redis需要重新分配hash槽

        2.负载均衡,redis需要把hash槽重新分配一遍

        实例之间是可以相互传递消息的,获得最新的哈希槽分配信息,但是客户端并不能实时获取这些信息,这就会导致,缓存的分配信息和最新的不一致,当这种情况出现时,会怎么办呢?

        Redis Cluster提供了一种重定向机制,就是指,当客户端给一个实例发送读写操作时,这个实例上并没有相应的数据,客户端还要再给新的实例再发送一次。

        重定向机制包含两种:moved重定向和ask重定向。

        moved重定向:

  • 1.每个节点通过通信都会共享Redis Cluster中槽和集群中对应节点的关系。
  • 2.客户端向Redis Cluster的任意节点发送命令,接收命令的节点会根据CRC16规则进行hash运算与16383取余,计算自己的槽和对应节点 。
  • 3.如果保存数据的槽被分配给当前节点,则去槽中执行命令,并把命令执行结果返回给客户端。
  • 4.如果保存数据的槽不在当前节点的管理范围内,则向客户端返回moved重定向异常 。
  • 5.客户端接收到节点返回的结果,如果是moved异常,则从moved异常中获取目标节点的信息。
  • 6.客户端向目标节点发送命令,获取命令执行结果。

        ask重定向:

        在对集群进行扩容和缩容时,需要对槽及槽中数据进行迁移。当槽及槽中数据正在迁移时,客服端请求目标节点时,目标节点中的槽已经迁移支别的节点上了,此时目标节点会返回ask转向给客户端。

  • 1.当客户端向集群中某个节点发送命令,节点向客户端返回moved异常,告诉客户端数据对应目标槽的节点信息。
  • 2.客户端再向目标节点发送命令,目标节点中的槽已经迁移出别的节点上了,此时目标节点会返回ask重定向给客户端。
  • 2.客户端向新的target节点发送Asking命令,然后再次向新节点发送请求请求命令。
  • 3.新节点target执行命令,把命令执行结果返回给客户端。

两者的区别:moved迁移了,ask:迁移中

思考:

16384(为什么是这个数)?作者的回答:https://github.com/antirez/redis/issues/2576

1.如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。

        在消息头中,最占空间的是 myslots[CLUSTER_SLOTS/8]。当槽位为65536时,这块的大小是: 65536÷8=8kb因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。

2.redis的集群主节点数量基本不可能超过1000个。

        如上所述,集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者,不建议redis cluster节点数量超过1000个。那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。

3.槽位越小,节点少的情况下,压缩率高。

        Redis主节点的配置信息中,它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中,会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。而16384÷8=2kb,怎么样,神奇不!

3.Codis

        3.1 整体架构和基本流程

  • Codis Proxy   (codis-proxy):接受客户端请求,并转发给codis-server。

        客户端连接的 Redis 代理服务,codis-proxy 本身实现了 Redis 协议,表现得和一个原生的 Redis 没什么区别 (就像 Twemproxy), 对于一个业务来说,可以部署多个 codis-proxy, codis-proxy 本身是无状态的。

  • Codis Manager (codis-config):Codis 的管理工具,支持包括,添加 / 删除 Redis 节点,添加 / 删除 Proxy 节点,发起数据迁移等操作. codis-config 本身还自带了一个 http server, 会启动一个 dashboard, 用户可以直接在浏览器上观察 Codis 集群的运行状态.

  • Codis Redis   (codis-server):进行了二次开发的redis实例,其中增加了额外的数据结构,支持数据迁移操作,主要负责处理具体的数据读写请求。

  • ZooKeeper:存放数据路由表和 codis-proxy 节点的元信息,codis-config 发起的命令都会通过 ZooKeeper 同步到各个存活的 codis-proxy.

处理流程

 3.2 数据多实例间的分配

        在Codis集群中,一个数据保存在哪个实例上,也是通过逻辑槽来完成的。

        1.Codis集群中一共1024个Slot,我们可以手动分配,也可以让Codis dashboard自动分配

        2.如何确定key放到哪个slot上呢?当客户端读写数据时,会使用CRC32算法计算key的哈希值,然后对1024取摸,对应slot的编号,就知道分配到哪个实力上了。

        我们把Slot和server的映射关系成为数据路由表,分配好路由表后,会把路由表发送给Codis proxy,codis proxy 会把路由表缓存到本地,当客户端收到请求后,直接查询本地路由表,完成正确的转发;同时,也会把路由表保存在zookeeper中。

        同时,数据路由表在每个实例也会进行通信传递的,每个实例上都会保存一份,数据路由发生变化时,就需要在所有实例间通过网络消息进行传递。如果实例较多的话,就会消耗较多的集群网络资源。

 3.3 扩容和数据迁移(待补充)

 欢迎大家访问:http://mumuxi.chat/

http://mumuxi.chat/articles/149 (资源分享# ai一些免费的GPT 4)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/759135.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

98英寸带来加倍沉浸享受,三星Q80Z新品呈现大有不同的精彩

作者 | 曾响铃 文 | 响铃说 在过去几年,家电行业可以说是负重前行。在经历2022年整年寒冬后,2023年的彩电市场能否迎来一场翻身仗?这是年初被业内讨论最多的话题。 目前2023年已经过半,据奥维云网数据显示,2023年一…

InsCode Stable Diffusion 美图活动一期——即刻体验!来自 CSDN 的 SD 模型

文章目录 🔥关于活动📋前言🎯什么是 Stable Diffusion🧩Stable Diffusion 与其他 AI 艺术生成器有什么区别? 🎯开始体验 InsCode Stable Diffusion🎯试用 SD 模型生成优质人物好图🧩…

内存池是什么原理?|内存池简易模拟实现|为学习高并发内存池tcmalloc做准备

前言 那么这里博主先安利一些干货满满的专栏了! 这两个都是博主在学习Linux操作系统过程中的记录,希望对大家的学习有帮助! 操作系统Operating Syshttps://blog.csdn.net/yu_cblog/category_12165502.html?spm1001.2014.3001.5482Linux S…

在Linux系统中如何搭建Apache服务

在Linux系统中如何搭建Apache服务 Apache服务是一种开源的、跨平台的Web服务器软件,它的作用是提供网页内容给用户的Web浏览器。具体来说,Apache服务有以下几个主要的作用: 1.Web服务器:Apache是一款功能强大且广泛使用的Web服务…

54、Mysql索引的数据结构,各自优劣

Mysql索引的数据结构,各自优劣 索引的数据结构和具体存储引擎的实现有关在MySQL中使用较多的索引有Hash索引,B树索引等InnoDB存储引擎的默认索引实现为: B树索引。对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求…

C++编程(三)—— C++11

文章目录 绑定器和函数对象函数对象绑定器lambda表达式 关键词与语法autonullptr右值引用 智能指针容器set和mapunordered_set和unordered_map数组链表 语言级别支持的多线程编程thread子线程如何结束主线程如何处理子线程线程间的互斥线程的同步通信机制(条件变量&…

Windows Cluster 分布式算法

在分布式系统中,都需要解决分布式一致性问题。那么,在Windows 集群中,使用了什么算法来保证集群的一致性呢——Paxos。Windows Server 故障转移集群 (WSFC) 使用 Paxos 算法在整个系统中同步更改。通过记录 Paxos Tag 值并保留历史记录&#…

连锁门店如何搭建B2B2C多用户商城系统?

现在很多的线下店铺都开始慢慢的转型线上了,想线上线下相结合,但是最近很多的商家都在问什么样的B2B2C商城系统开发适合线下店铺呢?这个问题今天加速度jsudo小编给大家一起整理如下,相信商家看完后就知道如何选择一款合适的商城系统了。 一、…

【C语言】求序列前N项和

问题描述 输入一个正整数n&#xff0c;输出2/13/25/38/5…的前n项之和&#xff08;该序列从第2项起&#xff0c;每一项的分子是前一项分子与分母的和&#xff0c;分母是前一项的分子&#xff09;&#xff0c;保留2位小数。试编写相应程序。 代码实现 #include<stdio.h>…

spring-14优化性能

原始Junit测试Spring的问题 这里的&#xff1a;第一行代码获得应用上下文对象&#xff0c;第二行代码获得你那个对象 2、原先测试找junit&#xff0c;现在测试找spring&#xff0c;然后再找&#xff0c;junit&#xff0c;告诉我配置文件是什么&#xff0c;然后注入测试对象&am…

LeetCode 172.阶乘后的零

基础方法就是暴力解&#xff0c;其次是数学归纳。 具体思路如下&#xff1a;&#xff08;copy大佬的&#xff09; 耐心看完&#xff01; 代码如下&#xff1a; #include <iostream> #include <vector> #include <cmath> #include <algorithm> #incl…

Android GridPager实战,从RecyclerView to ViewPager

这个简单的的案例展示了如何从RecyclerView to ViewPager&#xff0c;以网上的公开图片为样例。 安卓开发中从RecyclerView 到 ViewPager demo运行结果demo项目工程目录结构关键代码 MainActivity关键代码GridFragment关键代码ImageFragment关键代码ImagePagerFragment关键布局…

关于示波器引入50HZ工频干扰的解释

前几天&#xff0c;小白在实验室工作时&#xff0c;听到同事抱怨示波器有问题。上前查看&#xff0c;才知道&#xff0c;小白的那位同事在测量信号波形时&#xff0c;实际与理想相差甚远。于是乎&#xff0c;在探头什么也不接的情况下&#xff0c;发现示波器本身也存在波形信号…

2022Robocom国赛-u2 女王的大敕令

副本是游戏里的一个特色玩法&#xff0c;主要为玩家带来装备、道具、游戏资源的产出&#xff0c;满足玩家的游戏进程。 在 MMORPG《最终幻想14》里&#xff0c;有一个攻略人数最大达到 48 人的副本“零式贡希尔德神庙”&#xff0c;其中守关 BOSS “天佑女王”有一个很有趣的技…

图形编辑器开发:一些会用到的简单几何算法

大家好&#xff0c;我是前端西瓜哥。 开发图形编辑器&#xff0c;你会经常要解决一些算法问题。本文盘点一些我开发图形编辑器时遇到的简单几何算法问题。 矩形碰撞检测 判断两个矩形是否发生碰撞&#xff08;或者说相交&#xff09;&#xff0c;即两个矩形有重合的区域。 …

C生万物 | 程序员必备实用调试技巧分享

一起来学习调试~ 一、前言二、什么是Bug&#xff1f;三、调试是什么&#xff1f;有多重要&#xff1f;1、导学引入2、调试的基本步骤3、Debug和Release的介绍 四、Windows环境下VS调试介绍1、调试环境的准备2、学会快捷键3、调试的时候查看程序当前信息3.1 查看临时变量的值3.2…

基于SSM的购物商城系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

SpringBoot中通过自定义Jackson注解实现接口返回数据脱敏

场景 SpringBoot中整合Sharding Sphere实现数据加解密/数据脱敏/数据库密文&#xff0c;查询明文&#xff1a; SpringBoot中整合Sharding Sphere实现数据加解密/数据脱敏/数据库密文&#xff0c;查询明文_霸道流氓气质的博客-CSDN博客 上面讲的是数据库中存储密文&#xff0…

音乐格式转换mp3软件有哪些?分享三个方法给大家!

要将音乐文件转换为MP3格式的情况&#xff0c;以便在各种设备上播放。为了帮助大家完成这个任务&#xff0c;下面将分享三种实用的方法和工具&#xff0c;其中方法一是使用记灵在线工具进行音乐格式转换。无论您是音乐爱好者还是需要将音频文件转换为MP3格式的专业人士&#xf…

障碍物距离显示需求功能定义

1. 需求 来源 整车功能定义清单中SAF-10 -06 条需求 。泊车视觉辅助 &#xff0c;360全景 -距离树数值显示时&#xff0c;显示车辆与障碍物的距离数字 。 2. 开发 范围 项目带全景功能的配置&#xff0c;见最新配置表&#xff1a; 3. 功能 定义 在雷达报警激活状态下&#xff0…