什么是Redis主从复制?
通俗的说就是我们有一台主redis服务器,多台从redis服务器,一般主服务器用于写数据,从服务器只能读数据,从服务器会自动同步主服务器数据。
为什么要使用Redis主从复制?
- 读写分离
- 故障切换,当master出问题后还有slave节点可以使用
- redis-server单点故障
- 单节点QPS有限
搭建主从复制
我们将redis文件复制两份,修改其中一份的配置文件,将其端口号改为6380
port 6380
将两个redis服务启动。
同时启动两个客户端,客户端指定端口连接:
redis-cli -p 6380
首先清除两台服务器数据
flushdb
输入以下命令指定主服务器
slaveof 127.0.0.1 6379
现在测试是否主从同步
主服务器插入一条数据
set test_key test_value
从服务器获得数据
get test_key
查看主从复制信息
info replication
退出集群
slaveof no one
以上是命令行的主从配置,我们同样可以修改配置文件。
修改从服务器配置文件,增加一行配置即可
slaveof 127.0.0.1 6379
注意事项:
如果是master无持久化,slave开启持久化来保留数据的场景,建议不要配置redis自动重启,否则master启动后,无备份数据,可能导致集群数据丢失。
java实现读写分离
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sunyuqi</groupId>
<artifactId>redis_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>9</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
主从模式配置类
package com.sunyuqi.repl;
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.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
@Configuration
@Profile("replication-rw") // 主从 - 读写分离模式
class ReplicationRWRedisAppConfig {
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(ReadFrom.REPLICA_PREFERRED)
.build();
RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration("127.0.0.1", 6379);
return new LettuceConnectionFactory(serverConfig, clientConfig);
}
}
server类
package com.sunyuqi.repl;
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);
}
}
引导类
package com.sunyuqi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootApplicationDemo {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplicationDemo.class,args);
}
}
测试类
package com.sunyuqi.repl;
import com.sunyuqi.SpringbootApplicationDemo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootApplicationDemo.class)
@ActiveProfiles("replication-rw") // 激活主从集群-读写分离的配置
public class ReplicationRWTests {
@Autowired
ReplicationExampleService replicationExampleService;
@Test
public void setTest() {
replicationExampleService.setByCache("test_key", "test_value");
String result = replicationExampleService.getByCache("test_key");
System.out.println("从缓存中读取到数据:" + result);
}
}
通过monitor命令监控是否读写分离
主服务器写入数据
从服务器读取数据