19.Redis之集群

1.集群的基本介绍

  • 集群 这个词.
  • 广义的集群,只要你是多个机器,构成了分布式系统, 都可以称为是一个"集群"前面主从结构,哨兵模式,也可以称为是"广义的集群”
  • 狭义的集群,redis 提供的集群模式, 这个集群模式之下,主要是要解决,存储空间不足的问题(拓展存储空间)

哨兵模式提高了系统的可用性
哨兵模式中,本质上还是 redis 主/从节点(内存,256G,512G.上 TB 的服务器也不是没有(贵))存储数据,其中就要求一个主节点/从节点,就得存储整个数据的"全集

  • 此处关键问题,就是引入多台机器,每台机器存储一部分数据,
  • 设 有 1TB 的数据需要存储.
  • 拿两台机器来存,每个机器只需要存 512GB 即可.
  • 拿三台机器来存,每个机器只需要存 300 多 GB 即可, 
  • 拿四台机,器来存,每个机器只需要存 256GB.....
  • 随着机器数目的增加,每个机器存储的数据量就减少了
  • 【只要机器的规模足够多,就可以存储任意大小的数据了,(公司的实力)】
  • 【不是说光搞3个机器就够了每个存储数据的机器还需要搭配若于个从节点】

2.如何把数据分成多分?

  • 把数据分成多份,应该怎么分?
  • 是一个 分片(sharding).
  • 三种主流的分片方式,
  • 1.哈希求余

  • 借鉴了哈希表的基本思想.
    借助 hash 函数,把一个 key 映射到整数,再针对数组的长度
    求余,就可以得到一个数组下标.
  • 比如有三个分片,编号 012
    此时就可以针对要插入的数据的 key(redis 都是 键值对 结构的数据)计算 hash 值.(比如,使用 md5)【md5 本身就是一个计算 hash 值的算法针对一个字符串,里面的内容进行一系列的数学变换 =>整数.】再把这个 hash 值余上分片个数,就得到了一个下标,此时就可以把这个数据放到该下标对应的分片中了.
  • 【缺陷】
  • 一旦服务器集群需要扩容,就需要更高的成本了
    分片主要目的就是为了能提高存储能力.
    分片越多,能存的数据越多,成本也更高,
  • 一般都是先少搞几个分片.(3 个)
    但是随着业务逐渐增长,数据变多了~~3 个分片就已经不足以保存了
  • 就需要"扩容”
    引入新的分片,N 就改变了
    hash(key)% N >=0
  • 当 hash 函数和 key 都不变的情况下,如果 N 改变了整体的分片结果仍然会变!!
  • 如果发现某个数据,在扩容之后,不应该待在当前的分片中了,就需要重新进行分配 (搬运数据)
  • 此处列出的这些值,就可以脑补成 hash(key)假设当前计算完 hash 值之后,得到的 数值正好是 100-120
  • 共 20 个数据,只有 3 个数据不需要搬运~~ 搬运了 17 个数据如果是 20 亿 个数据呢?? 17 亿数据就要搬运...这就是一个大活了!!
  • 上述级别的扩容,开销极大的,往往是不能直接在生产环境上操作的,只能通过"替换"的方式来实现扩容。
  • 依赖的机器更多了.成本更高,操作步骤非常复杂!!!
  • 2.一致性哈希算法

  • 会导致数据不均匀的问题
  • 此时, 只需要把 0 号分⽚上的部分数据, 搬运给 3 号分⽚即可. 1 号分⽚和 2 号分⽚管理的区间都是不变的.
  • 优点: ⼤⼤降低了扩容时数据搬运的规模, 提⾼了扩容操作的效率.
  • 缺点: 数据分配不均匀 (有的多有的少, 数据倾斜).
  • 3.哈希槽分区算法

  • 【问题1】
  • Redis 集群是最多有 16384 个分片吗?
  • 每个分片上就只有一个槽位.(此时很难保证数据在各个分片上的均衡性~~)(有的槽位可能是 有多个 key,有的槽位可能是 没有 key ~)
  • key 是要先映射到槽位,再映射到分片的
  • 如果每个分片包含的槽位比较多,如果槽位个数相当, 就可以认为是包含的 key 数量相当的:
  • 如果每个分片包含的槽位非常少,槽位个数不一定能直观的反应到 key 的数目
  • 实际上 Redis 的作者建议集群分片数不应该超过(1000.
  • 如果真是1.6w 个分片,整个数据服务器的集群规模就太可怕了
  • 几万台主机构成的集群了.整个集群的可用性是非常堪忧的!!
  • 【问题2】
  • 问题二: 为什么是 16384 个槽位?
  • 心跳包中包含了该节点持有哪些 slots.
  • 需要表示出该节点持有哪些槽位
  • 虽然 8kb 比2kb 也大不了多少, 但是心跳包,周期性通信的.(非常频繁 & 网络带宽
  • 这个值个数上基本够用了.同时占用的硬件资源(网络带宽)又不是很大

 

3.搭建集群环境

3.1 生成配置文件

  • 基于 docker 在咱们云服务器上搭建出一个 redis 集群出来.
  • 当前阶段,主要是因为咱们只有一个 云服务器,搞分布式系统, 就比较麻烦
  • 实际工作中,一般是通过多个主机的方式,来搭建集群的,
第⼀步: 创建⽬录和配置
创建 redis-cluster ⽬录. 内部创建两个⽂件
一定要记得,把之前启动 redis 容器,给停止掉!!

  • 在 linux 上,以 .sh 后缀结尾的文件,称为"shell(脚本)【剧本,也可以称为脚本,】
  • 使用 linux 的时候, 都是通过一些命令来进行操作的.
  • 使用命令操作,就非常适合把命令给写到一个文件中,批量化执行,
  • 同时,还能加入, 条件,循环,函数 等机制
  • 因此,就可以基于这些来完成更复杂的工作了
  • 需要创建 11 个 redis 节点.这些 redis 的配置文件内容,大同小异.
  • 此时就可以使用脚本来批量生成.(也可以不使用脚本,手动一个一个改)
  • generate.sh 内容如下
  • for port in $(seq 1 9); \
    do \
    mkdir -p redis${port}/
    touch redis${port}/redis.conf
    cat << EOF > redis${port}/redis.conf
    port 6379
    bind 0.0.0.0
    protected-mode no
    appendonly yes
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    cluster-announce-ip 172.30.0.10${port}
    cluster-announce-port 6379
    cluster-announce-bus-port 16379
    EOF
    done
    # 注意 cluster-announce-ip 的值有变化. 
    for port in $(seq 10 11); \
    do \
    mkdir -p redis${port}/
    touch redis${port}/redis.conf
    cat << EOF > redis${port}/redis.conf
    port 6379
    bind 0.0.0.0
    protected-mode no
    appendonly yes
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    cluster-announce-ip 172.30.0.1${port}
    cluster-announce-port 6379
    cluster-announce-bus-port 16379
    EOF
    done
  •  
  • 成功!!!

3.2 创建容器 

  • 编写 docker-compose.yml

  • version: '3.3'
    networks:
      mynet:
        ipam:
          config:
            - subnet: 172.30.0.0/24
    services:
      redis1:
        image: 'redis:5.0.9'
        container_name: redis1
        restart: always
        volumes:
          - ./redis1/:/etc/redis/
        ports:
          - 6371:6379
          - 16371:16379
        command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.101
      redis2:
        image: 'redis:5.0.9'
        container_name: redis2
        restart: always
        volumes:
          - ./redis2/:/etc/redis/
        ports:
          - 6372:6379
          - 16372:16379
        command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.102
      redis3:
        image: 'redis:5.0.9'
        container_name: redis3
        restart: always
        volumes:
          - ./redis3/:/etc/redis/
        ports:
          - 6373:6379
          - 16373:16379
    command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.103
      redis4:
        image: 'redis:5.0.9'
        container_name: redis4
        restart: always
        volumes:
          - ./redis4/:/etc/redis/
        ports:
          - 6374:6379
          - 16374:16379
        command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.104
      redis5:
        image: 'redis:5.0.9'
        container_name: redis5
        restart: always
        volumes:
          - ./redis5/:/etc/redis/
        ports:
          - 6375:6379
          - 16375:16379
        command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.105
      redis6:
        image: 'redis:5.0.9'
        container_name: redis6
        restart: always
        volumes:
          - ./redis6/:/etc/redis/
        ports:
          - 6376:6379
          - 16376:16379
    command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.106
      redis7:
        image: 'redis:5.0.9'
        container_name: redis7
        restart: always
        volumes:
          - ./redis7/:/etc/redis/
        ports:
          - 6377:6379
          - 16377:16379
        command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.107
      redis8:
        image: 'redis:5.0.9'
        container_name: redis8
        restart: always
        volumes:
          - ./redis8/:/etc/redis/
        ports:
          - 6378:6379
          - 16378:16379
        command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.108
      redis9:
        image: 'redis:5.0.9'
        container_name: redis9
        restart: always
        volumes:
          - ./redis9/:/etc/redis/
        ports:
          - 6379:6379
          - 16379:16379
    command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.109
    
      redis10:
        image: 'redis:5.0.9'
        container_name: redis10
        restart: always
        volumes:
          - ./redis10/:/etc/redis/
        ports:
          - 6380:6379
          - 16380:16379
        command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.110
      redis11:
        image: 'redis:5.0.9'
        container_name: redis11
        restart: always
        volumes:
          - ./redis11/:/etc/redis/
        ports:
          - 6381:6379
          - 16381:16379
        command:
          redis-server /etc/redis/redis.conf
        networks:
          mynet:
            ipv4_address: 172.30.0.111
    

3.3 配置集群关系 

1)生成每个 redis 节点的配置文件
2)使用 docker 创建出 11 个 redis 节点, 并且启动容器
3)使用 redis-cli 执行构建集群命令

redis-cli --cluster create 172.30.0.101:6379 172.30.0.102:6379 172.30.0.103:6379 172.30.0.104:6379 172.30.0.105:6379 172.30.0.106:6379 172.30.0.107:6379 172.30.0.108:6379 172.30.0.109:6379 --cluster-replicas 2

3.4 使用集群

  • redis-cli -h 172.30.0.101 -p 6379
  • 4.故障处理

  •  

5.集群扩容 

101-1099个主机,构成了3主,6 从结构的集群了
110 和 111 也加入到集群中
以110为 master, 111为 slave.=>把数据分片从 3->4
集群扩容操作,是一件风险较高,成本较大的操作!!!

1.新的主节点(110) 加入到集群中
redis-cli --cluster add-node 172.30.0.110:6379 172.30.0.101:6379

 2.重新分配 slots

redis-cli --cluster reshard 172.30.0.101:6379

 

3.给新的主节点添加从节点
光有主节点了, 此时扩容的⽬标已经初步达成. 但是为了保证集群可⽤性, 还需要给这个新的主节点添加从节点, 保证该主节点宕机之后, 有从节点能够顶上 
redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --cluster-slave --cluster-master-id c999d6e82415680b57868cc3c59f9f1a779a59cd

6.集群的缩容

把一些节点拿掉,减少分片的数量,
般都是进行扩容,很少缩容!

7.小结

1)集群是什么,解决了什么问题?
2)数据分片算法[重点/考点]
a)哈希求余
b)一致性哈希算法
c)哈希槽分区算法(redis)
3)搭建 redis 集群,
4)集群容灾.故障转移
5)集群扩容.
6)代码连接集群
使用的库, 得能够支持 集群模式.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

原生小程序一键获取手机号

1.效果图 2.代码index.wxml <!-- 获取手机号 利用手机号快速填写的功能&#xff0c;将button组件 open-type 的值设置为 getPhoneNumber--><button open-type"getPhoneNumber" bindgetphonenumber"getPhoneNumber">获取手机号</button> …

【再探】设计模式—访问者模式、策略模式及状态模式

访问者模式是用于访问复杂数据结构的元素&#xff0c;对不同的元素执行不同的操作。策略模式是对于具有多种实现的算法&#xff0c;在运行过程中可动态选择使用哪种具体的实现。状态模式是用于具有不同状态的对象&#xff0c;状态之间可以转换&#xff0c;且不同状态下对象的行…

Threejs(WebGL)绘制线段优化:Shader修改gl.LINES模式为gl.LINE_STRIP

目录 背景 思路 Threejs实现 记录每条线的点数 封装原始裁剪索引数据 封装合并几何体的缓冲数据&#xff1a;由裁剪索引组成的 IntArray 守住该有的线段&#xff01; 修改顶点着色器 修改片元着色器 完整代码 WebGL实现类似功能&#xff08;简易版&#xff0c;便于测…

极验4点选逆向 JS逆向分析 最新版验证码

目录 声明&#xff01; 一、请求流程分析 二、加密参数w与payload 三、参数w生成位置 四、结果展示&#xff1a; 原创文章&#xff0c;请勿转载&#xff01; 本文内容仅限于安全研究&#xff0c;不公开具体源码。维护网络安全&#xff0c;人人有责。 声明&#xff01; 本文章…

mirth Connect 自定义JAVA_HOME

mirth Connect 自定义JAVA_HOME 1、背景 服务器上安装了两个不同版本的Java&#xff0c;我希望Mirth服务使用与默认系统不同的版本。自定义指定java版本 2、解决方法 2.1 优先级说明 系统变量JAVA_HOME (设置后&#xff0c;mirth会根据这个进行启动运行服务&#xff0c;优先级…

家政预约小程序10公众号集成

目录 1 使用测试号3 工作流配置4 配置关注事件脚本5 注册开放平台6 获取公众号access_token6 实现关注业务逻辑总结 我们本次实战项目构建的相当于一个预约平台&#xff0c;既有家政企业&#xff0c;也有家政服务人员还有用户。不同的人员需要收到不同的消息&#xff0c;比如用…

根据状态转移图实现时序电路 (三段式状态机)

看图编程 * ** 代码 module seq_circuit(input C ,input clk ,input rst_n,output wire Y ); reg [1:0] current_stage ; reg [1:0] next_stage ; reg Y_reg; //输出//第一段 &#xff1a; 初始化当前状态和…

vmware esxi虚拟化数据迁移

1、启用esxi的ssh 登录esxi的web界面&#xff0c;选择主机-》操作——》服务——》启动ssh 2.xshell登录esxi 3、找到虚拟机所在目录 blog.csdnimg.cn/direct/d57372536a4145f2bcc1189d02cc7da8.png)#### 3在传输数据前需关闭防火墙服务 查看防火墙状态&#xff1a;esxcli …

vue3学习(六)

前言 接上一篇学习笔记&#xff0c;今天主要是抽空学习了vue的状态管理&#xff0c;这里学习的是vuex&#xff0c;版本4.1。学习还没有学习完&#xff0c;里面有大坑&#xff0c;难怪现在官网出的状态管理用Pinia。 一、vuex状态管理知识点 上面的方式没有写全&#xff0c;还有…

如何修改开源项目中发现的bug?

如何修改开源项目中发现的bug&#xff1f; 目录 如何修改开源项目中发现的bug&#xff1f;第一步&#xff1a;找到开源项目并建立分支第二步&#xff1a;克隆分支到本地仓库第三步&#xff1a;在本地对项目进行修改第四步&#xff1a;依次使用命令行进行操作注意&#xff1a;Gi…

OAK相机如何将 YOLOv9 模型转换成 blob 格式?

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是Ashely。 专…

逆天工具一键修复图片,视频去码。简直不要太好用!

今天&#xff0c;我要向您推荐一款功能强大的本地部署软件&#xff0c;它能够在您的计算机上一键修复图片和视频&#xff0c;去除令人不悦的码赛克&#xff08;轻度马赛克&#xff09;。这款软件是开源的&#xff0c;并在GitHub上公开可用&#xff0c;您可以免费下载并使用。 …

智能制造案例专题|与MongoDB一起解锁工业4.0转型与增长的无限潜力!

MongoDB 智能制造 数字化技术的洪流在各个产业链的主干和枝节涌现。在工业制造领域&#xff0c;能否通过数字化技术实现各生产要素、生产环节之间的紧密配合&#xff0c;高效规划、管理整个生产流程&#xff0c;是企业提升韧性、赢得竞争的关键。随着工业4.0的深入发展和智能…

Kafka自定义分区器编写教程

1.创建java类MyPartitioner并实现Partitioner接口 点击灯泡选择实现方法&#xff0c;导入需要实现的抽象方法 2.实现方法 3.自定义分区器的使用 在自定义生产者消息发送时&#xff0c;属性配置上加入自定义分区器 properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,&q…

stack和queue(1)

一、stack的简单介绍和使用 1.1 stack的介绍 1.stack是一种容器适配器&#xff0c;专门用在具有先进后出&#xff0c;后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入和弹出操作。 2.stack是作为容器适配器被实现的&#xff0c;容器适配器即是…

C++ 混合运算的类型转换

一 混合运算和隐式转换 257 整型2 浮点5 行吗&#xff1f;成吗&#xff1f;中不中&#xff1f; C 中允许相关的数据类型进行混合运算。 相关类型。 尽管在程序中的数据类型不同&#xff0c;但逻辑上进行这种运算是合理的相关类型在混合运算时会自动进行类型转换&#xff0c;再…

EXCEL数据透视图中的日期字段,怎样自动分出年、季度、月的功能?

在excel里&#xff0c;这个果然是有个设置的地方&#xff0c;修改后就好了。 点击文件选项卡&#xff0c;选项&#xff0c;在高级里&#xff0c;将图示选项的勾选给取消&#xff0c;然后再创建数据透视表或透视图&#xff0c;日期就不会自动组合了&#xff1a; 这个选项只对新…

Scroll 生态明星项目Pencils Protocol,发展潜力巨大

近日&#xff0c;完成品牌升级的 Pencils Prtocol 结束了 Season 2 并无缝开启了 Season 3&#xff0c;在 Season 3 中&#xff0c;用户可以通过质押系列资产包括 $ETH、$USDT、$USDC、$STONE 、$wrsETH、$pufETH 等来获得可观收益&#xff0c;并获得包括 Scroll Marks、 Penci…

html+CSS部分基础运用9

项目1 参会注册表 1.设计参会注册表页面&#xff0c;效果如图9-1所示。 图9-1 参会注册表页面 项目2 设计《大学生暑期社会实践调查问卷》 1.设计“大学生暑期社会实践调查问卷”页面&#xff0c;如图9-2所示。 图9-2 大学生暑期社会调查表页面 2&#xff0e;调查表前导语的…

C/C++中互斥量(锁)的实现原理探究

互斥量的实现原理探究 文章目录 互斥量的实现原理探究互斥量的概念何为原子性操作原理探究 互斥量的概念 ​ 互斥量&#xff08;mutex&#xff09;是一种同步原语&#xff0c;用于保护多个线程同时访问共享数据。互斥量提供独占的、非递归的所有权语义&#xff1a;一个线程从成…