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"));
}
}
相關文章
相關標籤/搜索