Redis集群搭建与使用方法

集群概要:

    redis集群可以解决哨兵模式分布式难以搭建的问题、只需要连接任何一台服务器就可以将分布式存储数据,数据迁移简单

    整个集群6台服务器,三主三从,三台物理机,一台物理机一主一从

一、配置redis.conf

    1、新建一个目录存放集群的配置文件

        cd /home/jionsvolk/proc/redis-4.0.8

        mkdir conf-cluster

        cp redis.conf conf-cluster/6381.conf

    2.编辑6381.conf

#bind xxx全部注掉
bind xxx
#保护模式关闭
protected-mode no
#自定义端口
port 6381
#连接空闲关闭超时时间,根据系统负载考量
timeout 600
#TCP连接Keepalive时间,根据系统负载考量
tcp-keepalive 600
#打开后台运行
daemonize yes
#PID文件名 因为我之前测试了哨兵模式,已经有redis_6381.pid,为了区分加了"_c_"
pidfile /var/run/redis_c_6381.pid
#日志文件
logfile "/home/jionsvolk/proc/redis-4.0.8/logs-cluster/6381.log"
#持久化文件名
dbfilename 6381.rdb
#持久化文件存放目录,千万要去对应目录创建该文件夹
dir /home/jionsvolk/data/redis/cluster/dump
#另外一种持久化方式打开
appendonly yes
#AOF文件名
appendfilename "/home/jionsvolk/data/redis/cluster/aof/appendonly.aof"
#使用集群
cluster-enabled yes
#集群使用到的配置文件名
cluster-config-file nodes-6381.conf
#集群中各服务器通信超时时间
cluster-node-timeout 15000
#最大内存  byte
maxmemory 128*1024*1024
#内存管理策略
maxmemory-policy volatile-lru

    3.复制一份配置文件给从服务器用

        cp 6381.conf 6382.conf

        vi 6382.conf

        #下面的命令是将文件中所有6381改成6382

        :%s/6381/6382/g

    4.把两个服务器的启动脚本写在一个文件中

  • redis-server 6381.conf &
    redis-server 6382.conf &

二、配置集群

    配置集群需要使用到一个工具,该工具需要下载并编译

    1.工具安装

            cd ruby-2.3.1

            ./configure        

            make && make install

  • yum -y install rubygems

            rubygems是一个用于对 Ruby组件进行打包的 Ruby 打包系统。 它提供一个分发 Ruby 程序和库的标准格式,还提供一个管理程序包安装的工具

  • gem install redis
  • ruby -v  检查版本

    2.redis的安装

        按照该网址进行安装https://my.oschina.net/u/3049601/blog/1142841

    3.使用redis-trib.rb工具配置集群

   因为经常在conf-cluster目录操作,所以在该目录下创建一个硬连接文件指向/home/jionsvolk/proc/redis-4.0.8/src/redis-trib.rb

        ln redistool /home/jionsvolk/proc/redis-4.0.8/src/redis-trib.rb

        3.1在集群中添加三个主节点

            命令:redistool create 192.168.245.111:6381 192.168.245.112:6381 192.168.245.113:6381

            

            执行结果

            

            执行过程中如果出现如下类似错误,需删除所有的rdb、aof、nodes-xxxx.conf文件

 /usr/lib64/ruby/gems/1.8/gems/redis-3.3.2/lib/redis/client.rb:121:in `call': ERR Slot 3853 is already busy (Redis::CommandError)

        3.2 检查集群

            登录刚才三台服务器中的任意一台

            redis-cli -c -p 6381

            127.0.0.1:6381> cluster nodes

            

            可以看到三台服务器都是master

        3.3 将三个从节点添加到集群当中

            redistool add-node --slave --master-id b1ad0d9af8dd6c5ec91e8e92537ec8b44c8c1224 192.168.245.111:6382 192.168.245.111:6381
                redistool add-node --slave --master-id b8a1c799b3beb3f25242cd31c277d5a6481371bd 192.168.245.112:6382 192.168.245.111:6381
            redistool add-node --slave --master-id 33bc3c223900410922839944deefc8c4c8bc1332 192.168.245.113:6382 192.168.245.111:6381

                执行结果如下:

                

        3.4 检查从节点加入集群情况

            登录刚才三台服务器中的任意一台

            redis-cli -c -p 6381

            127.0.0.1:6381> cluster nodes

            

            可以看到新加的三台服务器已经是各自主服务器的从服务器

        3.5 往集群中添加数据

            redis-cli -c -p 6381

            set name Messi

            

            集群根据哈希取模定位到槽道5798,而5798操作是分配给192.168.245.112:6381这台服务器的(只有主服务器才能分配到槽道)

            

三、代码连接集群

    1. 普通模式

public static void main(String[] args) {
    JedisPoolConfig poolConfig = new JedisPoolConfig();
    // 最大连接数
    poolConfig.setMaxTotal(1);
    // 最大空闲数
    poolConfig.setMaxIdle(1);
    // 最大允许等待时间,如果超过这个时间还未获取到连接,则会报JedisException异常:
    // Could not get a resource from the pool
    poolConfig.setMaxWaitMillis(1000);
    Set<HostAndPort> nodes = new LinkedHashSet<HostAndPort>();
    //这里可以不把集群所有机器都添加进来,因为连接任何一台都可以往集群正确的地方发送数据并存储
    nodes.add(new HostAndPort("192.168.245.111", 6381));
    nodes.add(new HostAndPort("192.168.245.111", 6382));
    nodes.add(new HostAndPort("192.168.245.112", 6381));
    nodes.add(new HostAndPort("192.168.245.112", 6382));
    nodes.add(new HostAndPort("192.168.245.113", 6381));
    nodes.add(new HostAndPort("192.168.245.114", 6382));
    JedisCluster jedis = new JedisCluster(nodes, poolConfig);
    jedis.set("name", "Messi");
    System.out.println(cluster.get("name"));
    try {
        cluster.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

    2. Spring boot

        POM中导入redis启动器

        <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-redis</artifactId>
           <version>1.4.5.RELEASE</version>
    	</dependency>

        在application.properties中配置redis相关属性,该配置只适合集群

###################################  redis 集群配置 ##########################################
# REDIS(RedisProperties)
# (普通集群,不使用则不用开启)在群集中执行命令时要遵循的最大重定向数目。
# spring.redis.cluster.max-redirects=
# (普通集群,不使用则不用开启)以逗号分隔的“主机:端口”对列表进行引导。
spring.redis.cluster.nodes=192.168.245.111:6381,192.168.245.111:6382,192.168.245.112:6381,192.168.245.112:6382,192.168.245.113:6381,192.168.245.113:6382
# 连接工厂使用的数据库索引。
spring.redis.database=0
# 连接URL,将覆盖主机,端口和密码(用户将被忽略),例如:redis://user:[email protected]:6379
# spring.redis.url=
# Redis服务器主机。
#spring.redis.host=localhost
# 登录redis服务器的密码。
#spring.redis.password=
# 启用SSL支持。
spring.redis.ssl=false
# 池在给定时间可以分配的最大连接数。使用负值无限制。
spring.redis.pool.max-active=8
# 池中“空闲”连接的最大数量。使用负值表示无限数量的空闲连接。
spring.redis.pool.max-idle=8
# 连接分配在池被耗尽时抛出异常之前应该阻塞的最长时间量(以毫秒为单位)。使用负值可以无限期地阻止。
spring.redis.pool.max-wait=10000
# 目标为保持在池中的最小空闲连接数。这个设置只有在正面的情况下才有效果。
spring.redis.pool.min-idle=0
# Redis服务器端口。
#spring.redis.port=6379
# (哨兵模式,不使用则不用开启)Redis服务器的名称。
# spring.redis.sentinel.master=
# (哨兵模式,不使用则不用开启)主机:端口对的逗号分隔列表。 
# spring.redis.sentinel.nodes=
# 以毫秒为单位的连接超时。
spring.redis.timeout=10000

    在controller中配置使用redis

@Controller
@RequestMapping("/web/itemcat")
public class WebItemCatController {
	@Autowired
	private ItemCatService itemCatService;
	
	@Autowired
	private RedisTemplate redisTemplate;

	//jsonp格式传递三级结构数据
	@RequestMapping("/all")
	@ResponseBody
	public JSONPObject queryItemCatList(String callback){
		ItemCatResult result = itemCatService.queryItemCatsNew();
		System.out.println(result);
		redisTemplate.opsForValue().set("name", "Havi");
		System.out.println("redisTemplate.opsForValue().get(\"name\"):"+redisTemplate.opsForValue().get("name"));
		JSONPObject jsonpResult=new JSONPObject(callback, result);
		return jsonpResult;
		}
}

    RedisTemplate是spring boot自动实例化到容器中,并注入到我的controller

    3.spring boot 自己写代码注入redis集群对象

    配置共享上面的内容

@ConfigurationProperties("spring.redis")
public class RedisConfig {
	@Value("cluster.nodes:null")
	private String nodes;
	@Value("pool.max-active:10")
	private Integer maxActive;
	@Value("pool.max-idle:5")
	private Integer maxIdle;
	@Value("pool.max-wait:10000")
	private Integer maxWait;
	@Value("pool.min-idle:0")
	private Integer minIdle;
	@Value("timeout:10000")
	private Integer timeout;
	
	/**
	 * 初始化Jedis配置对象
	 * @return
	 */
	public JedisPoolConfig getConfig(){
		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxTotal(maxActive);
		config.setMaxIdle(maxIdle);
		config.setMaxWaitMillis(maxWait);
		config.setMinIdle(minIdle);
		return config;
	}
	
	/*
	 * 初始化连接池,并通过@Bean将连接池放入到容器中
	 * 
	 * 为了让开发人员更方便的使用,还需要对方法进一步封装
	 */
	@Bean
	public JedisCluster initCluster(){
		Set<HostAndPort> set  = new HashSet<>();
		
		String[] hps = nodes.split(",");
		for(String hp : hps) {
			HostAndPort hpConfig = new HostAndPort(hp.split(":")[0], Integer.parseInt(hp.split(":")[1]));
			set.add(hpConfig);
		}
		
		JedisCluster cluster = new JedisCluster(set,timeout);
		
		return cluster;
	}
}

    既然Spring Boot已经给咱们封装好了,直接用就行了,不用这么麻烦再自己搞代码放入容器,如果是使用原生的spring和spring mvc可以使用这种方式

猜你喜欢

转载自my.oschina.net/u/3049601/blog/1789500