Redis分布式存储主从复制

news/2024/11/25 16:27:00/

分析

为什么要分布式存储

如果有1~2亿条缓存数据需要缓存,这么大的量,单台服务器指定扛不住,必须要进行分布式存储,而为了保证redis的服务不宕机,或者宕机的影响最小化,可以采用主从复制加上redis自带的哨兵模式进行一个事故处理。

分布式存储的方式

1、哈希取余

2亿条记录就是2亿个k,v,单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:
hash(key) % N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。

优点:
简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分而治之的作用。

缺点:
原来规划好的节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。
某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。

2、一致性Hash算法

容错性:
假设Node C宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单说,就是C挂了,受到影响的只是B、C之间的数据,并且这些数据会转移到D进行存储。
在这里插入图片描述
扩展性

数据量增加了,需要增加一台节点NodeX,X的位置在A和B之间,那收到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,
不会导致hash取余全部数据重新洗牌。
在这里插入图片描述

缺点:Hash环的数据倾斜问题

一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,

例如系统中只有两台服务器:
在这里插入图片描述

小总结
为了在节点数目发生改变时尽可能少的迁移数据

将所有的存储节点排列在收尾相接的Hash环上,每个key在计算Hash后会顺时针找到临近的存储节点存放。
而当有节点加入或退出时仅影响该节点在Hash环上顺时针相邻的后续节点。

优点
加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。

缺点
数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。

3、哈希槽

1 为什么出现
在这里插入图片描述
哈希槽实质就是一个数组,数组[0,2^14 -1]形成hash slot空间。

2 能干什么

解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。
在这里插入图片描述
槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。

哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。

3 多少个hash槽

一个集群只能有16384个槽,编号0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是几key就落入对应的槽里。slot = CRC16(key) % 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。

技术栈

  • 1、redis,这个不用讲了吧
  • 2、docker,因为docker能快速将需要的环境搭建起来,用实体机差不多的,把中间的命令稍微做更改就行了
  • 3、采用哈希槽的方式进行分布式存储

步骤

前提

需要自己安装docker,让后我的 docker中redis版本是 6.0.8这个版本。只需要执行docker pull redis:6.0.8这个命令就行。

然后启动6个redis实例就行了

docker run -d --name redis-1 --net host --privileged=true -v /data/redis/share/redis-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381docker run -d --name redis-2 --net host --privileged=true -v /data/redis/share/redis-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382docker run -d --name redis-3 --net host --privileged=true -v /data/redis/share/redis-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383docker run -d --name redis-4 --net host --privileged=true -v /data/redis/share/redis-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384docker run -d --name redis-5 --net host --privileged=true -v /data/redis/share/redis-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385docker run -d --name redis-6 --net host --privileged=true -v /data/redis/share/redis-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386

命令详解

  • 1、 docker run 创建并运行docker实例
  • 2、-- name redis-4 为每一个实例设置一个名字
  • 3、 --net host 网络模式,代表使用宿主机的ip和端口
  • 4、–privileged=true 使用宿主机的root权限,能写能读
  • 5、-v /data/redis/share/redis-5:/data 容器卷地址 宿主机:实例
  • 6、redis:6.0.8 redis的镜像和版本号
  • 7、–cluster-enabled yes 开启redis集群
  • 8、 --appendonly yes 开启持久化
  • 9、–port 6386 redis端口号

执行完上述命令,可以输入docker ps 命令查看当前运行的实例都有哪些
在这里插入图片描述

随便输入命令docker exec -it redis-1 bash命令进入的其中一台,然后输入redis-cli -p 6381 进入的redis中,发现输入set key value会提示在这里插入图片描述
说没有提供哈希槽,是不能直接使用的。
接下来分配主从机器,将ip换成你们自己的ip

redis-cli --cluster create 172.16.16.144:6381 172.16.16.144:6382 172.16.16.144:6383 172.16.16.144:6384 172.16.16.144:6385 172.16.16.144:6386 --cluster-replicas 1
  • –cluster-replicas 1 表示为每个master创建一个slave节点

在这里插入图片描述
第一个框指出了哈希槽的分配情况,第二个指出了那些是主服务,那些事从服务。最后询问了是否遵循以上设置,输入yes进入下一步。
在这里插入图片描述
出现以上提示代表成功了。

查看集群状态

然后还以 名字为redis-1这台机器作为切入点,命令为docker exec -it redis-1 bash,进入后输入redis-cli -p 6381
在这里插入图片描述
可以看到状态时OK的,并且知道有6个节点。
可以输入 cluster nodes 查看每个节点的状态
在这里插入图片描述
上面可以看出,端口为 6381、6382、6383三台机器为主服务器,其余三台为从服务。可以看看出每个机器分配的哈希槽的范围。

可以通过redis-cli --cluster check 172.16.16.144:6381这么命令查看每个节点存储的信息,现在并没有存入任何信息,可以看到都是0个key,也能看到每一台主服务器都有一台从服务器。

存入数据

如果时通过普通的redis-cli -p直接进入会出现以下情况
在这里插入图片描述
原是key1这个key 哈希计算后的插槽并不在这台机器上
在这里插入图片描述
key2 这个key的哈希在这这台机器上。对于这个情况,需要在连接的时候加上参数 -c就行了,redis就能自动帮把数据路由到位置。

在这里插入图片描述
提示说已经把这个数据移动到开放端口为6382这台机器上了。然后检查集群
在这里插入图片描述
看到有两个key已经放入到了对应的主机上

容错切换

  • redis的策略是如果主服务挂了,从服务器会立马顶上,不过不知道这个和哨兵模式有什么联系,反转能顶。

现在假如6381这台服务器宕机了,就是先停掉了这台服务。然后端口为6382这台服务器重启了
在这里插入图片描述
然后进入端口为6382这台服务器。
输入redis-cli --cluster check 172.16.16.144:6381
在这里插入图片描述
可以看到端口为6386这台机器顶上了之前宕机的这台机器,插槽也继承了宕机的那台。然后重启的端口为6382这台机器,然后6382这台机器还是mast节点。

最后还原三主三从,发现端口为6381这台服务器并没成为主服务器
在这里插入图片描述
也就是具体的主从服务器要具体来看。


http://www.ppmy.cn/news/599462.html

相关文章

【Redis7】Redis7 集群(重点:哈希槽分区)

【大家好,我是爱干饭的猿,本文重点介绍Redis7 集群概述、作用、集群算法-分片-槽位slot、集群环境案例步骤、集群常用操作命令和CRC16算法。 后续会继续分享Redis7和其他重要知识点总结,如果喜欢这篇文章,点个赞👍&am…

Java 集合面试系列-04

1. 【腾讯】说说 B-tree、Btree 的区别和使用场景? 2. 【阿里巴巴】有10 亿个 url,每个 url 大小小于 56B,要求去重,内存只给你4G 3. Java 集合类框架的基本接口有哪些? 集合类接口指定了一组叫做元素的对象。集合类接…

MVG(second)学习笔记- 基础矩阵F和本质矩阵E 单应矩阵H计算

非常感谢Jichao_Peng和.https://zhuanlan.zhihu.com/p/55567702 基础矩阵F和本质矩阵E 单应矩阵H求解 不管是是那种矩阵,在求解方法的分类上大致是都可以分为基于代数误差的线性估计和基于几何误差的非线性估计。在基于代数误差的线性估计中,不管是那种矩…

【Redis】集群存储算法

集群存储算法 一、集群存储算法1.1、分布式存储算法1.2、哈希取余算法分区1.3、一致性哈希算法1.4、哈希槽分区1.5、Redis集群存储策略 一、集群存储算法 1.1、分布式存储算法 分布式存储的常见算法: 哈希取余算法分区一致性哈希算法分区哈希槽算法分区 1.2、哈…

C#程序连接达梦数据库相关问题处理

开发环境说明 开发语言:C# 框架:.NETCore 问题及处理 问题1 对数据库进行操作时,报错: System.NullReferenceException:“Object reference not set to an instance of an object. 原因: 这是由于对应项目中缺少Dm…

【频谱分配】基于频谱空洞预留算法的频谱分配算法的matlab仿真

1.软件版本 MATLAB2013a2.本算法理论知识 基于概率切换和最小化概率切换的频谱切换算法,由于过多的考虑了资源的合理利用,使得次用户的不切换概率并大于等于的情况,从而导致对应的次用户的服务质量显著下降,考虑到这个因素&#…

MATLAB算法实战应用案例精讲-【智能优化算法】 基于帕累托包络的选择算法II(PESA-II)(附MATLAB代码实现)

目录 前言 知识储备 数据包络分析(DEA) 特点 名词解释 类型介绍 案例简介 软件操作(SPSSPRO)