
redis cluster配置好,并运行一段时间后,我们想添加节点,或者删除节点,该怎么办呢。
一,redis cluster命令行
查看复制打印
//集群(cluster)
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
//节点(node)
CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
//槽(slot)
CLUSTER ADDSLOTS <slot> [slot ] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS <slot> [slot ] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
//键 (key)
CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。
CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。
这些命令是集群所独有的。执行上述命令要先登录
查看复制打印
[root@manage redis]# redis-cli -c -p 6382 -h 19216810220 //登录
19216810220:6382> cluster info //查看集群情况
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:8
cluster_my_epoch:4
cluster_stats_messages_sent:82753
cluster_stats_messages_received:82754
二,添加节点
1,新配置二个测试节点
查看复制打印
# cd /etc/redis
//新增配置
# cp redis-6379conf redis-6378conf && sed -i "s/6379/6378/g" redis-6378conf
# cp redis-6382conf redis-6385conf && sed -i "s/6382/6385/g" redis-6385conf
//启动
# redis-server /etc/redis/redis-6385conf > /var/log/redis/redis-6385log 2>&1 &
# redis-server /etc/redis/redis-6378conf > /var/log/redis/redis-6378log 2>&1 &
2,添加主节点
# redis-tribrb add-node 19216810219:6378 19216810219:6379
注释:
19216810219:6378是新增的节点
19216810219:6379集群任一个旧节点
3,添加从节点
# redis-tribrb add-node --slave --master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2 19216810220:6385 19216810219:6379
注释:
--slave,表示添加的是从节点
--master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2,主节点的node id,在这里是前面新添加的6378的node id
19216810220:6385,新节点
19216810219:6379集群任一个旧节点
4,重新分配slot
查看复制打印
# redis-tribrb reshard 19216810219:6378 //下面是主要过程
How many slots do you want to move (from 1 to 16384) 1000 //设置slot数1000
What is the receiving node ID 03ccad2ba5dd1e062464bc7590400441fafb63f2 //新节点node id
Please enter all the source node IDs
Type 'all' to use all the nodes as source nodes for the hash slots
Type 'done' once you entered all the source nodes IDs
Source node #1:all //表示全部节点重新洗牌
Do you want to proceed with the proposed reshard plan (yes/no) yes //确认重新分
新增加的主节点,是没有slots的,
public static void writeRedis(String inpath, int[] keyIndex) throws Exception {
InputStream in = new URL(inpath)openStream();// 输入流 ]
LineIterator br = orgapachecommonsioIOUtilslineIterator(in, "utf8");// 指定输入流与字符编码
JedisCluster cluster = RedisUtilsgetClusterConn();
String[] line = null;
while (brhasNext()) {
String s = brnext();
line = RedisUtilssplit(s);
String key = "";
for (int i = 0; i < keyIndexlength; i++) {
key += line[keyIndex[i]];// TODO:如果有必要,添加分隔符
}
clustersetnx(key, s);
}
RedisUtilsclusterClose(cluster);
搭建集群工作需要以下三个步骤:
1)准备节点。
2)节点握手。
3)分配槽。
Redis集群一般由多个节点组成,节点数量至少为6个才能保证组成完整高可用的集群。每个节点需要开启配置cluster-enabled yes,让Redis运行在集群模式下。建议为集群内所有节点统一目录,一般划分三个目录:conf、data、log,分别存放配置、数据和日志相关文件。把6个节点配置统一放在conf目录下,集群相关配置如下:
其他配置和单机模式一致即可,配置文件命名规则redis-{port}conf,准备好配置后启动所有节点。
Cluster集群启动过程如下图:
每个节点目前只能识别出自己的节点信息,可以执行cluster nodes命令获取集群节点状
态。
节点握手是指一批运行在集群模式下的节点通过Gossip协议彼此通信,达到感知对方的过程。节点握手是集群彼此通信的第一步,由客户端发起命令:cluster meet{ip}{port}
cluster meet命令是一个异步命令,执行之后立刻返回。内部发起与目标节点进行握手通信,握手通信过程:
1)节点6379本地创建6380节点信息对象,并发送meet消息。
2)节点6380接受到meet消息后,保存6379节点信息并回复pong消息。
3)之后节点6379和6380彼此定期通过ping/pong消息进行正常的节点通
信。
分别执行meet命令让其他节点加入到集群中,
最后执行cluster nodes命令确认6个节点都彼此感知并组成集群。
节点建立握手之后集群还不能正常工作,这时集群处于下线状态,所有的数据读写都被禁止,通过cluster info命令可以获取集群当前状态。
Redis集群把所有的数据映射到16384个槽中。每个key会映射为一个固定的槽,只有当节点分配了槽,才能响应和这些槽关联的键命令。通过cluster addslots命令为节点分配槽。这里利用bash特性批量设置槽(slots),命令如下:
执行cluster info查看集群状态,如下所示:
当前集群状态是OK,集群进入在线状态。所有的槽都已经分配给节点,执行cluster nodes命令可以看到节点和槽的分配关系:
集群模式下,Reids节点角色分为主节点和从节点。首次启动的节点和被分配槽的节点都是主节点,从节点负责复制主节点槽信息和相关的数据。使用cluster replicate{nodeId}命令让一个节点成为从节点。其中命令执行必须在对应的从节点上执行,nodeId是要复制主节点的节点ID,命令如下:
Redis集群模式下的主从复制使用了之前介绍的Redis复制流程,依然支持全量和部分复制。复制(replication)完成后,整个集群的结构如图:
集群搭建需要很多步骤当集群节点众多时,必然会加大搭建集群的复杂度和运维成本。因此Redis官方提供了redis-tribrb工具方便我们快速搭建集群。
redis-tribrb是采用Ruby实现的Redis集群管理工具。内部通过Cluster相关命令帮我们简化集群创建、检查、槽迁移和均衡等常见运维 *** 作,使用之前需要安装Ruby依赖环境。
1、安装Ruby:
2、安装rubygem redis依赖:
3、安装redis-tribrb:
4、安装完Ruby环境后,执行redis-tribrb命令确认环境是否正确,输出如
下:
首先我们跟之前内容一样准备好节点配置并启动:
启动好6个节点之后,使用redis-tribrb create命令完成节点握手和槽分配过程,命令如下:
--replicas参数指定集群中每个主节点配备几个从节点,这里设置为1。
如果部署节点使用不同的IP地址,redis-tribrb会尽可能保证主从节点不分配在同一机器下,因此会重新排序节点列表顺序。节点列表顺序用于确定主从角色,先主节点之后是从节点。创建过程中首先会给出主从节点角色分配的计划,当我们同意这份计划之后输入yes,redis-tribrb开始执行节点握手和槽分配 *** 作。
集群完整性指所有的槽都分配到存活的主节点上,只要16384个槽中有一个没有分配给节点则表示集群不完整。可以使用redis-tribrb check命令检测之前创建的集群是否成功,check命令只需要给出集群中任意一个节点地址就可以完成整个集群的检查工作,命令如下:
Spring对Redis的支持是通过Spring Data Redis实现的,JedisConnectionFactory为我们提供了Redis的一种Java客户端Jedis。本文主要为大家介绍使用工厂类获取Jedis的两种方式,以及使用过程中存在的问题,希望能为大家提供一些思路。
工具/材料IntelliJ IDEA
01首先我们需要编辑Spring的配置文件applicationproperties,添加Redis的相关配置,这些配置在代码中需要注入,用来生成JedisConnectionFactory的Bean。
02接下来我们写一个配置类,该配置类上需要添加@Configuration注解,我们在这个类中通过@Value注解注入applicationproperties配置文件中的部分需要的属性,其中{}用于接收属性值,在属性名冒号后面的值是默认值,若读取不到该属性则使用默认值。我们在该类中创建JedisConnectionFactory的Bean,在这个Bean中设置读取到的属性值。
03接下来我们创建一个RedisServer的类,主要用于获取Redis以及实现部分Redis *** 作的方法。在该类中我们可以使用@Autowired注解注入JedisConnectionFactory的Bean。下图中获取Redis客户端Jedis的方法是我们推荐的方法,使用该方法我们既获取到了Jedis实例又使用的连接池,将Jedis实例交由连接池管理,不用太担心并发 *** 作导致的Redis不可用的情况。最后再附上Jedis *** 作存储和获取数据的方法。
04另外,我们还有再介绍一种并不推荐的写法,如下图所示。这种方法每次都创建一个新的Redis连接并且没有关闭连接,在大量并发 *** 作时会带来性能上的开销,由于对连接数没有限制,可能会耗尽Redis的连接,导致Redis连接报错。
05配置完成后我们来测试一下Jedis是否能正常使用,创建一个RedisController类,在该类中注入JedisServer,使用JedisServer提供的存储和读取方法,然后启动服务。
06服务启动后我们在postman中进行测试,首先调用setRedis请求将数据存入Redis中,然后再调用getRedis请求获取数据,如下图所示。
07JedisConnectionFactory在Spring Data Redis 20后就不再推荐上述这种配置方式了,当我们的spring-boot-starter-parent版本设置为2x时,我们可以看到代码中的设置已经被废弃了。
08Spring Data Redis 20推荐使用Standalone、Sentinel、RedisCluster这三种模式的环境配置类,以便于更加灵活的适配更多的业务场景,我们一般自己测试Redis通常使用的都是单机版的,那么以单机版为例,JedisConnectionFactory的配置应写为如下的方式。
特别提示本文只是介绍了一种Redis客户端的使用方式,还是推荐大家使用spring-boot集成Redis做开发,因为spring-boot开箱即用的特性可以大大减少开发工作量。
1Redis集群是一个可以在多个Redis节点之间进行数据共享的设施(installation)
2Redis集群不支持那些需要同时处理多个键的Redis命令,因为执行这些命令需要在多个Redis节点之间移动数据,并且在高负载的情况下,这些命令将降低Redis集群的性能,并导致不可预测的行为。(使用ack协议)
3Redis集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。
4Redis集群有将数据自动切分(split)到多个节点的能力。
#高性能:
1在多分片节点中,将16384个槽位,均匀分布到多个分片节点中
2存数据时,将key做crc16(key),然后和16384进行取模,得出槽位值(0-16384之间)
3根据计算得出的槽位值,找到相对应的分片节点的主节点,存储到相应槽位上
4如果客户端当时连接的节点不是将来要存储的分片节点,分片集群会将客户端连接切换至真正存储节点进行数据存储
5客户端与redis节点直连,不需要中间proxy层客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
6Redis Cluster解决了redis资源利用率的问题
#高可用
7在搭建集群时,会为每一个分片的主节点,对应一个从节点,实现slaveof功能,同时当主节点down,实现类似于sentinel的自动failover的功能。
1在集群中,会把所有节点分为16384个槽位
2槽位的序号是 0 - 16383,序号不重要,数量才重要
3每一个槽位分配到数据的概率是一样
1在集群里面,节点会对其他节点进行下线检测。
2当一个主节点下线时,集群里面的其他主节点负责对下线主节点进行故障移。
3换句话说,集群的节点集成了下线检测和故障转移等类似 Sentinel 的功能。
一服务器设置准备
1 将6379端口在防火墙看开启
[root@redis1 ~]#vi /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
注:必须加在 REJECT 前面。
2修改Selinux参数
[root@redis1 ~]#vi /etc/selinux/config
SELINUX=disabled
注:分别在其它几个节点上同样配置防火墙和 SELINUX。
二安装Redis
1安装系统组件
安装gcc、tcl
yum install –y gcc-c++
yum install –y tcl
2安装redis
21解压 Redis 到/usr/local目录下
[root@redis1 ~]# tar -zxvf /root/software/redis-326targz -C /usr/local/
22在解压后的目录中进行 make 和 make test
[root@redis1 ~]# cd /usr/local/redis-326
[root@redis1 redis-326]# make
[root@redis1 redis-326]# make test
注:要检查 make 和 make test 的结果是否都正确,如果报错,针对性检查并安装系统缺少的组件。
23 复制 redis-server 和 redis-cli 到/usr/local/bin 目录下:
[root@redis1 redis-326]# cd src
[root@redis1 src]# cp redis-server /usr/local/bin/
[root@redis1 src]# cp redis-cli /usr/local/bin/
24验证 Redis 安装是否成功:
[root@redis1 ~]# redis-server
[root@redis1 ~]# redis-cli
注:安装其它 5 台服务器
三配置集群模式
1配置 redisconf
11 配置 redisconf
[root@redis1 ~]# mkdir /etc/redis
[root@redis1 ~]# cd /etc/redis
[root@redis ~]# vi redisconf
port 6379
daemonize yes
cluster-enabled yes
cluster-config-file /etc/redis/nodesconf
cluster-node-timeout 5000
appendonly yes
requirepass Ab123456
注 1:cluster-node-timeout 是集群中各节点相互通讯时,允许“失联”的最大毫秒数,本演示
中配置的为 5 秒,如果超过 5 秒某个节点没有向其它节点汇报成功,认为该节点挂了。
注 2:requirepass 是 Redis 访问密码,为了安全起见,该参数建议必须配置,从但客户端
Jedis 版本必须使用 28x 以上的版本,否则需要通过扩展 JedisCluster 来实现对密码访问的
支持。此外几个 Redis 节点的密码应该设置为相同的。
注 3:分别在其它几个节点上创建与上面相同的 redisconf 文件,内容也相同。
注 4:重启/重建 Redis 集群时,必须删除去/etc/redis/nodesconf 文件。
12以次启动所有节点
[root@redis1 ~]# redis-server /etc/redis/redisconf
[root@redis2 ~]# redis-server /etc/redis/redisconf
[root@redis3 ~]# redis-server /etc/redis/redisconf
[root@redis4 ~]# redis-server /etc/redis/redisconf
[root@redis5 ~]# redis-server /etc/redis/redisconf
[root@redis6 ~]# redis-server /etc/redis/redisconf
2安装 Redis 集群所需的 Ruby 工具
21安装 Ruby 工具:
Redis 集群需要借助其它工具将相关节点加入到 Cluster 中,而这个工具是由 Redis 提供
一个名为 redis-tribrb 的 ruby 脚本,否则接下来创建 cluster 会失败。
[root@redis1 ~]# cd /usr/local/redis-326/src
[root@redis1 src]# yum install –y ruby
[root@redis1 src]# yum install -y rubygems
[root@redis1 src]# gem install redis --version 300
[root@redis1 src]# gem list
22 设置 Ruby 连接 Redis 的密码:
[root@redis1 ~]# vi /usr/lib/ruby/gems/18/gems/redis-300/lib/redis/clientrb
:password => "Ab123456"
注:分别在其它几个节点上用同样的方式安装好 Ruby 工具
3 利用redis-tribrb 创建 Redis集群
3 1 在 src 目录下运行以下脚本:
[root@redis1 ~]# cd /usr/local/redis-326/src
[root@redis1 src]# /redis-tribrb create --replicas 1 1050130101:6379 1050130102:6379
1050130103:6379 1050130104:6379 1050130105:6379 1050130106:6379
注 1:只需在其中某个个节点执行以上脚本(本例在第一个节点执行)。
注 2:利用 redis-trib 创建 Cluster,只需要 *** 作一次即可,假设系统关机、重启,把所有的
节点全部关闭之后,下次重启后,即自动进入 Cluster 模式,不用现次执行 redis-tribrb cteate
命令。
32查看 Cluster 进程:
[root@redis1 ~]# ps -ef|grep redis
[root@redis2 ~]# ps -ef|grep redis
[root@redis3 ~]# ps -ef|grep redis
[root@redis4 ~]# ps -ef|grep redis
[root@redis5 ~]# ps -ef|grep redis
[root@redis6 ~]# ps -ef|grep redis
33 查看节点属性(Master/Slave)
[root@redis1 ~]# cd /usr/local/redis-326/src
[root@redis1 src]# /redis-tribrb check 1050130101:6379
[root@redis1 src]# /redis-tribrb check 1050130102:6379
[root@redis1 src]# /redis-tribrb check 1050130103:6379
[root@redis1 src]# /redis-tribrb check 1050130104:6379
[root@redis1 src]# /redis-tribrb check 1050130105:6379
[root@redis1 src]# /redis-tribrb check 1050130106:6379
34查看节点/集群信息
redis-cli 客户端登录到任一个节点,查看:
4Jedis 测试 Redis 集群
第一:非集群状态下
非集群状态下用Jedis获取Redis连接,得到Jedis对象即可,一共有两种:
1利用Jedis构造器,仅限用于测试,在实际项目中肯定是用JedisPool。
Jedis(String host);
Jedis(String host , int port);
2利用JedisPool
主要是利用Jedis jedis=jedisPoolgetResource();
JedisPool有N多个构造器,常用的构造器参数有GenericObjectPoolConfig poolConfig,String host,int port,int timeout,String password,创建GenericObjectPoolConfig对象时我们一般用其子类JedisPoolConfig (redisclientsjedisJedisPoolConfig),timeout是连接redis服务器的超时时间,以毫秒为单位,一般设置为0,如果不设为0,则不可设置太小,如果设成1、2,那么可能因为网络原因在1毫秒、2毫秒之内没有连上服务器而报错。见下例:
[java] view plain copy
public static void main(String[] args) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
// 最大连接数
poolConfigsetMaxTotal(2);
// 最大空闲数
poolConfigsetMaxIdle(2);
// 最大允许等待时间,如果超过这个时间还未获取到连接,则会报JedisException异常:
// Could not get a resource from the pool
poolConfigsetMaxWaitMillis(1000);
JedisPool pool = new JedisPool(poolConfig, "19216883128", 6379, 0, "123");
Jedis jedis = null;
try {
for (int i = 0; i < 5; i++) {
jedis = poolgetResource();
jedisset("foo" + i, "bar" + i);
Systemoutprintln("第" + (i + 1) + "个连接, 得到的值为" + jedisget("foo" + i));
// 用完一定要释放连接
jedisclose();
}
} finally {
poolclose();
}
}
如上,创建出一个JedisPool对象,然后调用其getResource()方法获取redis连接即可,之后就可以调用Jedis API *** 作redis了。jedis连接用完要释放即close,如果不close,则产生的连接会越来越多,当达到了最大连接数,再想获得连接,就会等待,当超过了最大等待时间后就会报异常。
第二:集群状态下
集群状态下用Jedis获取redis连接,是得到JedisCluster对象,之后对redis进行 *** 作都是用此对象的方法进行的:
[java] view plain copy
public static void main(String[] args) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
// 最大连接数
poolConfigsetMaxTotal(1);
// 最大空闲数
poolConfigsetMaxIdle(1);
// 最大允许等待时间,如果超过这个时间还未获取到连接,则会报JedisException异常:
// Could not get a resource from the pool
poolConfigsetMaxWaitMillis(1000);
Set<HostAndPort> nodes = new LinkedHashSet<HostAndPort>();
nodesadd(new HostAndPort("19216883128", 6379));
nodesadd(new HostAndPort("19216883128", 6380));
nodesadd(new HostAndPort("19216883128", 6381));
nodesadd(new HostAndPort("19216883128", 6382));
nodesadd(new HostAndPort("19216883128", 6383));
nodesadd(new HostAndPort("19216883128", 6384));
JedisCluster cluster = new JedisCluster(nodes, poolConfig);
String name = clusterget("name");
Systemoutprintln(name);
clusterset("age", "18");
Systemoutprintln(clusterget("age"));
try {
clusterclose();
} catch (IOException e) {
eprintStackTrace();
}
}
用集群时,好像没有办法设置集群的参数,比如最大连接数,虽然在创建JedisCluster 对象时传了JedisPoolConfig对象进去,但是JedisPoolConfig对象中的设置是不生效的。
1、redis的cluster模式下,需要客户端自己去手动获取缓存路由表,redis不会向客户端主动发送或者更新;
2、客户端的获取或者说更新路由表,就是通过客户端与每个node(包括master和slave)建立TCP连接以及后续的命令来实现的:先查看能否建立连接,如果成功建立链接,再发送command来确定其他信息;
以上就是关于redis cluster命令cluster nodes怎么用全部的内容,包括:redis cluster命令cluster nodes怎么用、如何用java实现基于JedisCluster对象的连接池、Redis Cluster集群的搭建等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)