๊ฐœ๋ฐœ์ž HOON
๐Ÿ› HOON DEVLog
๊ฐœ๋ฐœ์ž HOON
์ „์ฒด ๋ฐฉ๋ฌธ์ž
์˜ค๋Š˜
์–ด์ œ
  • ๐Ÿ˜Ž ์ „์ฒด ์นดํ…Œ๊ณ ๋ฆฌ (137)
    • ๐Ÿ“ ์‹ ์ž… ์ธํ„ฐ๋ทฐ ์ค€๋น„ (7)
    • ๐Ÿฆ” ์ทจ์—…์ค€๋น„ ๊ธฐ๋ก (7)
    • โ˜• ์ž๋ฐ” : JAVA (5)
    • ๐Ÿ ์ฝ”๋”ฉํ…Œ์ŠคํŠธ ๋Œ€๋น„ : PS (80)
    • ๐ŸŒฑ ๋ฐฑ์—”๋“œ : Backend (13)
    • ๐Ÿงช ์ปดํ“จํ„ฐ๊ณผํ•™ : CS (11)
    • ๐Ÿ—‚ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค : DB (1)
    • ๐Ÿƒ‍โ™‚๏ธ DEVLOG (8)
    • โš™๏ธ Trouble Shooting (5)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • GitHub
  • Resume

๊ณต์ง€์‚ฌํ•ญ

์ธ๊ธฐ ๊ธ€

์ตœ๊ทผ ๊ธ€

ํ‹ฐ์Šคํ† ๋ฆฌ

hELLO ยท Designed By ์ •์ƒ์šฐ.
๊ฐœ๋ฐœ์ž HOON

๐Ÿ› HOON DEVLog

[Redis] M1 MacOS์—์„œ Docker Redis Cluster ์„ค์ •ํ•˜๊ธฐ + SpringBoot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํด๋Ÿฌ์Šคํ„ฐ ์—ฐ๊ฒฐํ•˜๊ธฐ
๐ŸŒฑ ๋ฐฑ์—”๋“œ : Backend

[Redis] M1 MacOS์—์„œ Docker Redis Cluster ์„ค์ •ํ•˜๊ธฐ + SpringBoot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํด๋Ÿฌ์Šคํ„ฐ ์—ฐ๊ฒฐํ•˜๊ธฐ

2024. 5. 11. 23:23

 

๐Ÿค” ๊ฐœ์š”

 

[Redis] Redis์˜ ๋ฐฑ์—…๊ณผ HA๋ฅผ ์œ„ํ•œ ์ „๋žต (RDB, AOF, Replication, Sentinel, Sharding, Cluster)

๐Ÿ0. ์„œ๋ก  ํŒ€ ํ”„๋กœ์ ํŠธ์—์„œ Redis๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€, ์‹ ๊ธฐํ•œ ํ˜„์ƒ์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค. ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋„์ปค๋ฅผ ํ†ตํ•ด ๋ ˆ๋””์Šค ์„œ๋ฒ„๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ์—ˆ๊ณ , JWT Refresh Token์„ ๋ ˆ๋””์Šค ์„œ๋ฒ„์— ์ €์žฅํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ๋„

hoons-dev.tistory.com

 

์ด์ „ ๊ธ€์„ ๋ณด๋ฉด, ๋ ˆ๋””์Šค์˜ ๋ฐฑ์—…๊ณผ ๊ณ ๊ฐ€์šฉ์„ฑ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ด์•ผ๊ธฐ๊ฐ€ ๋‹ด๊ฒจ์žˆ์Šต๋‹ˆ๋‹ค.

Redis์˜ ๊ณ ๊ฐ€์šฉ์„ฑ์„ ์œ„ํ•ด์„œ Cluster๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ค‘์—์„œ๋„ Docker Desktop for Mac์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ Redis-Cluster๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋„๋ก Docker-Compose ํŒŒ์ผ ๊ตฌ์„ฑ๊ณผ SpringBoot Application ์„ค์ •์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํด๋Ÿฌ์Šคํ„ฐ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์ด ๊ถ๊ธˆํ•˜๋‹ค๋ฉด, ์œ„์˜ ์ด์ „ ๊ธ€์„ ์ฐธ์กฐํ•ด์ฃผ์„ธ์š”.

 

๐Ÿ’œ Docker Compose ์„ธํŒ…

 

Docker์˜ ์–ด๋–ค ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋А๋ƒ๊ฐ€ ๊ต‰์žฅํžˆ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ Redis ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๊ณ , bitnami์˜ Redis-Cluster ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์…”๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์—์„œ๋Š” Docker Desktop for Mac์„ ์‚ฌ์šฉํ•˜๋ฉฐ(M1 MacOS) Docker ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ•˜๋ ค ํ•˜๊ธฐ ๋•Œ๋ฌธ์— arm64v8/redis ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์‹œ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

 

Linux ์„œ๋ฒ„ ๋“ฑ์—์„œ Cluster๋ฅผ ๊ตฌ์ถ•์„ ์‹œ๋„ํ•œ๋‹ค๋ฉด, bitnami/redis-cluster๋ฅผ ๊ฒ€์ƒ‰ํ•ด ๊ตฌํ˜„ํ•˜๋ฉด ํŽธํ•˜๊ฒŒ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์„๊ฒ๋‹ˆ๋‹ค.

 

Docker

 

hub.docker.com

 

โœ… docker-compose.yml

version: '3'

services:
  redis-master-1:
    container_name: redis-master-1
    image: arm64v8/redis:latest
    restart: always
    volumes:
      - ./redis-master-1.conf:/etc/redis-master-1.conf
    command:
      redis-server /etc/redis-master-1.conf
    ports:
      - "7001:7001"
      - "7002:7002"
      - "7003:7003"
      - "7004:7004"
      - "7005:7005"
      - "7006:7006"

  redis-master-2:
    container_name: redis-master-2
    image: arm64v8/redis:latest
    network_mode: "service:redis-master-1"
    restart: always
    volumes:
      - ./redis-master-2.conf:/etc/redis-master-2.conf
    command:
      redis-server /etc/redis-master-2.conf

  redis-master-3:
    container_name: redis-master-3
    image: arm64v8/redis:latest
    network_mode: "service:redis-master-1"
    restart: always
    volumes:
      - ./redis-master-3.conf:/etc/redis-master-3.conf
    command:
      redis-server /etc/redis-master-3.conf

  redis-replica-1:
    container_name: redis-replica-1
    image: arm64v8/redis:latest
    network_mode: "service:redis-master-1"
    restart: always
    volumes:
      - ./redis-replica-1.conf:/etc/redis-replica-1.conf
    command:
      redis-server /etc/redis-replica-1.conf

  redis-replica-2:
    container_name: redis-replica-2
    image: arm64v8/redis:latest
    network_mode: "service:redis-master-1"
    restart: always
    volumes:
      - ./redis-replica-2.conf:/etc/redis-replica-2.conf
    command:
      redis-server /etc/redis-replica-2.conf

  redis-replica-3:
    container_name: redis-replica-3
    image: arm64v8/redis:latest
    network_mode: "service:redis-master-1"
    restart: always
    volumes:
      - ./redis-replica-3.conf:/etc/redis-replica-3.conf
    command:
      redis-server /etc/redis-replica-3.conf

  redis_cluster_entry:
    image: arm64v8/redis:latest
    network_mode: "service:redis-master-1"
    container_name: redis_cluster_entry
    command: redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-yes
    depends_on:
      - redis-master-1
      - redis-master-2
      - redis-master-3
      - redis-replica-1
      - redis-replica-2
      - redis-replica-3

 

๋ ˆ๋””์Šค ํด๋Ÿฌ์Šคํ„ฐ์˜ ๊ตฌ์„ฑ์€ Master : Replica = 3 : 3์˜ ๋น„์œจ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€๋Š” ์‹ค๋ฆฌ์ฝ˜ ๋งฅ ํ”Œ๋žซํผ์„ ์ง€์›ํ•˜๋Š” arm64v8/redis์˜ latest ๋ฒ„์ „์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

network_mode๋Š” ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ redis-master-1์œผ๋กœ ์„ค์ •ํ•จ์œผ๋กœ์จ ๊ฐ™์€ ๋„คํŠธ์›Œํฌ๋ฅผ ๊ณต์œ ํ•˜๋„๋ก ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋…ธ๋“œ๋Š” ๋ณผ๋ฅจ ๋งˆ์šดํŠธ๋ฅผ ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, docker-compose.yml๊ณผ ๊ฐ™์€ ๋””๋ ‰ํ† ๋ฆฌ ์œ„์น˜์— 

- redis-master-1.conf ~ redis-master-3.conf
- redis-replica-1.conf ~ redis-replica-3.conf

์˜ ์„ค์ • ํŒŒ์ผ์ด ์กด์žฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์„ค์ • ํŒŒ์ผ ๋‚ด์—์„œ ํฌํŠธ ๋ฒˆํ˜ธ์™€, ๋น„๋ฐ€๋ฒˆํ˜ธ, AOF ๋ฐฑ์—… ๋ฐฉ์‹, enable cluster ์„ค์ •์„ ๋งˆ์น˜๊ณ  ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

 

defaultํ•œ config ํŒŒ์ผ์€ ์•„๋ž˜์˜ ๋งํฌ์—์„œ Redis์˜ ๋ฒ„์ „์— ๋งž๊ฒŒ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ•ด๋‹น ํŒŒ์ผ์—์„œ ๊ฐ’์„ ์ˆ˜์ •ํ•ด ์ €์žฅํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Redis์˜ ๋ฒ„์ „์ด ๋‹ค๋ฅธ config ํŒŒ์ผ์„ ๋ฐ›์•„ ์„ค์ •ํ•˜๋ฉด ์‹คํ–‰ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ์ƒ๊ธธ ์—ฌ์ง€๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ ๋งž์ถฐ์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

 

Redis configuration

Overview of redis.conf, the Redis configuration file

redis.io

 

default config ํŒŒ์ผ์˜ ๋‚ด๋ถ€, ์ฃผ์„์„ ํ’€์–ด ๊ฐ’์„ ์ˆ˜์ •ํ•˜๋Š” ์‹์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

์•„๋ž˜๋Š” ํด๋Ÿฌ์Šคํ„ฐ ๋…ธ๋“œ๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด config ํŒŒ์ผ์˜ ๋Œ€ํ‘œ์ ์œผ๋กœ ์ˆ˜์ •ํ•  ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

# ํ˜ธ์ŠคํŠธ ๋จธ์‹ ์—์„œ ๋ ˆ๋””์Šค๊ฐ€ ์ปค๋„ฅ์…˜์„ ๋ฐ›์•„๋“ค์ผ IP ์„ค์ •
# bind 192.168.1.100 10.0.0.1     # listens on two specific IPv4 addresses
# bind 127.0.0.1 ::1              # listens on loopback IPv4 and IPv6
# bind * -::*                     # like the default, all available interfaces
# ์•„๋ž˜๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.
bind 127.0.0.1

# ๋ ˆ๋””์Šค์˜ ํฌํŠธ ๋„˜๋ฒ„ ์„ค์ •
port 6379

# ๋ฐฑ์—… ๋ฐฉ์‹ AOF ๋ฐฉ์‹ ์„ค์ •
appendonly yes

# Normal Redis instances can't be part of a Redis Cluster; only nodes that are
# started as cluster nodes can. In order to start a Redis instance as a
# cluster node enable the cluster support uncommenting the following:
#
cluster-enabled yes

# Every cluster node has a cluster configuration file. This file is not
# intended to be edited by hand. It is created and updated by Redis nodes.
# Every Redis Cluster node requires a different cluster configuration file.
# Make sure that instances running in the same system do not have
# overlapping cluster configuration file names.
#
cluster-config-file nodes.conf

# Cluster node timeout is the amount of milliseconds a node must be unreachable
# for it to be considered in failure state.
# Most other internal time limits are a multiple of the node timeout.
#
cluster-node-timeout 3000

์œ„์™€ ๊ฐ™์€ ์ž‘์—…์„ ๊ฐ ๋…ธ๋“œ ๋งˆ๋‹ค ๋…ธ๋“œ์— ๋งž๋Š” ๊ฐ’์œผ๋กœ (๋งˆ์Šคํ„ฐ 3, ๋ ˆํ”Œ๋ฆฌ์นด 3 ๊ฐ ๋…ธ๋“œ์— ๋งž๋Š” ํฌํŠธ ๋ฒˆํ˜ธ) conf ํŒŒ์ผ์„ ๊ตฌ์„ฑํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

์ตœ์ข…์ ์œผ๋กœ redis-cluster-entry์—์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ํด๋Ÿฌ์Šคํ„ฐ ๊ตฌ์ถ•์„ ์™„๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-yes

 

๊ตฌ์ถ•์ด ์™„๋ฃŒ๋œ ํ›„, ์•„๋ž˜์™€ ๊ฐ™์ด ๋„์ปค ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ตฌ๋™๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์•„๋ž˜๋Š”, ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ์‚ฝ์ž…๋˜๋Š”์ง€ ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ, ๊ฐ„๋‹จํ•˜๊ฒŒ Medis GUI๋ฅผ ํ†ตํ•ด Connection์„ ๋งบ์Šต๋‹ˆ๋‹ค. ํ•˜๋‹จ์˜ Cluster ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ•ด์„œ MOVED ์—๋Ÿฌ๋ฅผ ํ›„์ฒ˜๋ฆฌ ํ•œ ํ›„ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ณด์—ฌ์ฃผ๋„๋ก ์„ธํŒ…ํ•ฉ๋‹ˆ๋‹ค.

 

 

๊ฐ’์ด ์ž˜ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

๐Ÿ’œ SpringBoot Application

 

์œ„์™€ ๊ฐ™์ด ๊ตฌ์„ฑํ•œ ๋ ˆ๋””์Šค ํด๋Ÿฌ์Šคํ„ฐ์™€ ์Šคํ”„๋ง ๋ถ€ํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์—ฐ๊ฒฐํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

โœ… build.gradle

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

 

โœ… application.yml

spring:
  data:
    redis:
      cluster:
        nodes:
          127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005,127.0.0.1:7006

 

โœ… RedisConfig.java

@Configuration
public class NEORedisConfig {

    private final String clusterNodes;

    public NEORedisConfig(@Value("${spring.data.redis.cluster.nodes}") final String clusterNodes) {
        this.clusterNodes = clusterNodes;
    }

    @Bean
    public RedisTemplate<?, ?> redisTemplate() {
        RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        return redisTemplate;
    }

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(Arrays.asList(clusterNodes.split(",")));
        return new LettuceConnectionFactory(clusterConfig);
    }

}

 

application.yml์—์„œ ์„ค์ •ํ•œ cluster์˜ ๋…ธ๋“œ๋“ค์„ @Value ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด cluterNodes ํ•„๋“œ์— ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ํ›„, ๊ฐ ๋…ธ๋“œ๋“ค์„ RedisClusterConfiguration ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด LettuceConnectionFactory์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์œผ๋กœ ๊ฐ„๋‹จํ•œ ์—ฐ๊ฒฐ ์„ค์ •์„ ๋งˆ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ €์ž‘์žํ‘œ์‹œ ๋น„์˜๋ฆฌ ๋ณ€๊ฒฝ๊ธˆ์ง€ (์ƒˆ์ฐฝ์—ด๋ฆผ)

'๐ŸŒฑ ๋ฐฑ์—”๋“œ : Backend' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[QueryDSL] QueryDSL-JPA : DTO Projection๊ณผ Transform  (1) 2024.04.26
[QueryDSL] QueryDSL-JPA : JOIN ํ•˜๊ธฐ  (0) 2024.04.25
[QueryDSL] QueryDSL-JPA : @ElementCollection VO์— ๋Œ€ํ•œ JOIN  (1) 2024.04.23
[Spring] Spring Security + OAuth2.0 + JWT Token์„ ํ™œ์šฉํ•œ ์†Œ์…œ๋กœ๊ทธ์ธ ์ด์ •๋ฆฌ - (1) ๋ฐฐ๊ฒฝ ์ง€์‹ ์ดํ•ดํ•˜๊ธฐ, ์ „์ฒด ๊ทธ๋ฆผ ์‚ดํŽด๋ณด๊ธฐ  (0) 2023.09.22
[Spring] API ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ Swagger ๋„์ž…ํ•˜๊ธฐ (gradle ๊ธฐ์ค€)  (0) 2023.03.24
    '๐ŸŒฑ ๋ฐฑ์—”๋“œ : Backend' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
    • [QueryDSL] QueryDSL-JPA : DTO Projection๊ณผ Transform
    • [QueryDSL] QueryDSL-JPA : JOIN ํ•˜๊ธฐ
    • [QueryDSL] QueryDSL-JPA : @ElementCollection VO์— ๋Œ€ํ•œ JOIN
    • [Spring] Spring Security + OAuth2.0 + JWT Token์„ ํ™œ์šฉํ•œ ์†Œ์…œ๋กœ๊ทธ์ธ ์ด์ •๋ฆฌ - (1) ๋ฐฐ๊ฒฝ ์ง€์‹ ์ดํ•ดํ•˜๊ธฐ, ์ „์ฒด ๊ทธ๋ฆผ ์‚ดํŽด๋ณด๊ธฐ
    ๊ฐœ๋ฐœ์ž HOON
    ๊ฐœ๋ฐœ์ž HOON
    ์ข‹์€ ๋ฐฑ์—”๋“œ ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๋˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ก์„ ๋ชจ์•˜์Šต๋‹ˆ๋‹ค. # ์ฃผ๋‹ˆ์–ด # ๋ฐฑ์—”๋“œ # ๊ฐœ๋ฐœ์ž

    ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”