`
conkeyn
  • 浏览: 1505829 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

安装rredis集群

 
阅读更多

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);

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics