1、先参考《CentOS下安装rvm、ruby》将ruby安装起来。
2、安装ruby redis工具
gem install redis
3、如果出现以下错误,那么确认一下《CentOS下安装rvm、ruby》的第5点是否正常配置
ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError) Errno::ECONNRESET: Connection reset by peer - SSL_connect (https://api.rubygems.org/quick/Marshal.4.8/redis-3.2.1.gemspec.rz)
4、 创建集群节点。
4.1:如果集群中不需要主从,只需要主节点的话,那么只需要3个节点即可;
4.2:如果集群中需要主从,那么节点数就需要为6的倍数,通过redis-trib.rb创建集群时,会自动帮助我们将主从给配置上来;
5、创建节点目录和节点的redis.conf
mkdir -p /usr/local/redis-cluster/nodes/9001
redis.conf最小配置,注意nodes.conf由redis自动生成,不要以为要自己手动创建:
daemonize yes port 9001 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
就这样在每台机器创建至少3节点。
6、redis cluster 运维操作
6.1、初始化并构建集群
(1)启动集群相关节点(必须是空节点,节点目录下只有redis.conf文件),指定配置文件和输出日志
cd /usr/local/redis-cluster/nodes/9001 && /usr/local/redis-cluster/redis-server redis.conf 1>log.log 2>err.log & cd /usr/local/redis-cluster/nodes/9002 && /usr/local/redis-cluster/redis-server redis.conf 1>log.log 2>err.log & cd /usr/local/redis-cluster/nodes/9003 && /usr/local/redis-cluster/redis-server redis.conf 1>log.log 2>err.log & cd /usr/local/redis-cluster/nodes/9004 && /usr/local/redis-cluster/redis-server redis.conf 1>log.log 2>err.log & cd /usr/local/redis-cluster/nodes/9005 && /usr/local/redis-cluster/redis-server redis.conf 1>log.log 2>err.log &
必须进入到节点的目录,因为redis-server会生成节点数据文件。
(2):使用自带的ruby工具(redis-trib.rb)构建集群
#redis-trib.rb的create子命令构建
#--replicas 则指定了为Redis Cluster中的每个Master节点配备几个Slave节点
#节点角色由顺序决定,先master之后是slave(为方便辨认,slave的端口比master大1000)
/usr/local/redis-cluster/redis-trib.rb create --replicas 1 \ 192.168.0.178:9002 192.168.0.178:9003 192.168.0.178:9004 192.168.0.178:9005 \ 192.168.0.179:9002 192.168.0.179:9003 192.168.0.179:9004 192.168.0.179:9005 \ 192.168.1.206:9002 192.168.1.206:9003 192.168.1.206:9004 192.168.1.206:9005
(3):检查集群状态
#redis-trib.rb的check子命令构建
#ip:port可以是集群的任意节点
redis-trib.rb check 10.10.34.14:6380
最后输出如下信息,没有任何警告或错误,表示集群启动成功并处于ok状态
[OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
2):添加新master节点
(1)添加一个master节点:创建一个空节点(empty node),然后将某些slot移动到这个空节点上,这个过程目前需要人工干预
a):根据端口生成配置文件(ps:establish_config.sh是我自己写的输出配置脚本)
sh establish_config.sh 6386 > conf/redis-6386.conf
b):启动节点
redis-server /opt/redis/conf/redis-6386.conf > /opt/redis/logs/redis-6386.log 2>&1 &
c):加入空节点到集群
add-node 将一个节点添加到集群里面, 第一个是新节点ip:port, 第二个是任意一个已存在节点ip:port
redis-trib.rb add-node 10.10.34.14:6386 10.10.34.14:6381
node:新节点没有包含任何数据, 因为它没有包含任何slot。新加入的加点是一个主节点, 当集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中
d):为新节点分配slot
redis-trib.rb reshard 10.10.34.14:6386
#根据提示选择要迁移的slot数量(ps:这里选择500)
How many slots do you want to move (from 1 to 16384)? 500
#选择要接受这些slot的node-id
What is the receiving node ID? f51e26b5d5ff74f85341f06f28f125b7254e61bf
#选择slot来源:
#all表示从所有的master重新分配,
#或者数据要提取slot的master节点id,最后用done结束
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
import java.io.InputStream; import java.text.MessageFormat; import java.util.Properties; import org.apache.commons.lang3.StringUtils; public final class ProfileAndResourcesUtils { private ProfileAndResourcesUtils() { } /** * <p> * 读取系统参数(-D)profiles.activation或spring.profiles.active的值。<br /> * <b>值:</b>develop、test、production * </p> * * @return 返回以下三个目录值其一 * <ol> * <li>"" * <li>"/test" * <li>"/production" * <ol> */ public static String getSystemProfilePath() { String profile = ""; // jvm参数中获取profile profile = System.getProperty("profiles.activation"); if (StringUtils.isBlank(profile)) { profile = System.getProperty("spring.profiles.active"); if (StringUtils.isBlank(profile)) { profile = ""; } } if (StringUtils.isNotBlank(profile) && !profile.equalsIgnoreCase("develop")) { profile = "/" + profile; } else { profile = ""; } return profile; } /** * 读取属性文件 * * @param propFilepathPattern "/config{0}/jdbc.properties" * @param profilePath 参考:{@link ProfileAndResourcesUtils#getSystemProfilePath()} * @return 返回以下三个目录值其一 * <ol> * <li>"/config/jdbc.properties" * <li>"/config/test/jdbc.properties" * <li>"/config/production/jdbc.properties" * <ol> */ public static String getPropFilePath(String propFilepathPattern, String profilePath) { return MessageFormat.format(propFilepathPattern, profilePath); } /** * 读取 * * @param propFilepathPattern "/config{0}/jdbc.properties" * @param profilePath 参考:{@link ProfileAndResourcesUtils#getSystemProfilePath()} * @return 返回以下三个目录值其一 * <ol> * <li>"/config/jdbc.properties" * <li>"/config/test/jdbc.properties" * <li>"/config/production/jdbc.properties" * <ol> * @throws Exception 异常 */ public static void loadPropFile(Properties p, String propFilePath) throws Exception { InputStream in = ClassLoader.class.getResourceAsStream(propFilePath); try { if (in != null) { p.load(in); } } finally { if(in!=null){ in.close(); } } } }
import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; public class ResourceUtil { private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); /** * * 从jar、项目目录中读取资源文件 * <p> * 使用说明:<br> * 1:*.txt:将返回类路径下的所有.txt文件<br> * 2:conf/*.txt:将返回类路径与Jar文件conf下的所有.txt文件<br> * 3:asm.txt:将返回类路径与Jar文件下的asm.txt文件<br> * <p> * * @param locationPattern 模式匹配 * @return 返回匹配到的文件的Resource数组 */ public static Resource[] loadResources(String locationPattern) { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] resources; try { resources = resolver.getResources("classpath*:" + locationPattern); return resources; } catch (IOException e) { throw new RuntimeException(e); } } /** * * 从jar、项目目录中读取资源文件,至返回一个 * <p> * 使用说明:<br> * 1:*.txt:将返回类路径下的所有.txt文件<br> * 2:conf/*.txt:将返回类路径与Jar文件conf下的所有.txt文件<br> * 3:asm.txt:将返回类路径与Jar文件下的asm.txt文件<br> * <p> * * @param locationPattern 模式匹配 * @return 返回匹配到的文件的Resource */ public static Resource loadResourcesOne(String locationPattern) { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] resources; try { resources = resolver.getResources("classpath*:" + locationPattern); if (resources != null && resources.length > 0) { return resources[0]; } } catch (IOException e) { throw new RuntimeException(e); } return null; } /** * * 从jar、项目目录中读取资源文件 * <p> * 使用说明:<br> * 1:*.txt:将返回类路径下的所有.txt文件<br> * 2:conf/*.txt:将返回类路径与Jar文件conf下的所有.txt文件<br> * 3:asm.txt:将返回类路径与Jar文件下的asm.txt文件<br> * <p> * * @param locationPattern 模式匹配 * @return 返回匹配到的文件的InputStream集合 */ public static List<InputStream> loadResourcesAsInputStream(String locationPattern) { List<InputStream> xmlInputStreamList = new ArrayList<InputStream>(); Resource[] resources = loadResources(locationPattern); for (Resource resource : resources) { try { xmlInputStreamList.add(resource.getInputStream()); } catch (IOException e) { throw new RuntimeException(e); } } return xmlInputStreamList; } /** * * 从jar、项目目录中读取资源文件,只返回一个 * <p> * 使用说明:<br> * 1:*.txt:将返回类路径下的所有.txt文件<br> * 2:conf/*.txt:将返回类路径与Jar文件conf下的所有.txt文件<br> * 3:asm.txt:将返回类路径与Jar文件下的asm.txt文件<br> * <p> * * @param locationPattern 模式匹配 * @return 返回匹配到的文件的InputStream */ public static InputStream loadResourcesOneAsInputStream(String locationPattern) { Resource resource = loadResourcesOne(locationPattern); if (resource != null) { try { return resource.getInputStream(); } catch (IOException e) { LOGGER.error(e.getMessage(), e); throw new RuntimeException(e); } } return null; } /** * * 读取资源 * <p> * 使用说明:<br> * 1:file:C:/test.dat<br> * 2:classpath:test.dat<br> * 3:WEB-INF/test.dat * <p> * * @param location 路径 * @return 返回匹配到的文件的resource */ public static Resource getResource(String location) { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource resource; resource = resolver.getResource(location); return resource; } public static void main(String[] args) { Resource[] resources = ResourceUtil.loadResources("conf/lua/*.lua"); for (Resource r : resources) { System.out.println(r.getFilename()); } } }
public final class RedisClusterClient { private static Logger logger = LoggerFactory.getLogger(RedisClusterClient.class); private static JedisCluster jc; static { String redisClusterPropFile = "/config{0}/redis-cluster.properties"; //只给集群里一个实例就可以 try { Properties p = new Properties(); redisClusterPropFile = ProfileAndResourcesUtils.getPropFilePath(redisClusterPropFile, ProfileAndResourcesUtils.getSystemProfilePath()); List<InputStream> ins = ResourceUtil.loadResourcesAsInputStream(redisClusterPropFile); for(InputStream in : ins){ p.load(in); in.close(); } Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>(); String hostsStr = p.getProperty("redis.cluster.hosts"); if (StringUtils.isBlank(hostsStr)) { throw new IllegalStateException("Cant not find property value with the name is \"redis.cluster.hosts\"!"); } String[] hosts = hostsStr.split(","); for (String host : hosts) { String[] hostPort = host.split(":"); if (hostPort != null && hostPort.length == 2 && StringUtils.isNotBlank(hostPort[0]) && StringUtils.isNotBlank(hostPort[1])) { jedisClusterNodes.add(new HostAndPort(hostPort[0], Integer.parseInt(hostPort[1]))); } } jc = new JedisCluster(jedisClusterNodes); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { redisClusterPropFile = null; } } private RedisClusterClient() { } public static JedisCluster getJedisCluster(){ return jc; } public static void main(String[] args) { JedisCluster jc = RedisClusterClient.getJedisCluster(); System.out.println(jc.set("roo", "foo")); } }
ClusterServersConfig redisServer = resConfig.useClusterServers(); String [] hostPortsPieces = hostPorts.split(","); List<String> validHostPorts = new ArrayList<String>(); for(String hostPort:hostPortsPieces){ if(StringUtils.isNotBlank(hostPort)){ validHostPorts.add(hostPort); } } redisServer.addNodeAddress(validHostPorts.toArray(new String[0])); if (password != null && !"".equals(password)) { redisServer.setPassword(password); } Redisson redisson = Redisson.create(resConfig);
相关推荐
"Hadoop集群安装笔记" Hadoop集群安装笔记是一篇详细的安装指南,旨在帮助新手快速搭建Hadoop学习环境。以下是该笔记中的重要知识点: Hadoop集群安装目录 在安装Hadoop集群之前,需要准备好安装环境。安装环境...
Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装...
本文将详细介绍如何在Ubuntu 20.04上进行MinIO的单机安装、集群搭建、数据同步以及设置策略。 首先,让我们看看单机安装的步骤: 1. **下载MinIO Server**:使用`wget`命令从官方站点下载最新版的Linux-amd64架构...
CentOS7.5 安装 Redis 集群 CentOS7.5 安装 Redis 集群是指在 CentOS 7.5 操作系统上安装和配置 Redis 集群的过程。Redis 是一个开源的、基于内存的数据结构存储系统,可以用作数据库、消息队列、缓存等。下面是...
k8s搭建Nacos集群,制作Nacos镜像 Nacos版本是:2.0.2
### Linux下Zookeeper集群的安装详解 #### 一、Zookeeper概述及主要功能 ##### Zookeeper简介 Zookeeper是一款开源的分布式协调服务组件,属于Apache顶级项目之一。它主要用于简化分布式应用程序的开发过程,为...
使用Kubeadm工具快速安装Kubernetes集群 本文档主要介绍使用Kubeadm工具快速安装Kubernetes集群的步骤和详细配置过程。Kubeadm是Kubernetes官方提供的一个用于快速安装和管理Kubernetes集群的工具。通过本文档,...
**Redis 安装** Redis(Remote Dictionary Server)...以上就是Redis的安装、配置以及集群搭建的基本流程和常用操作命令。在实际应用中,还需要考虑数据备份、监控、安全等多方面因素,以确保Redis的稳定和高效运行。
在这个安装与集群的指南中,我们将详细讲解如何进行Weblogic 11g的安装配置,以及如何构建高可用性的集群。 1. **端口与IP规划**: 在安装Weblogic之前,需要对服务器的端口和IP地址进行合理的规划。例如,Admin ...
本文将详细介绍TiDB的单机安装与集群安装步骤。 ### 一、TiDB单机安装 #### 1. 系统要求 确保你的操作系统是Linux,例如Ubuntu 18.04或CentOS 7.6。TiDB不支持Windows系统。 #### 2. 安装依赖 在开始安装前,需要...
Linux安装Spark集群 Spark可以在只安装了JDK、scala的机器上直接单机安装,但是这样的话只能使用单机模式运行不涉及分布式运算和分布式存储的代码,例如可以单机安装Spark,单机运行计算圆周率的Spark程序。...
Linux安装zookeeper集群部署文档
WebSphere 8.5 安装和集群配置 WebSphere 8.5 是一款功能强大且灵活的应用服务器,可以在各种环境中运行,包括 Linux。下面我们将详细介绍如何在 Linux 环境下安装和配置 WebSphere 8.5,以及如何设置集群环境。 ...
文章目录推荐阅读文章微服务入门,有这一篇就够了分布式微服务架构(初级篇)深入理解Dubbo核心概念,这篇文章你绝对不能错过集群模式部署安装MySQL数据库安装Nacos 推荐阅读文章 微服务入门,有这一篇就够了 分布式...
在本文中,我们将深入探讨如何在CentOS操作系统上安装和配置Redis集群,以及集群的一些常用操作。 首先,让我们了解Redis集群的基础。Redis集群是一种分布式解决方案,允许将数据分散到多个节点上,提供高可用性和...
storm单本安装及集群安装配置,详情见文档,另需要注意storm.yaml的配置。
tongweb集群安装手册 本文档旨在指导Windows平台下安装tongweb集群的人员,涵盖了Apache配置、TONGWEB集群配置、AJP通道配置等知识点。 1. Apache配置 为了实现Apache与应用服务器之间的负载均衡,我们需要使用...