搭建redis高可用:主从、哨兵、集群

搭建主从

version: "3"

networks:
  redis-replication:
    driver: bridge
    ipam:
      config:
        - subnet: 172.25.0.0/24

services:
  master:
    image: 10.30.30.22:9080/library/redis:5.0.5
    container_name: redis-master
    ports:
      - "6379:6379"
    volumes:
      - "./master/redis.conf:/etc/redis.conf"
      - "./master/data:/data"
    command: redis-server /etc/redis.conf
    restart: always
    networks:
      redis-replication:
        ipv4_address: 172.25.0.101

  slave1:
    image: 10.30.30.22:9080/library/redis:5.0.5
    container_name: redis-slave-1
    ports:
      - "6380:6379"
    volumes:
      - "./slave1/redis.conf:/etc/redis.conf"
      - "./slave1/data:/data"
    command: redis-server --slaveof redis-master 6379
    restart: always
    networks:
      redis-replication:
        ipv4_address: 172.25.0.102

  slave2:
    image: 10.30.30.22:9080/library/redis:5.0.5
    container_name: redis-slave-2
    ports:
      - "6381:6379"
    volumes:
      - "./slave2/redis.conf:/etc/redis.conf"
      - "./slave2/data:/data"
    command: redis-server --slaveof redis-master 6379
    restart: always
    networks:
      redis-replication:
        ipv4_address: 172.25.0.103

执行

docker-compose -f docker-compose-master-slave.yaml up -d

执行即可搭建好
验证:一个输入,在另外节点查询

搭建哨兵

第一步先搭建主从,上面的配置即可
第二步,搭建哨兵
放置的目录

.
├── docker-compose-master-slave.yaml
├── docker-compose-sentinel.yaml
├── sentinel1.conf
├── sentinel2.conf
└── sentinel3.conf
version: '3'
services:
  sentinel1:
    image: 10.30.30.22:9080/library/redis:5.0.5
    container_name: redis-sentinel-1
    ports:
      - 26379:26379
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    restart: always
    volumes:
      - ./sentinel1.conf:/usr/local/etc/redis/sentinel.conf
  sentinel2:
    image: 10.30.30.22:9080/library/redis:5.0.5
    container_name: redis-sentinel-2
    ports:
    - 26380:26379
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./sentinel2.conf:/usr/local/etc/redis/sentinel.conf
  sentinel3:
    image: 10.30.30.22:9080/library/redis:5.0.5
    container_name: redis-sentinel-3
    ports:
      - 26381:26379
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./sentinel3.conf:/usr/local/etc/redis/sentinel.conf
networks:
  default:
    external:
      name: sentinel_redis-replication

sentinel.conf三个配置都一样

# 哨兵sentinel实例运行的端口 默认26379
port 26379
# myid
# 哨兵sentinel的工作目录
dir /tmp
# 自定义集群名,其中 172.25.0.101 为 redis-master 的 ip,6379 为 redis-master 的端口,2 为最小投票数(因为有 3 台 Sentinel 所以可以设置成 2)
sentinel monitor mymaster 172.25.0.101 6379 2

sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster 123456
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes

搭建集群

.
├── cluster-6381.conf
├── cluster-6382.conf
├── cluster-6383.conf
├── cluster-6384.conf
├── cluster-6385.conf
├── cluster-6386.conf
└── docker-compose-cluster.yaml
version: '3'
services:
 redis-6381:
  container_name: redis-cluster-1
  image: 10.30.30.22:9080/library/redis:5.0.5
  command: redis-server /etc/usr/local/redis.conf
  ports:
   - "6381:6381"
  volumes:
   - ./cluster-6381.conf:/etc/usr/local/redis.conf
   - ./redis-6381/data:/data

 redis-6382:
  container_name: redis-cluster-2
  image: 10.30.30.22:9080/library/redis:5.0.5
  command: redis-server /etc/usr/local/redis.conf
  ports:
   - "6382:6382"
  volumes:
   - ./cluster-6382.conf:/etc/usr/local/redis.conf
   - ./redis-6382/data:/data

 redis-6383:
  container_name: redis-cluster-3
  image: 10.30.30.22:9080/library/redis:5.0.5
  command: redis-server /etc/usr/local/redis.conf
  ports:
   - "6383:6383"
  volumes:
   - ./cluster-6383.conf:/etc/usr/local/redis.conf
   - ./redis-6383/data:/data

 redis-6384:
  container_name: redis-cluster-4
  image: 10.30.30.22:9080/library/redis:5.0.5
  command: redis-server /etc/usr/local/redis.conf
  ports:
   - "6384:6384"
  volumes:
   - ./cluster-6384.conf:/etc/usr/local/redis.conf
   - ./redis-6384/data:/data

 redis-6385:
  container_name: redis-cluster-5
  image: 10.30.30.22:9080/library/redis:5.0.5
  command: redis-server /etc/usr/local/redis.conf
  ports:
   - "6385:6385"
  volumes:
   - ./cluster-6385.conf:/etc/usr/local/redis.conf
   - ./redis-6385/data:/data

 redis-6386:
  container_name: redis-cluster-6
  image: 10.30.30.22:9080/library/redis:5.0.5
  command: redis-server /etc/usr/local/redis.conf
  ports:
   - "6386:6386"
  volumes:
   - ./cluster-6386.conf:/etc/usr/local/redis.conf
   - ./redis-6386/data:/data
protected-mode no
#bind 127.0.0.1
port 6381
# 开启集群模式
cluster-enabled yes
protected-mode no
#bind 127.0.0.1
port 6382
# 开启集群模式
cluster-enabled yes
protected-mode no
#bind 127.0.0.1
port 6383
# 开启集群模式
cluster-enabled yes
protected-mode no
#bind 127.0.0.1
port 6384
# 开启集群模式
cluster-enabled yes
protected-mode no
#bind 127.0.0.1
port 6385
# 开启集群模式
cluster-enabled yes
protected-mode no
#bind 127.0.0.1
port 6386
# 开启集群模式
cluster-enabled yes

启动容器

docker-compose -f docker-compose-cluster.yaml up -d

配置槽位

docker exec -it redis-cluster-1 redis-cli -p 6381 --cluster fix localhost:6381
docker exec -it redis-cluster-2 redis-cli -p 6382 --cluster fix localhost:6382
docker exec -it redis-cluster-3 redis-cli -p 6383 --cluster fix localhost:6383
docker exec -it redis-cluster-4 redis-cli -p 6384 --cluster fix localhost:6384
docker exec -it redis-cluster-5 redis-cli -p 6385 --cluster fix localhost:6385
docker exec -it redis-cluster-6 redis-cli -p 6386 --cluster fix localhost:6386

配置集群

查找每个节点的ip并进行配置
查找对应ip命令

docker exec -it redis-cluster-1 cat /etc/hosts

配置集群关联

docker exec -it redis-cluster-1 redis-cli -p 6381 --cluster create 172.27.0.4:6381 172.27.0.2:6382 172.27.0.6:6383 172.27.0.5:6384 172.27.0.3:6385 172.27.0.7:6386 --cluster-replicas 1

遇到需要输入,输入yes即可

java使用

.
├── Dockerfile
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── github
        │           └── test
        │               ├── DemoApplication.java
        │               ├── config
        │               │   └── RedisConfig.java
        │               └── controller
        │                   └── DemoController.java
        └── resources
            └── application.yml
package com.isyscore.os.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    //字符串建议使用StringRedisTemplate
    @Bean("stringRedisTemplate")
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

/**
* @author shizi
* @since 2022-05-24 10:19:26
*/
@RequestMapping("api/demo")
@RestController
public class DemoController {
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    @GetMapping("set/{key}/{value}")
    private String setValue(@PathVariable("key") String key, @PathVariable("value") String value) {
        stringRedisTemplate.opsForValue().set(key, value, 1, TimeUnit.HOURS);
        return "ok";
    }
    
    @GetMapping("get/{key}")
    private String getValue(@PathVariable("key") String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }
}
spring:
  redis:
    host: 172.17.0.2
    port: 6379
#    sentinel:
#      master: mymaster
#      nodes:
#        - 172.25.0.2:26379
#        - 172.25.0.3:26379
#        - 172.25.0.4:26379
    cluster:
      nodes:
        - 172.27.0.4:6381
        - 172.27.0.2:6382
        - 172.27.0.6:6383
        - 172.27.0.5:6384
        - 172.27.0.3:6385
        - 172.27.0.7:6386

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
</parent>

<groupId>com.isyscore.os</groupId>
<artifactId>isc-redis-test</artifactId>
<version>1.0.0</version>

<dependencies>
  <!-- redis start -->
  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
  </dependency>
  
  <dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
  </dependency>
  
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
  </dependency>
  
  <dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
  </dependency>
  
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
  </dependency>
  <!-- redis end -->
  
  <!-- spring -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator-autoconfigure</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator</artifactId>
  </dependency>
 </dependencies>
<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>
FROM docker.io/itoak/java8:1.0.0
# 容器启动后的工作目录
WORKDIR /opt
# 将jar包添加到容器内
ADD xxx.jar server.jar
# 容器启动后 执行命令
CMD java -jar server.jar

打容器镜像(标签自行打,我这里是哨兵使用sentinel,集群使用cluster)

docker build -t redis-java-test:sentinel .
docker build -t redis-java-test:cluster .

运行时候有不同,要将对应的测试镜像所在网络与哨兵或者集群应该在同一个网络

docker network ls

上面的哨兵和集群配置最后生成的网络分别如下,在运行测试用例的时候要带上对应的网络

  • cluster_default:这个是集群的网络
  • sentinel_redis-replication:这个是哨兵的网络

哨兵下的运行命令

docker run --network sentinel_redis-replication --name redis-java-sentinel -d -p 28080:8080 redis-java-test:sentinel

集群下的运行命令

docker run --network cluster_default --name redis-java-cluster -d -p 28081:8080 redis-java-test:cluster

go使用

go代码这里使用了go-redis,不过进行了一些封装,使用方式请见https://github.com/isyscore/isc-gobase/tree/main/redis

go get github.com/isyscore/isc-gobase�

.
├── Dockerfile
├── application.yml
├── go.mod
└── main.go
#build stage
FROM golang:1.18 as builder

RUN go version

ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.cn

WORKDIR /app

COPY . /app/

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /app
EXPOSE 8081

#image stage
FROM alpine:latest

WORKDIR /app

ENV TZ=Asia/Shanghai
ENV ZONEINFO=/app/zoneinfo.zip

COPY --from=builder /app/application.yml /app/application.yml
#COPY --from=builder /app/config/application-default.yml /app/config/application-default.yml
COPY --from=builder /app/base-redis-test /app/base-redis-test
COPY --from=builder /usr/local/go/lib/time/zoneinfo.zip /app

CMD ["./base-redis-test"]
base:
  application:
    name: sample
  server:
    enable: true
    port: 32005
    gin:
      # 有三种模式:debug/release/test
      mode: debug
  redis:
    enable: true
#    standalone:
#      addr: redis-standalone:6379
#    sentinel:
#      master: mymaster
#      addrs:
#        - redis-sentinel-1:26379
#        - redis-sentinel-2:26379
#        - redis-sentinel-3:26379
    cluster:
      addrs:
        - localhost:6381
        - localhost:6382
        - localhost:6383
        - localhost:6384
        - localhost:6385
        - localhost:6386
      max-redirects: 4

构建

go build

然后执行打镜像,镜像手法与java同样

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值