Redis学习笔记:(五)集群架构

1. 集群架构原理

                    
        redis集群是有多个主从节点群组成的分布式服务器集群,每一个主从节点都实现了master故障从新选举功能。支持水平扩容:官方建议不超过1000个节点)。
        redis cluster 将全部数据划分红 16384 个槽位 slots,每组节点各负责一部分。每组主从节点存储的数据都不相同。当客户端操做时,先经过 key 按照必定算法计算出 key对应的 slots,经过slots定位到相应的主从节点,在当前节点操做。
        槽位定位算法: 
            cluster对key进行crc16算法,获得一个整数,而后对13684取模,获得槽位。  HASH_SLOT = CRC16(key)mod 16384
       
集群节点之间的通讯
            节点之间采用gossip协议进行通讯。
        跳转重定位
            当客户端接收到命令,算出来对应的槽位不是当前ip对应的节点时,会向客户端发出一个特殊的跳转指令,重定位到正确的槽位后再进行操做。
            

        集群选举原理
            当从节点slave发现主节点mater状态变为FAIL后,尝试进行Failover,变为主节点。当msater有多个slave时,slave之间变存在竞争关系。争夺master流程以下:
            1)发现master状态变为FAIL
            2)将本身记录的集群currentEpoch值加1,并广播FAILOVER_AUTH_REQUEST信息
            3)其余slave收到信息后,将向集群中其余的redis节点发送信息,其余节点收到信息后,只有主节点会响应而且只会对第一个slave发送过来的请求发送异常ack,从节点不会响应
            4)尝试failover的slave收集master返回的FAILOVER_AUTH_ACK
            5)slave 收到超过半数mater的ack后变成新的Master
            6)广播Pong消息通知其余集群节点
                                 java

2. 集群搭建

    redis.conf 配置文件修改node

daemonize yes
clusterenabled yes
cluster
configfile nodes6379.conf  # 与节点 port 对应上
cluster
nodetimeout 5000
# bind
127.0.0.1(去掉bind绑定访问ip信息)
protected
mode no (关闭保护模式)
appendonly yes
requirepass 123123
 (设置redis访问密码,测试环境可不设置)
masterauth 123123
 (设置集群节点间访问密码,跟上面一致,测试环境可不设置) web

    分别启动全部节点信息,注意关闭主机防火墙,或打开相应的端口号(redis端口和gossip协议端口),保证redis 各节点之间可以相互访问
    用 redis-cli 建立集群信息(redis 5 及之后版本),链接任意一个客户端,输入如下命令
        src/redis-cli -a 123123 --cluster create --cluster-replicas 1 192.168.137.10:8001 192.168.137.10:8002 192.168.137.10:8003 192.168.137.10:8004 192.168.137.10:8005 192.168.137.10:8006
        (其中 --cluster-replicas 1 表示一个master 创建一个副本数)
        输入  cluster nodes 查看节点列表,主节点 最后的 0-5460、5461-1092二、10923-16383 表示槽位信息
        
至此集群搭建完毕。redis

3. Jedis 链接 redis 集群

    pom 文件算法

<dependencies>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>
</dependencies>

    Java 代码 spring

package com.zg.jedis;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * jedis 链接redis集群架构
 * @author zg
 * @date 2020/9/13
 */
public class JedisClusterTest {

    public static void main(String[] args) {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(20);
        config.setMaxIdle(10);
        config.setMinIdle(5);

        Set<HostAndPort> jedisClusterNode = new HashSet<>();
        jedisClusterNode.add(new HostAndPort("192.168.137.10", 8001));
        jedisClusterNode.add(new HostAndPort("192.168.137.10", 8002));
        jedisClusterNode.add(new HostAndPort("192.168.137.10", 8003));
        jedisClusterNode.add(new HostAndPort("192.168.137.10", 8004));
        jedisClusterNode.add(new HostAndPort("192.168.137.10", 8005));
        jedisClusterNode.add(new HostAndPort("192.168.137.10", 8006));

        JedisCluster jedisCluster = null;

        try {
           jedisCluster = new JedisCluster(jedisClusterNode, 6000, 5000, 10, config);

            System.out.println(jedisCluster.set("myCluster", "happy"));
            System.out.println(jedisCluster.get("myCluster"));
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            if (null != jedisCluster){
                try {
                    jedisCluster.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

4. Springboot 链接 redis集群

    pom文件apache

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
    </dependency>
</dependencies>

    application.propertites 服务器

spring.redis.database=0
spring.redis.timeout=3000ms
spring.redis.password=123123  # 没有密码的话,不用加
spring.redis.lettuce.pool.max-idle=50
spring.redis.lettuce.pool.min-idle=10
spring.redis.lettuce.pool.max-active=100
spring.redis.lettuce.pool.max-wait=1000ms
# 集群模式链接参数
spring.redis.cluster.nodes=192.168.137.10:8001,192.168.137.10:8002,192.168.137.10:8003,192.168.137.10:8004,192.168.137.10:8005,192.168.137.10:8006

    java 代码 架构

package com.zg.redis.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 集群架构测试
 * @author gz
 * @date 2020/9/13
 */
@RestController
public class RedisController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping("testCluster")
    public void testCluster(){
        stringRedisTemplate.opsForValue().set("myCluster", "Hello World");
        System.out.println(stringRedisTemplate.opsForValue().get("myCluster"));
}
}
相关文章
相关标签/搜索