Maison  >  Article  >  base de données  >  Comment installer un cluster à six nœuds dans Redis

Comment installer un cluster à six nœuds dans Redis

WBOY
WBOYavant
2023-06-03 09:19:281169parcourir

Introduction

redis cluster est une solution de cluster native, elle a actuellement fait de grands progrès en termes de haute disponibilité et de stabilité. D’après les statistiques et les observations, de plus en plus d’entreprises et de communautés adoptent l’architecture redis cluster, devenue de facto un standard. Sa principale caractéristique est qu'il est décentralisé et ne nécessite pas de proxy proxy. L’un des principaux objectifs de conception est d’atteindre une évolutivité linéaire. redis cluster是亲生的集群方案,目前,在高可用和稳定性方面,都有了很大的进步。据统计和观察,采用redis cluster架构的公司和社区越来越多,已经成为事实的标准。它的主要特点就是去中心化,无需proxy代理。其中一个主要设计目标就是达到线性可扩展性(linear scalability)。

仅仅靠redis cluster服务器本身,并不能完成官方承诺的功能。广义上的redis cluster应该既包含redis服务器,又包含客户端实现比如jedis等。它们是一个整体。

分布式存储无非就是处理分片和副本。redis cluster来说,核心概念就是槽(slot),了解了它,基本就了解了集群的管理方式。

优缺点

当了解这些特性以后,运维上其实是更简单了。我们先看下比较明显的优缺点。

优点

1、不再需要额外的Sentinel集群,为使用者提供了一致的方案,减少了学习成本。 

2、去中心架构,节点对等,集群可支持上千个节点。 

3、抽象出了slot概念,针对slot进行运维操作。 

4、副本功能能够实现自动故障转移,大部分情况下无需人工介入。

缺点

1、客户端要缓存部分数据,实现Cluster协议,相对复杂。 

2、数据是通过异步复制的,不能保证数据的强一致性。

3、资源隔离困难,经常流量不均衡,尤其是多个业务共用集群的时候。数据不知道在哪里,针对热点数据,也无法通过专项优化完成。 

4、从库是完全的冷备,无法分担读操作,真是太太浪费了。需要做额外工作。 

5、MultiOpPipeline支持有限,老代码要是进行架构升级,要小心了。 

6、数据迁移是基于key而不是基于slot的,过程较慢。

基本原理

从槽到key,定位过程明显就是一个双层的路由。

key的路由

redis cluster和常用的一致性hash没什么关系,它主要采用了哈希槽的概念。当需要在其中存取一个key时,redis客户端会首先对这个key采用crc16算法算出一个值,然后对这个值进行mod操作。

crc16(key)mod 16384

所以,每个key都会落在其中的一个hash槽上。16384 等同于 2^14(16k),redis节点发送心跳包时,需要把所有的槽信息放在这个心跳包里,所以要竭尽全力的优化,感兴趣的可以看下为什么默认的槽数量是 16384 。

服务端简单原理

上面谈到,redis cluster共定义了 16384 个槽,所有的集群操作都是围绕着这个槽数据进行编码。服务端使用一个简单的数组存储这些信息。

对于判断有无的操作,使用bitmap来存储是最节省空间的。redis cluster就是使用一个叫做slot的数组来保存当前节点是否持有了这个槽。

数组的长度为 16384/8=2048 Byte,那么就可以使用 0 或者 1 来标识本节点对某个槽是否拥有。

其实,只需要第一份数据ClusterState也能完成操作,保存另外一个维度的Slot数组,能够方便编码和存储。一个节点除了会将自己负责处理的槽记录在两个地方(clusterNode结构的slots和numslots),它还会将自己的slots数组通过消息发送给集群中的其他节点,以此来告诉其他节点自己目前拥有的槽。

当数据库中的 16384 个槽都有节点在处理时,集群处于上线状态(ok);相反地,如果数据库中有任何一个槽没有得到处理,那么集群处于下线状态(fail)。

当客户端向节点发送相关命令时,接收命令的节点会计算出命令要处理的key属于哪个槽,并检查这个槽是否指派给了自己。如果不是自己的,会指引客户端到正确的节点。

所以,客户端连接集群中的任意一台机器,都能够完成操作。

安装一个6节点集群

准备工作

假如我们要组装一个3分片的集群,每个分片有一个副本。那么总共需要的node实例就有 3*2=6 个。redis

Le serveur redis cluster lui-même ne peut pas remplir les fonctions officiellement promises. Au sens large, le redis cluster devrait inclure à la fois les serveurs redis et les implémentations client telles que jedis, etc. Ils forment un tout.

Le stockage distribué n'est rien d'autre que la gestion du partitionnement et des répliques. Pour le redis cluster, le concept de base est le slot. Si vous le comprenez, vous comprendrez essentiellement la méthode de gestion du cluster. 🎜🎜Avantages et inconvénients🎜🎜Après avoir compris ces fonctionnalités, le fonctionnement et la maintenance seront en réalité plus simples. Examinons d’abord les avantages et les inconvénients les plus évidents. 🎜

Avantages

🎜1. Aucun cluster Sentinel supplémentaire n'est nécessaire, offrant aux utilisateurs une solution cohérente et réduisant les coûts d'apprentissage. 🎜🎜2. Architecture décentralisée, les nœuds sont peer-to-peer et le cluster peut prendre en charge des milliers de nœuds. 🎜🎜3. La notion de slot est abstraite, et les opérations d'exploitation et de maintenance sont effectuées sur slot. 🎜🎜4. La fonction de réplique peut réaliser un basculement automatique, sans intervention manuelle dans la plupart des cas. 🎜

Inconvénients

🎜1. Le client doit mettre en cache certaines données et implémenter le protocole Cluster, ce qui est relativement compliqué. 🎜🎜2. Les données sont copiées de manière asynchrone et une forte cohérence des données ne peut pas être garantie. 🎜🎜3. L'isolation des ressources est difficile et le trafic est souvent déséquilibré, surtout lorsque plusieurs entreprises partagent un cluster. Nous ne savons pas où se trouvent les données, et les données chaudes ne peuvent pas être obtenues via une optimisation spéciale. 🎜🎜4. La base de données esclave est complètement en veille et ne peut pas partager les opérations de lecture. Des travaux supplémentaires sont nécessaires. 🎜🎜5. MultiOp et Pipeline ont un support limité. Si vous souhaitez mettre à niveau l'architecture de l'ancien code, soyez prudent. 🎜🎜6. La migration des données est basée sur la clé au lieu du slot, et le processus est lent. 🎜🎜Principe de base🎜🎜De la fente à la clé, le processus de positionnement est évidemment un routage à deux couches. 🎜

routage des clés

🎜redis cluster n'a rien à voir avec la cohérence hash couramment utilisée. Il utilise principalement le concept de slots de hachage. Lorsqu'il faut accéder à une clé, le client redis utilisera d'abord l'algorithme crc16 pour calculer la clé A valeur, puis effectuez une opération mod sur cette valeur. 🎜
for i in {0..5}
do
cp redis.conf  redis-700$i.conf
done
🎜Ainsi, chaque clé tombera sur l'un des emplacements hash. 16384 équivaut à 2^14 (16k). Lorsque le nœud redis envoie un paquet de battement de cœur, il doit mettre toutes les informations d'emplacement dans ce paquet de battement de cœur, nous devons donc faire de notre mieux pour l'optimiser. Si vous êtes intéressé, vous pouvez lire Pourquoi le nombre d'emplacements par défaut est 16384. 🎜

Principe simple côté serveur

🎜Comme mentionné ci-dessus, le redis cluster définit un total de 16384 emplacements, et toutes les opérations du cluster sont codées autour de ces données d'emplacement. Le serveur utilise un simple tableau pour stocker ces informations. 🎜🎜Pour l'opération consistant à déterminer s'il y en a, il est le plus économe en espace d'utiliser bitmap pour le stocker. Le redis cluster utilise un tableau appelé slot pour savoir si le nœud actuel détient cet emplacement. 🎜🎜La longueur du tableau est 16384/8=2048 Byte, vous pouvez alors utiliser 0 ou 1 pour identifier si ce nœud possède un certain emplacement. 🎜🎜En fait, seule la première donnée ClusterState est nécessaire pour terminer l'opération, et le tableau Slot d'une autre dimension est enregistré, ce qui peut faciliter l'encodage et le stockage. En plus d'enregistrer les slots qu'il est chargé de traiter à deux endroits (slots et numslots de la structure clusterNode), un nœud enverra également son propre tableau slots aux autres nœuds du cluster via des messages. indique aux autres nœuds les emplacements qu'ils possèdent actuellement. 🎜🎜Lorsque les 16 384 emplacements de la base de données sont traités par des nœuds, le cluster est dans l'état en ligne (ok) ; à l'inverse, si un emplacement de la base de données n'est pas traité, le cluster est dans l'état hors ligne (échec). 🎜🎜Lorsque le client envoie une commande associée à un nœud, le nœud recevant la commande calculera à quel emplacement appartient la clé à traiter par la commande et vérifiera si cet emplacement lui est attribué. Si ce n'est pas le vôtre, il dirigera le client vers le bon nœud. 🎜🎜Ainsi, le client peut terminer l'opération en se connectant à n'importe quelle machine du cluster. 🎜🎜Installation d'un cluster à 6 nœuds🎜

Préparation

🎜Supposons que nous souhaitions assembler un cluster à 3 fragments, avec une réplique pour chaque fragment. Ensuite, le nombre total d'instances de node requises est de 3*2=6. redis peut être démarré en spécifiant un fichier de configuration. Ce que nous faisons est de modifier le fichier de configuration. 🎜🎜Copiez 6 fichiers de configuration par défaut. 🎜
for i in {0..5}
do
cp redis.conf  redis-700$i.conf
done

修改其中的配置文件内容,拿redis-7000.conf来说,我们要启用它的cluster模式。

cluster-enabled yes
port 7000
cluster-config-file nodes-7000.conf

nodes-7000.conf会保存一些集群信息到当前节点,所以需要独立。

启动&关闭

同样的,我们使用脚本来启动它。

for i in {0..5}
do
nohup ./redis-server redis-700$i.conf &
done

为了演示,我们暴力把它关闭。

ps -ef| grep redis | awk '{print $2}' | xargs kill -9

组合集群

我们使用redis-cli进行集群的组合。redis将自动完成这个过程。这一系列的过程,是通过发送指令给每个节点进行组合的。

./redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1

几个高级原理

节点故障

集群中的每个节点都会定期地向集群中的其他节点发送ping消息,以此来检测对方是否在线,如果接收ping消息的节点没有在规定的时间内返回pong消息,那么发送ping消息的节点就会将接收ping消息的节点标记为疑似下线(PFAIL)。

如果在一个集群里面,半数以上节点都将某个主节点 x 报告为疑似下线,那么这个主节点x将被标记为已下线(FAIL),将x标记为FAIL的节点会向集群广播一条关于 x 的FAIL消息,所有收到这条FAIL消息的节点都会立即将 x 标记为FAIL

大家可以注意到这个过程,与 es 和 zk 的节点判断类似,都是半数以上才进行判断,所以主节点的数量一般都是奇数。由于没有最小组群配置,理论上会有脑裂(暂时并未遇到过)。

主从切换

当一个节点发现自己的主节点进入fail状态,将会从这个节点的从节点当中,选出一台,执行slaveof no one命令,变身为主节点。

新的节点完成自己的槽指派以后,会向集群广播一条pong消息,以便让其他节点立即知道自己的这些变化。它告诉别人:我已经是主节点了,我已经接管了有问题的节点,成为了它的替身。

redis内部对集群的这些管理,大量使用了已经定义好的这些指令。所以这些指令不仅仅供我们从命令行使用,redis自己内部也用。

数据同步

当一台从机连接到master之后,会发送一个sync指令。master在收到这个指令后,会在后台启动存盘进程。执行完毕后,master将整个数据库文件传输到slave,这样就完成了第一次全量同步。

接下来,master会把自己收到的变更指令,依次传送给slave,从而达到数据的最终同步。从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。

数据丢失

redis cluster中节点之间使用异步复制,并没有类似kafka这种ack的概念。节点之间通过gossip协议交换状态信息,用投票机制完成SlaveMaster的角色提升,完成这个过程注定了需要时间。在发生故障的过程中就容易存在窗口,导致丢失写入的数据。比如以下两种情况。

一、命令已经到到master,此时数据并没有同步到slavemaster会对客户端回复ok。如果这个时候主节点宕机,那么这条数据将会丢失。redis这样做会避免很多问题,但对一个对数据可靠性要求较高的系统,是不可忍受的。

二、由于路由表是在客户端存放的,存在一个时效问题。如果分区导致一个节点不可达,提升了某个从节点,但原来的主节点在这个时候又可以用了(并未完成failover)。如果客户端的路由表没有及时更新,那么写入错误的节点可能导致数据丢失。

所以redis cluster在通常情况下运行的很好,在极端情况下某些值丢失问题,目前无解。

复杂的运维

redis cluster的运维非常的繁杂,虽然已经进行了抽象,但这个过程依然不简单。有些指令,必须在详细了解它的实现原理之后,才能真正放心的去用。

扩容会用到的一些命令。在实际使用的过程中,可能需要多次频繁地输入这些命令,且输入的过程中还要监视它的状态,所以基本上是不可能人工跑这些命令的。

运维的入口有两个。一个是使用redis-cli连接任意一台,然后发送cluster打头的命令,这部分命令大多数是对槽进行操作。 在开始组合集群时,就是反复调用这些命令进行的具体逻辑执行。

另外一个入口是使用redis-cli命令,加上--cluster参数和指令。这种形式主要是用来管控集群节点信息 ,比如增删节点等。所以推荐使用这种方式。

redis cluster提供了非常复杂的命令,难于操作和记忆。推荐使用类似CacheCloud的工具进行管理。

下面是几个例子。

通过向节点 A 发送 CLUSTER MEET 命令,客户端可以让接收命令的节点 A 将另一个节点 B 添加到节点 A 当前所在的集群里面:

CLUSTER MEET  127.0.0.1 7006

通过cluster addslots命令,可以将一个或者多个槽指派给某个节点负责。

127.0.0.1:7000> CLUSTER ADDSLOTS 0 1 2 3 4 . . . 5000

设置从节点。

CLUSTER REPLICATE <node_id>

redis-cli —cluster

redis-trib.rb是官方提供的Redis Cluster的管理工具,但最新版本已经推荐使用redis-cli进行操作。

向集群中添加新节点

redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7007 --cluster-replicas 1

从集群中删除节点

redis-cli --cluster del-node 127.0.0.1:7006 54abb85ea9874af495057b6f95e0af5776b35a52

迁移槽到新的节点

redis-cli --cluster reshard 127.0.0.1:7006 --cluster-from 54abb85ea9874af495057b6f95e0af5776b35a52 --cluster-to 895e1d1f589dfdac34f8bdf149360fe9ca8a24eb  --cluster-slots 108

类似的命令还有很多。

create:创建集群 check:检查集群 info:查看集群信息 fix:修复集群 reshard:在线迁移slot rebalance:平衡集群节点slot数量 add-node:添加新节点 del-node:删除节点 set-timeout:设置节点的超时时间 call:在集群所有节点上执行命令 import:将外部redis数据导入集群

其他方案概览

主从模式

redis最早支持的,就是M-S模式,也就是一主多从。redis单机qps可达到 10w+,但是在某些高访问量场景下,依然不太够用。一般通过读写分离来增加slave,减少主机的压力。

既然是主从架构,就面临着同步问题,redis主从模式的同步分为全同步和部分同步。当刚创建一个从机的时候,不可避免的要进行一次全量同步。等全量同步结束之后,进入增量同步阶段。这个和redis cluster是没什么区别的。

这种模式还是比较稳定的,但要额外做一些工作。用户需要自行开发主从切换的功能,也就是使用哨兵去探测每个实例的健康状况,然后通过指令进行集群状态的改变。

当集群规模增大,主从模式会很快遇到瓶颈。所以一般会采用客户端hash的方法进行扩展,包括类似于memcached的一致性哈希。

客户端hash的路由可能会很复杂,通常会通过发布jar包或者配置的方式维护这些meta信息,这也给线上环境增加了很多不确定性。

不过,通过加入类似ZK主动通知的功能,将配置维护在云端,可以显著降低风险。笔者曾经维护过的几千个redis节点,就是用这种方式进行管理的。

代理模式

代码模式在redis cluster出现之前,非常流行,比如codis。代理层通过把自己模拟成一个redis,接收来自客户端的请求,然后按照自定义的路由逻辑进行数据分片以及迁移,而业务方不需要改动任何代码。除了能够平滑的进行扩容,一些主从切换、FailOver的功能也在代理层完成,客户端甚至可以没有任何感知。这类程序又称为分布式中间件。

一个典型的实现如下图,背后的redis集群甚至可以是混合的。

但这种方式的缺点也是显而易见的。首先,它引入了一个新的代理层,在结构上、运维上都显复杂。需要进行大量的编码,比如failover、读写分离、数据迁移等。另外,proxy层的加入,对性能也有相应的损耗。

多个proxy一般使用lvs等前置进行负载均衡的设计,如果proxy层的机器很少而后端redis的流量很高,那么网卡会成为主要的瓶颈。

Nginx也可以作为redis的代理层,比较专业的说法叫做Smart Proxy。这种方式较为偏门,如果你对nginx比较熟悉,不失为一种优雅的做法。

使用限制和坑

redis的速度特别的快。一般越快的东西,出问题的时候造成的后果越大。

Il n'y a pas longtemps, j'ai écrit une spécification pour redis : "Spécification Redis, c'est peut-être la plus pertinente". Les spécifications sont les mêmes que l'architecture. Celle qui convient le mieux à l'environnement de votre entreprise, mais elle fournira quelques idées de base. redis的规范:《Redis规范,这可能是最中肯的了》。规范和架构一样,适合自己公司环境的,才是最好的,但会提供一些起码的思路。

严格禁止的东西,一般都是前人踩坑的地方。除了这篇规范的内容,对于redis-cluster,补充以下几点。

1、redis cluster号称能够支持1k个节点,但你最好不要这么做。当节点数量增加到10,就能够感受到集群的一些抖动。这么大的集群证明你的业务已经很牛x了,考虑一下客户端分片吧。

2、一定要避免产生热点,如果流量全部打到了某个节点,后果一般很严重。

3、大key不要放redis,它会产生大量的慢查询,影响正常的查询。

4、如果你不是作为存储,缓存一定要设置过期时间。占着茅坑不拉屎的感觉是非常讨厌的。

5、大流量,不要开aof,开rdb即可。

6、redis cluster的操作,少用pipeline,少用multi-key

Les choses strictement interdites sont généralement les endroits où les prédécesseurs ont marché dessus. En plus du contenu de cette spécification, pour redis-cluster, les points suivants sont ajoutés. 🎜🎜1. Le redis cluster prétend être capable de prendre en charge 1 000 nœuds, mais vous feriez mieux de ne pas le faire. Lorsque le nombre de nœuds augmente jusqu'à 10, vous pouvez ressentir une certaine instabilité dans le cluster. Un cluster d’une telle envergure prouve que votre entreprise est déjà très bonne. Envisagez le partage client. 🎜🎜2. Assurez-vous d'éviter les points chauds. Si tout le trafic atteint un certain nœud, les conséquences seront généralement graves. 🎜🎜3. Ne mettez pas redis dans une grande clé. Cela générera un grand nombre de requêtes lentes et affectera les requêtes normales. 🎜🎜4. Si vous ne l'utilisez pas comme stockage, le cache doit définir un délai d'expiration. La sensation d’occuper les toilettes et de ne pas chier est très énervante. 🎜🎜5. Pour un trafic important, n'activez pas aof, activez simplement rdb. 🎜🎜6. Lorsque vous utilisez le redis cluster, utilisez moins de pipeline et moins de multi-key. Ils produiront un grand nombre de résultats imprévisibles. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer