美文网首页
Redis 主从复制

Redis 主从复制

作者: 右耳菌 | 来源:发表于2022-09-01 22:31 被阅读0次

1. 主从复制介绍

1.1 什么是主从复制?
1.2 为什么要主从复制?
  • redis-server 单节点故障
  • 单节点QPS有限
1.3 主从复制应用场景分析
  • 读写分离场景,规避redis单机瓶颈
  • 故障切换,master出问题后还有slave节点可以使用。

2. 搭建主从复制

主Redis Server以普通模式启动,主要是启动从服务器的方式

2.1 第一种方式:命令行
#连接需要实现从节点的redis,执行下面的命令
slaveof [ip] [port]
2.2 第二种方式:redis.conf配置文件
# 配置文件中增加
slavepof [ip] [port]
# 从服务器是否只读(默认yes)
slave-read-only yes
2.3 退出主从集群的方式
slaveof no one

注意: 因为文化差异的原因,新的版本可能会将slaveof变为replicaof,但是其实是一样的。


3. 检查主从复制

  • master


    网上的例子

    实际运行的例子

192.168.1.7:6379> info replication
# Replication
role:master
connected_slaves:0
master_replid:4fa1246eb96e7ad381cd21ab0f1f5a267d1a1cec
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:210
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:210
  • slave


    网上的例子

    实际运行的例子

192.168.1.7:6378> info replication
# Replication
role:slave
master_host:192.168.1.7
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1662020523
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:101535bfbefc8c9858ff46bad42b8439c87295eb
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
(3.74s)

注意: 如果从服务器尝试复制数据时,提示以下错误,那么可能是缺少了文件的读取权限,需要使用sudo 或者 切换到 root用户启动!

Opening the temp file needed for MASTER <-> REPLICA synchronization: Permission denied

4. 主从复制流程

  1. 从服务器通过psync命令发送服务器已有的同步进度(同步源ID、同步进度offset)
  2. master收到请求,同步源为当前master,则根据偏移量增量同步
  3. 同步源非当前master,则进入全量同步: master生成rdb,传输到slave,加载到slave内存

5. 主从复制核心知识

  • Redis默认使用异步复制,slave和master之间异步地确认处理的数据量
  • 一个master可以拥有多个slave
  • slave可以接受其他slave的连接。slave可以有下级sub slave
  • 主从同步过程在master侧是非阻塞的
  • slave初次同步需要删除旧数据,加载新数据,会阻塞到来的连接请求

6. 主从复制应用场景

  • 主从复制可以用来支持读写分离
  • slave服务器设定为只读,可以用在数据安全的场景下。
  • 可以使用主从复制来避免master持久化造成的开销。master关闭持久化,slave配置为不定期保存或是启用AOF。(注意:重新启动的master程序将从一个空数据集开始,如果一个slave试图与它同步,那么这个slave也会被清空。)

7. 主从复制的注意事项

  • 读写分离场景
    1.数据复制延时导致读到过期数据或者读不到数据(网络原因、slave阻塞)
    2.从节点故障(多个client如何迁移)

  • 全量复制情况下
    1.第一次建立主从关系或者runid不匹配会导致全量复制
    2.故障转移的时候也会出现全量复制

  • 复制风暴
    1.master故障重启,如果slave节点较多,所有slave都要复制,对服务器的性能,网络的压力都有很大影响。
    2.如果一个机器部署了多个master

  • 写能力有限
    1.主从复制还是只有一台master,提供的写服务能力有限

  • matser故障情况下
    1.如果是master无持久化,slave开启持久化来保存数据的场景,建议不要配置redis自动重启。
    2.启动redis自动重启,master启动后,无备份数据,可能导致集群数据丢失的情况

  • 带有效期的key
    1.slave不会让key过期,而是等待master让key过期
    2.在Lua脚本执行期间,不执行任何key过期操作


8. 例子

首先记得先把lettuce依赖加入pom

        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>${lettuce.version}</version>
        </dependency>

1. 非读写分离方式
创建ReplicationRedisAppConfig.java

package cn.lazyfennnec.cache.redis;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;

@Configuration
@Profile("replication") // 主从模式
class ReplicationRedisAppConfig {

    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(redisConnectionFactory);
        return stringRedisTemplate;
    }


    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        // 假设master:192.168.100.241    slave:192.168.100.242
        // 默认slave只能进行读取,不能写入
        // 如果你的应用程序需要往redis写数据,建议连接master
        // 其实本地的redis都是在同一个服务器上的,分别为
        // 1. master 192.168.1.7 6379
        // 2. slave  192.168.1.7 6378
        return new LettuceConnectionFactory(new RedisStandaloneConfiguration("192.168.1.7", 6379));
    }
}

2. 读写分离的方式
创建ReplicationRWRedisAppConfig.java

package cn.lazyfennec.cache.redis;

import io.lettuce.core.ReadFrom;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;

@Configuration
@Profile("replication-rw") // 主从 - 读写分离模式
class ReplicationRWRedisAppConfig {

    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(redisConnectionFactory);
        return stringRedisTemplate;
    }

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        System.out.println("使用读写分离版本");
        LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
                .readFrom(ReadFrom.SLAVE_PREFERRED)
                .build();
        // 此处
        RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration("192.168.1.7", 6378);
        return new LettuceConnectionFactory(serverConfig, clientConfig);
    }
}

3. Service实现类

package cn.lazyfennec.cache.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class ReplicationExampleService {
    @Autowired
    private StringRedisTemplate template;

    public void setByCache(String userId, String userInfo) {
        template.opsForValue().set(userId, userInfo);
    }

    public String getByCache(String userId) {
        return template.opsForValue().get(userId);
    }
}

4. 测试代码

  • 非读写分离方式
package cn.lazyfennec.cache.redis;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@ActiveProfiles("replication") // 激活主从复制的配置
public class ReplicationTests {
    @Autowired
    ReplicationExampleService replicationExampleService;

    @Test
    public void setTest() {
        replicationExampleService.setByCache("neco", "hahhhhh");
    }
}
  • 读写分离的方式
package cn.lazyfennec.cache.redis;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@ActiveProfiles("replication-rw") // 激活主从集群-读写分离的配置
public class ReplicationRWTests {
    @Autowired
    ReplicationExampleService replicationExampleService;

    @Test
    public void setTest() {
        replicationExampleService.setByCache("neco", "xxxx");
        String result = replicationExampleService.getByCache("neco");
        System.out.println("从缓存中读取到数据:" + result);
    }
}

如果觉得有收获,欢迎点赞和评论,更多知识,请点击关注查看我的主页信息哦~

相关文章

  • Redis|主从复制与哨兵机制

    1. Redis主从复制 1.1 Redis主从复制 Redis主从复制主要有两个角色,主机(master)对外提...

  • 【Redis学习笔记】13 Redis 主从复制

    1. Redis 主从复制特性 2. Redis 主从复制流程 3. Redis 主从复制操作 IP地址端口角色1...

  • Redis主从复制

    Redis主从复制 一.主从复制介绍 1.Redis复制功能介绍 1)Redis 使用异步复制。从 Redis2....

  • Redis的高可用

    Redis主从复制 什么是主从复制 Redis有三种集群方案,主从复制,哨兵,cluster集群,主从复制是指将一...

  • redis(二)

    Redis用户认证 禁用危险命令 主从复制的过程 主从复制的部署 哨兵 Redis哨兵+主从+密码 Redis哨兵...

  • Redis Sentinel 介绍与部署

    Redis Sentinel 介绍与部署 1. Sentinel介绍 1.1 主从复制的问题 Redis主从复制可...

  • 高可用的redis服务搭建

    Redis Sentinel 介绍与部署 1. Sentinel介绍 1.1 主从复制的问题 Redis主从复制可...

  • redis主从设置

    redis主从复制 Redis读取写入的速度都特别快,但是也会产生读压力特别大的场景。 Redis支持主从复制,主...

  • redis的三种集群方式

    redis的三种集群方式 redis有三种集群方式:主从复制,哨兵模式和集群。 1.主从复制 主从复制原理: 从服...

  • Redis哨兵集群

    redis-sentinel主从复制高可用 Redis-Sentinel Redis-Sentinel是redis...

网友评论

      本文标题:Redis 主从复制

      本文链接:https://www.haomeiwen.com/subject/wcrsnrtx.html