Cold Sequence

구독 할 때마다 타임라인이 새로 생성됨

구독하는 시점과 상관없이 첫번째로 emit 된 데이터부터 읽을 수 있음

ex) Flux.fromIterable(Array.asList("A", "B", "C")

subscribe(data -> Logger.info("data : {}", data) // ABC

subscribe(data -> Logger.info("data : {}", data) // ABC

 

 

Hot Sequence

타임라인이 하나만 존재

구독하는 시점에 따라 구독 시점 이후로 emit 된 데이터만 읽을 수 있음

ex) Flux.fromStream(Stream.of("A", "B", "C").delayElements(Duration.ofSeconds(1)).share()

subscribe(data -> Logger.info("data : {}", data) // A B

TimeUtils.sleep(2000)

subscribe(data -> Logger.info("data : {}", data) // C

* share() : cold 시퀀스를 hot 시퀀스로 변환해줌

반응형

'back > Reactive Java' 카테고리의 다른 글

Reactive 란?  (1) 2023.10.16

Reactive System 설계 원칙

아래 네가지 원칙을 잘 반영한 시스템

 

Responsive : 응답성 즉각적인 응답

Resilient : 회복성 장애시 회복성

Elastic : 탄력성 작업량 변화에도 응답성을 유지하는 것

Message Driven : 비동기(async) 메시지 주고받아 느슨한 결합(loose coupling), 위치 투명성(location transparency) 보장

 

 

Reactive programming 특징

1) 데이터 소스에 변경이 있을때마다 데이터를 전파 - publisher 데이터 전파, subscriber 전파된 데이터를 받아서 처리

2) 선언형 프로그래밍 패러다임 : 실행할 동작을 구체적으로 명시하지 않고 목표만 정의 

3) 함수형 프로그래밍 기법 사용

 

 

명령형 프로그래밍 vs 선언형 프로그래밍

명령형 프로그래밍

List<Integer> numbers = Arrays.asList(1,3,21,10,8);
int sum = 0;

for (int number: numbers) {
 if (number > 6 && (number % 2 != 0)) {
   sum += number;
 }
}

선언형 프로그래밍

List<Integer> numbers = Arrays.asList(1,3,21,10,8);

int sum = numbers.stream()
	.filter(number -> number > 6 && number%2!=0)
	.mapToInt(number -> number)
	.sum();

 

Reactive Streams 란?

리액티브 프로그래밍을 표준화 한 명세

https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.3/README.md#specification

 

reactive streams 4가지 인터페이스

1) Publisher : 데이터 통제

2) Subscriber : 퍼블리셔가 통제한 데이터를 구독하는 구독자

3) Subscription : 구독 자체를 정의

4) Process : Publisher & Subsriber 역할을 동시에 할 수 있는 인터페이스

 

 

Reactive Streams 구현체

1) RxJava

2) Java 9 Flow API

3) Akka Streams

4) Reactor

5) RxJS, RxScala, RxAndroid 등..

 

 

참고 :

reactivemanifesto.org

반응형

'back > Reactive Java' 카테고리의 다른 글

cold vs hot sequence  (1) 2023.11.06

Intellij Syntax highlighting has been temporarily turned off 에러 발생시

Bean 주입받는 모든 곳에서 import 에러 발생

File > Repair IDE 클릭 > 문제가 해결될 때 까지 Fix Next Step

 

출처 :

https://github.com/kotest/kotest-intellij-plugin/issues/168

 

반응형

서킷브레이커(CircuitBreaker)란

서킷브레이커 패턴이란 외부 서비스에 의한 문제를 방지하기 위해 등장한 디자인 패턴으로 문제가 발생한 지점을 감지하고 실패하는 요청을 계속하지 않도록 방지합니다.
그리고 이를 통해 시스템의 장애 확산을 막고 장애 복구를 도와주며 유저는 불필요하게 대기하지 않게 됩니다.
가정집에 있는 누전차단기가 화재를 막는 것과 비슷하게 CircuitBreaker(직역하면 회로차단기)는 서비스의 장애 전파를 막는다고 이해하면 됩니다.

아래 그림과 같이 ServiceA가 ServiceB를 호출 할 때
ServiceB가 반복적으로 실패한다면 CircuitBreaker 를 Open 하여 ServiceB에 대한 흐름을 차단하는게 서킷브레이커의 역할입니다.
* CircuitBreaker 의 Open 은 흐름을 차단하는 것으로, 흐름을 열어둔다(opened) 라는 의미가 아닙니다.
* 
반대로 CircuitBreaker 의 Closed 상태는 흐름을 허용하는 정상상태를 의미합니다.

이미지 출처 : https://symphony.is/blog/service-resiliency-with-spring-boot-and-resilience4j


"CircuitBreaker 가 무엇인지 그리고 어떤 역할을 하는지 알았으니, 이제 CircuitBreaker의 상태인 Closed/Open/Half Open에 대해 좀 더 알아보겠습니다."

 

서킷브레이커의 3가지 상태

  Closed Open HalfOpen
상황 정상 장애 Open 상태가 되고 일정 요청 횟수/시간이 지난 상황.
Open 으로 상태를 변경할지, Closed 로 상태를 변경할지에 대한 판단이 이루어지는 상황
요청에 대한 처리 요청에 대한 처리 수행.
정해진 횟수만큼 실패할 경우 Open 상태로 변경
외부 요청을 차단하고 에러를 뱉거나 지정한 callback 메소드를 호출 요청에 대한 처리를 수행하고 실패시 CircuitBreaker 를 Open 상태로 변경.
성공시 CircuitBreaker를 Close 상태로 변경

* 서킷브레이커에서 장애판단의 기준(Closed 상태에서 Open 이 되기 위해 카운팅 되는 실패의 기준)은 아래와 같습니다.

1) slow call : 기준보다 오래 걸린 요청

2) failure call : 실패하거나 오류 응답을 받은 요청

* slow call 과 failure call 은 CircuitBreaker의 프로퍼티로 정의되어 있으며 사용자가 특정 값으로 지정할 수 있습니다.

 

"아래는 CircuitBreaker 의 3가지 상태에 대해 이해를 돕기 위한 순서도와 그림입니다."

서킷브레이커 상태 변경

이미지 출처 : https://martinfowler.com/bliki/CircuitBreaker.html

서킷브레이커의 상태는 아래와 같이 변경됩니다.

1. 정상 요청 수행(Closed)

2. 실패 임계치 도달(Closed → Open)

3. 일정시간 소요(Open → Half Open)

4. 요청 수행

     a. 수행 결과 정상 (Half Open → Closed)

     b. 수행 결과 실패 (Half Open → Open) 

 

서킷브레이커 라이브러리 종류

1) Netflix Hystrix

넷플릭스에서 개발한 라이브러리로 MSA 환경에서 분산된 서비스간 통신이 원할하지 않을 경우 각 서비스가 장애 내성과 지연 내성을 갖게하도록 하는 라이브러리
현재는 deprecated 된 상태로 Resilience4j 사용을 권장

 

2) Resilience4j

Netflix Hystrix 로부터 영감을 받아 개발된 Fault Tolerance Library 
Java 전용으로 개발된 경량화된 라이브러리

 

"Netflix Hystrix 공식 doc에서도 Resilience4j 사용을 권장하고 있으니, Hystrix 를 사용할 이유가 없습니다.

Hystrix 에 대해 알아볼 필요 없이 바로 Resilence4j 에 대해 알아보겠습니다."

 

Resilience4j 의 코어 모듈

1) CircuitBreaker : 장애 전파 방지 기능 제공

2) Retry : 요청 실패시 재시도 처리 기능 제공

3) RateLimiter : 제한치를 넘어서 요청을 거부하거나 Queue 생성하여 처리하는 기능 제공

4) TimeLimiter : 실행 시간 제한 설정 기능 제공

5) Bulkhead : 동시 실행 횟수 제한 기능 제공

6) Cache : 결과 캐싱 기능 제공

 

Resilience4j 의 코어 모듈은 위와 같으며 필요한 모듈의 의존성을 설정해 주어 필요한 모듈만 사용할 수 있습니다.

 

Gradle 예시

 
dependencies {
  implementation("io.github.resilience4j:resilience4j-circuitbreaker:${resilience4jVersion}")
  implementation("io.github.resilience4j:resilience4j-ratelimiter:${resilience4jVersion}")
  implementation("io.github.resilience4j:resilience4j-retry:${resilience4jVersion}")
  implementation("io.github.resilience4j:resilience4j-bulkhead:${resilience4jVersion}")
  implementation("io.github.resilience4j:resilience4j-cache:${resilience4jVersion}")
  implementation("io.github.resilience4j:resilience4j-timelimiter:${resilience4jVersion}")
}

Resilience4j 모듈의 우선순위

Retry ( CircuitBreaker ( RateLimiter ( TimeLimiter ( BulkHead ( TargetFunction ) ) ) ) )

위와 같은 우선순위로 모듈이 적용됩니다. (Retry 모듈이 가장 마지막에 적용됨)

 

이를 알아보기 위해 resilience4j jar의 CircuitBreakerConfigurationProperties, RetryConfigurationProperties 클래스 내부를 살펴보면, 

CircuitBreaker 와 Retry 의 Order 값이 각각 -3, -4 로

별도 처리가 없을 경우 CircuitBreaker 가 Retry 보다 우선으로 적용됨을 알 수 있습니다.

 

CircuitBreakerConfigurationProperties

 
public class CircuitBreakerConfigurationProperties extends
    io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigurationProperties {

    private int circuitBreakerAspectOrder = Ordered.LOWEST_PRECEDENCE - 3;
    ...
}

RetryConfigurationProperties

 
public class RetryConfigurationProperties extends
    io.github.resilience4j.common.retry.configuration.RetryConfigurationProperties {

    private int retryAspectOrder = Ordered.LOWEST_PRECEDENCE - 4;
    ...
}

CircuitBreakerAspect 

 
@Aspect
public class CircuitBreakerAspect implements Ordered {
   ...
   @Override
    public int getOrder() {
        return circuitBreakerProperties.getCircuitBreakerAspectOrder();
    }
}

AOP 기반하에 동작하므로 우선순위를 바꿔서 적용하고자 할 경우 annotation 방식을 사용하여 layer 를 분리하거나 aspectOrder 속성값을 수정하여 적용할 수 있습니다.

 

Resilience4j Configuration

Resilience4j 의 Configuration 은 yml 파일을 사용하거나, java 코드를 통해 설정할 수 있습니다.

1) yml 파일을 사용한 Config 예시

 
resilience4j.circuitbreaker:
    configs:
        default:
            slidingWindowSize: 100
            waitDurationInOpenState: 10000
            permittedNumberOfCallsInHalfOpenState: 30
            failureRateThreshold: 60
            eventConsumerBufferSize: 10
        custom:
            slidingWindowSize: 50
            permittedNumberOfCallsInHalfOpenState: 10
            ... 생략

2) Java 코드를 통한 Config 예시

 
@Configuration
class CircuitBreakerProvider(
    val circuitBreakerRegistry: CircuitBreakerRegistry,
) {

    companion object {
        const val CIRCUIT_MEMDB: String = "CB_MEMDB"
    }

    @Bean
    fun memDBCircuitBreaker(): CircuitBreaker {
        return circuitBreakerRegistry.circuitBreaker(            
            CIRCUIT_MEMDB, CircuitBreakerConfig.custom()
                .failureRateThreshold(10F)  // 실패비율 10% 이상시 서킷 오픈
                .slowCallDurationThreshold(Duration.ofMillis(500))  // 500ms 이상 소요시 실패로 간주
                .slowCallRateThreshold(10F) // slowCallDurationThreshold 초과 비율이 10% 이상시 서킷 오픈
                .waitDurationInOpenState(Duration.ofMillis(60000))   // OPEN -> HALF-OPEN 전환 전 기다리는 시간
                .minimumNumberOfCalls(5) // 집계에 필요한 최소 호출 수
                .slidingWindowSize(5)    // 서킷 CLOSE 상태에서 5회 호출 도달시 failureRateThreshold 실패비율 계산
                .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED)    // 호출 횟수 기준 계산 (TIME_BASED는 시간 기준)
                .ignoreExceptions(StockManageException::class.java)   // 화이트리스트로 서킷 오픈 기준 ex 관리
                .build()
        )
    }

 

"Resilience4j 모듈 중 가장 많이 사용되는 CircuitBreaker, Retry 모듈의 속성값에 대해 간단히 알아보겠습니다."

Resilience4j CircuitBreaker Property

property설명
failureRateThreshold 실패비율 임계치를 백분율로 설정 해당 값을 넘어갈 시 Circuit Breaker 는 Open상태로 전환되며, 이때부터 호출을 차단한다 (기본값: 50)
slowCallRateThreshold 임계값을 백분율로 설정, CircuitBreaker는 호출에 걸리는 시간이 slowCallDurationThreshold보다 길면 느린 호출로 간주, 해당 값을 넘어갈 시 Circuit Breaker 는 Open상태로 전환되며, 이때부터 호출을 차단한다 (기본값: 100)
slowCallDurationThreshold 호출에 소요되는 시간이 설정한 임계치보다 길면 느린 호출로 계산한다. -> 응답시간이 느린것으로 판단할 기준 시간 (60초, 1000 ms = 1 sec) (기본값: 60000[ms])
permittedNumberOfCallsInHalfOpenState HALF_OPEN 상태일 때, OPEN/CLOSE 여부를 판단하기 위해 허용할 호출 횟수를 설정 수 (기본값: 10)
maxWaitDurationInHalfOpenState HALF_OPEN 상태로 있을 수 있는 최대 시간이다. 0일 때 허용 횟수 만큼 호출을 모두 완료할 때까지 HALF_OEPN 상태로 무한정 기다린다. (기본값: 0)
slidingWindowType sliding window 타입을 결정한다. COUNT_BASED인 경우 slidingWindowSize만큼의 마지막 call들이 기록되고 집계됩니다.
TIME_BASED인 경우 마지막 slidingWindowSize초 동안의 call들이 기록되고 집계됩니다. (기본값: COUNT_BASED)
slidingWindowSize CLOSED 상태에서 집계되는 슬라이딩 윈도우 크기를 설정한다. (기본값: 100)
minimumNumberOfCalls minimumNumberOfCalls 이상의 요청이 있을 때부터 faiure/slowCall rate를 계산한다. 예를들어, 해당값이 10이라면 최소한 호출을 10번을 기록해야 실패 비율을 계산할 수 있다.
기록한 호출 횟수가 9번뿐이라면 9번 모두 실패했더라도 circuitbreaker는 열리지 않는다. (기본값: 100)
waitDurationInOpenState OPEN에서 HALF_OPEN 상태로 전환하기 전 기다리는 시간 (60초, 1000 ms = 1 sec) (기본값: 60000[ms])
recordExceptions 실패로 기록할 Exception 리스트 (기본값: empty)
ignoreExceptions 실패나 성공으로 기록하지 않을 Exception 리스트 (기본값: empty)
ignoreException 기록하지 않을 Exception을 판단하는 Predicate<Throwable>을 설정 (커스터마이징, 기본값: throwable -> true)
recordFailure 어떠한 경우에 Failure Count를 증가시킬지 Predicate를 정의해 CircuitBreaker에 대한 Exception Handler를 재정의하는 것이다. true를 return할 경우, failure count를 증가시키게 된다 (기본값: false)

 

Resilience4j Retry Property

property설명
maxRetryAttempts 최대 재시도 수(최초 호출도 포함, 기본값 3)
waitDuration 재시도 할 때마다 기다리는 고정시간 (1초[1000ms], 기본값: 0.5초[500ms])
retryOnResultPredicate 반환되는 결과에 따라서 retry를 할지 말지 결정하는 filter, true로 반환하면 retry하고 false로 반환하면 retry 하지 않습니다. (기본값: (numOfAttempts,Either<throwable, result) -> waitDuration)
retryExceptionPredicate 예외(Exception)에 따라 재시도 여부를를 결정하기 위한 filter, 만약 예외에 따라 재시도해야 한다면 true를, 그 외엔 false를 리턴해야 한다. (기본값: result -> false)
retryExceptions 실패로 기록되는 블랙리스트 예외. empty일 경우 모든 에러 클래스를 재시도 한다. (기본값: empty)
ignoreExceptions 무시되어야 하는 예외(화이트리스트) 즉, 재시도 되지 않아야 할 에러 클래스 리스트이다. (기본값: empty)
failAfterMaxRetries 설정한 maxAttempts 만틈 재시도하고 나서도 결과가 여전히 retryOnResultPredicate를 통과하지 못했을 때 MaxRetriesExceededException 발생을 활성화/비활성화하는 boolean (기본값: false)

 

* 그외 모듈에 대한 속성값이 궁금하시다면 아래의 Resilience4j 공식 document 를 참고해주세요.

 

 

 

참고 : 

https://resilience4j.readme.io/docs/getting-started

 

반응형

 

아래 쿼리를 DBeaver 에 복붙시 따옴표 자동 제거하기

@NamedNativeQuery(
    name = "example",
    query = "   SELECT EX_CD AS exampleCd" +
            "     FROM EXAMPLE",
    resultSetMapping = "example"
)

 

DBeaver -> 윈도우 -> 설정 -> 편집기 -> SQL 편집기 -> Auto format -> Extract SQL from source code 활성화

아래와 같이 문자열 (" 포함) 을 복사후, 

"   SELECT EX_CD AS exampleCd" +
"     FROM EXAMPLE",

 

DBeaver 에 붙여넣기 할 경우  Auto format 되어 SQL 만 추출됨

SELECT EX_CD AS exampleCd
FROM EXAMPLE

 

 

 

 

반응형

'etc.' 카테고리의 다른 글

Slack reminder 푸시 설정  (0) 2023.04.07
[IDE] IntelliJ 단축키  (0) 2022.07.11
티스토리 소스코드 넣기  (0) 2019.02.12

/remind [수신자or채널] [메시지] [알림시간] 

eg) /remind #스쿼드채널 데일리미팅 at 10:00am every weekday

/remind list : 리마인드 목록 확인

 

https://slack.com/intl/ko-kr/resources/using-slack/how-to-use-reminders-in-slack

https://slack.com/intl/ko-kr/help/articles/208423427-%EB%A6%AC%EB%A7%88%EC%9D%B8%EB%8D%94-%EC%84%A4%EC%A0%95

 

반응형

'etc.' 카테고리의 다른 글

[etc.] nativeQuery 복붙할 때 따옴표(") 제거하기  (0) 2023.04.19
[IDE] IntelliJ 단축키  (0) 2022.07.11
티스토리 소스코드 넣기  (0) 2019.02.12

옮길 모니터 하단(모니터 제일 아래 최하단 끝에 닿게)에 마우스를 놓고 

스크롤 아래로 내리면 해당 모니터로 Dock 옮겨진다.

반응형

Amazon MemoryDB for Redis 는 OpenSource 인 Redis 를 Amazon 클라우드 컴퓨팅 자원을 사용해 AWS 에서 지원하는 것으로, Redis 와 거의 모든 면에서 동일합니다.

다만 AWS Redis 를 사용할 경우, Redis 서버를 직접 구축하는 것 보다 Performance와 Durability 면에서 이점을 가지며, 설정이 편리한 장점이 있습니다.

이 글에선 Redis의 Persistence(영속성)/Durability(내구성) 측면을 중점적으로 다뤄보겠습니다.

 

[ Redis RDB vs AOF  ] 

메모리는 휘발성이므로 memory DB 인 Redis 프로세스를 종료하게 되면 데이터가 모두 유실됩니다.

따라서 단순 캐시용도가 아닌 Persistence 한 DB로 활용하기 위해서는 데이터를 Disk 에 저장하여 데이터 유실이 발생하지 않도록 해야합니다.

이를 위해 Redis 엔 RDB(snapshot) 와 AOF(Append Only File) 기능이 존재합니다.

 

1. RDB

  • RDB 는 memory snapshot 파일의 확장자인 .rdb 를 의미
  • 특정 시점/간격 마다 메모리의 전체 데이터를 디스크에 바이너리 파일로 저장(snapshot)하는 방식
  • 특정 시점마다 백업을 받을 때 사용
  • AOF 파일보다 사이즈가 작다는 특징이 있고 사이즈가 작으므로 로딩 속도도 AOF 보다 빠른 장점이 있습니다.
  • RDB 관련주요 redis.conf 파라미터
dbfilename $rdbTargetFileName RDB 파일명 지정 
save $duration $cnt  특정시간(duration)동안 특정횟수(cnt) 이상 key 변경이 발생하면 저장 (eg: save 300 10 : 300초 동안 10번 이상 key 변경 발생시 저장)
stop-writes-on-bgsave-error $yesOrNo RDB 파일을 디스크에 저장하다 실패하면 save 이벤트를 거부할지에 대한 파라미터(yes 일 경우 RDB 저장 실패시 쓰기 요청 거부)
rdbcompression $yesOrNo RDB 파일을 쓸 때 압축 여부
  • RDB 방식의 문제점
    Redis 장애 발생시 .rdb 백업 시점 이후에 발생한 데이터는 유실됨
# .rdb 데이터 유실 예시
> SET key val
> SET key1 val1
> SAVE
> SET key val2 #SAVE 이후로 데이터 유실
> SET key1 val3 #SAVE 이후로 데이터 유실

 

2. AOF

  • Append Only File 이라는 의미에서 알 수 있듯이 .aof 파일에 모든 쓰기 명령을 기록 (조회는 제외)
  • redis client 가 redis 에 쓰기 명령을 요청하면 Redis 는 해당 명령을 .aof 파일(디스크)에 저장한 후, 해당 명령을 수행하는 방식으로 RDB 방식과 달리 특정 시점이 아닌 항상 현재 시점까지의 로그를 기록
  • CUD 를 계속 append 하며 기록하게 되므로 파일 크기가 계속 커지게 되는데, Rewrite 를 하게 되면 최종 데이터만 기록되어 파일 크기가 작아진다
# 기존 appendonly.aof 파일 예시
SET key value
SET key value2
SET key value3
SET key value4

# AOF REWRITE 실행 후 appendonly.aof 파일
SET key value4 # 최종 데이터인 key value4 만 남게된다

 

  • AOF 관련 주요 redis.conf 파라미터
appendfilename $aofTargetFileName  AOF 파일명 지정
appendfsync $everysec  AOF 기록되는 시점 지정
  • always : 모든 명령 시행마다 기록
  • everysec : 1초마다 AOF 에 기록(권장)
  • no : 기록 시점을 OS 가 저장
auto-aof-rewrite-min-size $size  AOF 파일 사이즈가 64mb 이하면 rewrite 를 하지 않음(rewrite 를 자주 하는 것을 방지)
auto-aof-rewrite-percentage $percentage AOF 파일 사이즈가 rewrite 되는 파일 사이즈 기준으로, redis 서버가 시작할 시점의 AOF 파일 사이즈를 기준으로 함 (만약 redis 서버 시작시 AOF 파일 사이즈가 0 이라면 rewrite를 하지 않음)

 

  • AOF 를 사용한 복구 예시 
    .aof 파일에서 문제가 되는 명령어를 수정/제거한 후 redis 서버를 재시작하면 데이터 손실없이 DB를 살릴 수 있다
# .aof 를 사용한 복구 예시
*1
$8
flushall #문제가 되는 해당 명령어 삭제 후 저장
  • AOF 방식의 문제점
    모든 쓰기 기록이 남아있는 파일이므로 RDB 방식에 비해 백업 데이터 크기가 크고, 모든 라인이 한 줄 씩 재수행 되므로 서버자원을 많이 사용

 

[ RDB vs AOF 무엇을 써야하는가? ]

특정 시점을 기준으로 메모리 DB의 데이터를 백업하는 snapshot 방식의 RDB 방식과

조회 명령을 제외한 모든 쓰기 명령을 기록하는 AOF 방식은

각각의 장단점이 명확하므로 AOF 를 default로 사용하고 RDB 를 optional로 사용하는 방식으로 둘을 조합하여 사용합니다.

→ 서버가 실행될 때 백업된 .rdb 를 reload 하여 복구하고, snapshot 시점과 shutdown 사이의 데이터만 AOF 로그로 복구하여 서버 재기동 시간과 서버자원을 절약


그렇다면 RDB 와 AOF 방식을 통해 memory DB 인 Redis 를 Persistence 하게 사용 할 수 있을까요?

모든 쓰기 명령을 로그로 기록하는 AOF 방식도 아래와 같은 데이터 손실 가능성이 있다고 합니다.

아래는 AWS memoryDB 관련 가이드 발췌 글입니다. (출처: https://aws.amazon.com/ko/memorydb/faqs/)

How is MemoryDB’s durability functionality different from open source Redis’ append-only file (AOF)?
MemoryDB leverages a distributed transactional log to durably store data. By storing data across multiple AZs, MemoryDB has fast database recovery and restart. Also, MemoryDB offers eventual consistency for replica nodes and consistent reads on primary nodes.
Open source Redis includes an optional append-only file (AOF) feature, which persists data in a file on a primary node’s disk for durability. However, because AOF stores data locally on primary nodes in a single availability zone, there are risks for data loss. Also, in the event of a node failure, there are risks of consistency issues with replicas.

How does MemoryDB durably store my data?
MemoryDB stores your entire data set in memory and uses a distributed Multi-AZ transactional log to provide data durability, consistency, and recoverability. By storing data across multiple AZs, MemoryDB has fast database recovery and restart. By also storing the data in-memory, MemoryDB can deliver ultra-fast performance and high throughput.

위 글에서 알 수 있듯이 Redis AOF는 .aof 파일을 마스터 노드 디스크(싱글 AZ라 할 수 있는)에만 저장하여 데이터 loss risk가 있으며 노드 장애시 슬레이브 노드와 데이터 일관성 문제가 있을 수 있다고 합니다.

AWS memoryDB for Redis 는 모든 메모리 데이터를 분산된 multi AZ 에 transaction log 로 기록하여 durability 와 마스터 노드 ↔ 슬레이브 노드간의 데이터 일관성을 보장한다고 합니다.

 

아래는 Redis 와 AWS MemoryDB for Redis 의 차이를 정리한 차트입니다.

 

RedisAWS MemoryDB for RedisRedisAWS MemoryDB for Redis 
내구성(Durability) AOF, RDB 로 내구성 처리 Transaction log 까지 작성 후 응답하여 데이터 무손실 가능
성능 12만/sec read : 마이크로초
write : ms (한자리 milisecond)
Cluster mode Cluster mode 선택적 운영 Cluster mode 활성화 필수
접속 redis-cli 사용하여 접속
백업 특정 시점 RDB 백업
AOF 로 모든 CUD DML 저장
24시간 동안 20개 까지 스냅샷 생성 제한
해당 Region 에서 수동 스냅샷 보유 개수 제한 없음
복구 RDB 시점 복원
AOF 사용시 원하는 명령까지 복원
RDB 스냅샷 복원
특점시점 복원은 불가
Transaction log 사용하여 장애 최종 복구 가능
고가용성(HA) replica
shard 구성
replica node 의 복제가 실패할 경우
  • 실패 노드를 감지하여 오프라인 전환 및 동일 AZ에 교체노드 실행하여 동기화 진행
MemoryDB MultiAZ primary 장애
  • MemoryDB 에서 Primary 오류 감지하면, replica node들 중 primary 정합성 체크 후 primary 승격 후 다른 AZ에 있는 primary spin up 이후 동기화 진행
복제 replica 구성
  • async 복제
    • rdb로 먼저 전체 복제
    • 복제 버퍼 내용 복제
transaction lop 를 사용하는 async 복제
transaction log 에 저장(영구저장) 하므로 데이터 손실 위험 없음

 

참고 :

https://redis.io/docs/management/persistence/

https://docs.aws.amazon.com/memorydb/latest/devguide/what-is-memorydb-for-redis.html

https://aws.amazon.com/ko/memorydb/faqs/

https://hyunki1019.tistory.com/169

https://rmcodestar.github.io/redis/2018/12/10/redis-persistence/

https://www.youtube.com/watch?v=Jbq_XZMZEKY

반응형

'infra & cloud > AWS' 카테고리의 다른 글

[AWS] EC2 ssh 접속 및 bastion rsa 설정  (0) 2022.12.01
[AWS] VPC 구성  (0) 2022.12.01
[SSH] RSA 공유키 충돌 문제  (0) 2022.12.01
[AWS] SSO : Single Sign-On  (0) 2022.05.26
[AWS] 20-4. Resource Access Manager  (0) 2022.05.26

[ Login Shell vs Non-login Shell ]

Login Shell : 계정/암호를 입력하여 Shell 실행하는 것. ex) ssh 로그인 / GUI에서 로그인

Non-login Shell : 로그인 없이 실행되는 Shell. ex) ssh 접속 후 bash 를 다시 실행하는 경우, GUI에서 터미널을 띄운 경우 sudo su 로 계정 변경하는 경우

 

[ 파일 로드 순서 ]

1. /etc/profile

: /etc/profile.d 디렉토리 안의 모든 쉘 스크립트 실행시킴. /etc/profile.d 엔 vim, qt, lang 등 다양한 설정이 sh 파일 형태로 존재. 쉘에 로그인하면 일단 이 sh 파일을 모두 실행시키는 것.

2. ~/.bash_profile or ~/.profile

: 계정 디렉토리에 있는 .bash_profile or .profile 로드. 이 파일들은 계정에 종속적이기 때문에 계정 디렉토리에 존재하므로 ~/.bash_profile or ~/.profile 파일을 로드하게 되는 것. PATH 같은 환경변수를 설정할 때 이 파일을 수정하는 이유가 여기에 있다.

3. ~/.bashrc

: 계정 디렉토리에 있는 .bashrc 파일 로드. 이 파일은 로그인과 상관없이 bash 콘솔을 새롭게 열 때 실행됨. 파일 안에는 아래와 같은 구문이 있는데, /etc/bashrc 파일을 실행하라는 뜻.

if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

4. /etc/bashrc

마지막으로 /etc/bashrc 파일 실행. 이 파일도 /etc/profile 과 마찬가지로 계정과 상관없이 전역적으로 영향을 미침.

 

[ /etc/profile , /etc/bashrc ]

이 파일들은 계정과 상관없이 전역적 설정

 

[ ~/.profile, ~/.bashrc ]

계정 디렉터리로 가면 .bashrc와 .bash_profile or .profile이라는 2개이 파일이 있다.

.bash_profile이란 bash로 로그인 할 때만 로드된다.

반면 .profile은 bash와 상관없이 로그인 하면 로드된다.

두 개 중 하나만 로드되며 bash로 로그인하면 .bash_profile만, bash 외 쉘로 로그인하면 .profile만 로드된다.

이 파일들은 공통적으로 환경변수를 세팅할 때 사용하고, 차이점은 실행되는 시점이 다르다는 것이다

 

1) .profile : 로그인 되는 시점에 실행 (Login Shell). bash와 상관 없는 것들을 넣는다.
2) .bash_profile : Bash로 로그인 되는 시점에 실행 (Login Shell).
3) .bashrc : 새로운 콘솔을 열 때 실행 (Non-login Shell). 로그인 없이 Bash가 실행될 때 로드된다. bash 쉘이 아닌 경우 각 쉘에 맞는 cshrc, tcshrc, kshrc 파일 등이 동일한 역할을 한다.

 

 

[ 환경변수 설정 ]

전역 파일 설정 :

환경설정은 /etc/profile에, 기타 함수나 alias 설정은 /etc/bashrc에..

 

/etc/profile : 

# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc

/etc/bashrc :

# System wide functions and aliases
# Environment stuff goes in /etc/profile

 

[ 사용자 계정 파일 설정 ]

사용자 디렉터리에 있는 .bash_profile 또는 .profile  .bashrc 가 위의 전역 파일들에 대응된다고 볼 수 있다. 다만 로드 순서는 전역 파일이 먼저고 사용자 파일이 그 다음이다. 두 파일에서 중복되지 않는 내용들은 둘 다 적용된다고 볼 수 있다. 하지만 만약 내용이 중복된다면 사용자 계정 파일의 내용이 우선된다.

 

가급적 사용자 계정 디렉터리에 있는 환경설정 파일을 수정하고, 전역 설정을 변경해야 하는 경우에도 직접 전역 파일을 건드리지 말고 사용자 계정의 환경설정 파일 내에서 연속성을 유지할 수 있도록 수정해야 한다.

ex)  PATH를 수정해야 하는 상황에 놓였을 때, /etc/profile 를 직접 수정하는 것이 아니라 ~/.profile을 아래와 같이 전역 설정을 기반으로 연속적으로 수정한다.

/etc/profile

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

~/.profile

PATH="$PATH:/usr/home/test"

 

 

https://projooni.tistory.com/entry/bashrc-%EC%99%80-profile-%EC%B0%A8%EC%9D%B4%EC%99%80-%EC%9E%91%EB%8F%99%EC%9B%90%EB%A6%AC

 

반응형

1. aws 에서 생성한 키페어를 사용하여 외부 접근이 허용된 서버 (ex: 0.0.0.0/0 에 대한 인바운드 허용 Security Group 사용중인 bastion 서버) 에 접속

ssh -i key.pem ubuntu@bastion서버publicIP

 

2. aws 에서 생성한 키페어 를 home 디렉토리에 key.pem 생성

sudo vi key.pem

 

3. bastion 서버에서 내부망 서버 접속

ssh -i key.pem ubuntu@내부망ip

 

[ 보다 쉽게 접속을 위한 ssh rsa 공유키/개인키 설정하기 ]

1) bastion 서버에서 공개키 생성

ssh-keygen -t rsa

2) bastion 에서 접속할 내부망 서버에 접속하여 공개키 추가 (공백 라인 추가 후 1)번의 bastion 서버 공개키 붙여넣기)

vi ~/.ssh/authorized_keys

3) 접속

ssh ubuntu@내부망서버IP

※ bastion 서버 /etc/hosts 에 내부망서버IP 를 등록 후 alias 사용하여 접속 가능

vi /etc/hosts
192.168.52.129 db

설정 후 접속

ssh db

 

 

https://johncom.tistory.com/42

 

 

반응형

'infra & cloud > AWS' 카테고리의 다른 글

AWS MemoryDB for Redis 영속성과 내구성  (0) 2023.03.31
[AWS] VPC 구성  (0) 2022.12.01
[SSH] RSA 공유키 충돌 문제  (0) 2022.12.01
[AWS] SSO : Single Sign-On  (0) 2022.05.26
[AWS] 20-4. Resource Access Manager  (0) 2022.05.26

+ Recent posts