Victoree's Blog

Redis의 동시성 프로그래밍 본문

Python/3rd-Party

Redis의 동시성 프로그래밍

victoree 2023. 6. 21. 00:40
728x90

현업에서 근무하면서 레디스를 여러번 사용할 기회가 있었는데, 제대로 공부해볼 시간 없이 그냥 Single Thread니까! 하고 사용만 해왔다. 이것저것 Wrap Up 공부하면서 Redis에 관해 공부한 내용을 정리해본다. 

1. Redis는 

싱글 스레드 기반의 Key, Value 구조의 비정형 데이터를 저장하고 관리하는 비관계형 DBMS이다. 레디스는 모든 데이터를 메모리에 저장하는 인메모리 데이터베이스이며, 다양한 자료구조를 지원한다.

레디스는 영속성을 보장하기 위해 데이터를 DISK에 저장할 수 있다. 서버가 내려가더라도 DISK에 저장된 데이터를 읽어서 메모리에 로딩을 하는데, 데이터를 DISK에 저장하는 방식은 아래와 같이 두 가지 방식이 있다.

  • RDB(Snapshotting) 방식
    • 순간적으로 메모리에 있는 내용을 DISK에 전체를 옮겨 담는 방식
  • AOF (Append On File) 방식
    • Redis의 모든 write/update 연산 자체를 모두 log 파일에 기록하는 형태
    • 명령이 실행될 때마다, 명령이 파일에 기록되며 특정 시점에 data 전체를 다시 쓴다
      • 특정 key값에 데이터가 5번 rewrite 되었다면, 그냥 가장 마지막 시점에 최종적으로 설정된 데이터의 값만 저장해도 되기 때문

 

2. Redis는 기본적으로 Single-Thread에요.

레디스는 기본적으로 Single-Thread입니다. 멀티 스레드 기반으로 구현되면, 컨텍스트 스위칭 비용이 발생하게 되고, 공유하고 있는 자원(shared-data)의 데이터를 수정할 때 sync 문제가 발생할 수 있기 때문이죠. 

레디스는 클러스터 기능을 제공하는 동시성 프로그래밍을 위한 인메모리 데이터베이스이다. 명령에 대한 부분들은 MultiplexingEventloop에 의해 처리되기에 Atomic함을 유지할 수 있다.

 

3. 그런데 어떤 상황에서는 Redis가 Multi-Thread 입니다.

  • Version 3.2 : AOF 관련 처리만 Sub Thread에서 실행
  • Version 4 : UNLINK 명령을 Sub Thread에서 처리하기 시작
  • Version 6 : ThreadedIO가 부분적으로 적용

위의 기능들에는 부분적으로 Multi Thread이며, 명령의 실행 자체는 Single Thread 입니다. 고로 Redis의 특징인 Atomic은 Single Thread를 유지함으로써 여전히 보장이 된다.

3.1 AOF 는 위에서 설명했고, 이 과정은 SubThread에서 처리하는게 훨씬 효율적이겠죠. 

3.2 UNLINK란,

DEL 명령어와 같이 특정 key 값을 지워주는 명령어로 Version 4.0에서 추가된 명령어이다. DEL과 다른 점은 key가 존재하지 않을 때 DEL은 Block되지만 Unlink 명령어는 Block되지 않는다.
UNLINK 명령어는 Key 삭제는 Sync 로 동작하고, 값 삭제를 별도의 Thread에서 비동기로 처리한다. 대부분의 경우, DEL 명령어를 사용하는 것보다 UNLINK 명령어를 사용하는 것이 더 안전하고 낫다고 한다.
https://stackoverflow.com/questions/45818371/is-the-unlink-command-always-better-than-del-command

 

Is the UNLINK command always better than DEL command?

In Redis 4.0, there is a new command UNLINK to delete the keys in Redis memory. This command is very similar to DEL: it removes the specified keys. Just like DEL a key is ignored if it does not

stackoverflow.com

3.3. ThreadedIO

['클라이언트가 전송한 명령을 네트워크로 읽어서 파싱하는 부분'과 '명령이 처리된 결과 메세지를 클라이언트에게 전달하는 부분'] I/O Socket Read/Write 멀티스레드 기반으로 하여 네트워크 통신 비용을 효율적으로 사용하고, 이 외에 명령을 수행하는 부분은 싱글 스레드로 수행하여 Redis의 Atomic을 유지한다. 

 

4. Redis는 동시성 문제가 발생할 수 있는 부분을 안전한 Transaction을 통해 해결한다.

Redis Documents를 보면, Redis는 안전한 Transaction을 위해 여러 명령어를 제공한다.

Redis는 MULTI, EXEC, DISCARD, WATCH 명령어를 제공한다. MULTI와 EXEC를 이용해서 Transaction 을 실행하게 될때, 이 명령어들만 사용하게 되면 동시성 문제가 발생하게 된다.
그래서 Optimistic Locking을 사용하기 위해 WATCH 명령어를 사용하고, 해당 명령어가 안전한 Transaction을 보장하게 된다고 한다.

728x90

'Python > 3rd-Party' 카테고리의 다른 글

[2] AMQP (RabbitMQ Docs 번역)  (2) 2021.06.01
[1] Kombu란? RabbitMQ with Python  (0) 2021.06.01
Comments