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);
相关推荐
Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装...
k8s搭建Nacos集群,制作Nacos镜像 Nacos版本是:2.0.2
Linux环境MinIO单机安装、集群搭建,数据同步,策略示例。 超详细,一步步学会并启动
ZooKeeper安装配置 集群ZooKeeper安装配置 集群ZooKeeper安装配置 集群ZooKeeper安装配置 集群ZooKeeper安装配置 集群ZooKeeper安装配置 集群ZooKeeper安装配置 集群ZooKeeper安装配置 集群ZooKeeper安装配置 集群...
CentOS7 安装RabbitMQ集群 CentOS7 安装RabbitMQ集群 CentOS7 安装RabbitMQ集群
Linux安装Spark集群 Spark可以在只安装了JDK、scala的机器上直接单机安装,但是这样的话只能使用单机模式运行不涉及分布式运算和分布式存储的代码,例如可以单机安装Spark,单机运行计算圆周率的Spark程序。...
Linux安装zookeeper集群部署文档
Linux下Zookeeper集群的安装
文档详细描述了如何在linux上配置mysql集群,列出了linux版本、mysql版本以及其他用到的系统包,其中gcc-4.4.4.tar.gz比较大,没办法上传,需要自己网上下载。
利用ansible 自动 安装Hadoop 集群
CentOS7.5 安装Redis集群,已经在生成环境使用 CentOS7.5 安装Redis集群,已经在生成环境使用
redis集群安装redis集群安装redis集群安装redis集群安装redis集群安装redis集群安装redis集群安装redis集群安装
redis 安装教程,及redis 集群搭建教程 redis 常用操作命令
storm单本安装及集群安装配置,详情见文档,另需要注意storm.yaml的配置。
activemaq 的linux安装教程,包含集群和单个安装
ubuntu下安装hadoop集群,设置ssh对其他node无密码访问
docker安装greenplum集群服务,通过dockerfile创建greenplum镜像,容器启动后,对greenplum集群进行配置
本文包含elang安装,RabbitMQ安装配置,RabbitMQ两台服务器集群
linux环境下WebSphere8.5安装+集群2台集群配置集群A:配置 集群管理端+节点 B:配置节点
cognos10安装、集群文档,赶紧来下载吧,很好的cognos资料