[Redis에 대하여] 1. 개요와 트랜잭션

아양시·2023년 1월 4일
1

Redis에 대하여

목록 보기
1/3

Redis란 ?

  • Remote Dictionary Server
  • 인-메모리 자료 구조 저장소
  • 데이터베이스, 캐시, 메시지 브로커 등으로 사용할 수 있다.
  • 다양한 자료구조(Strings, Lists, Sets, Hashes, Sorted Sets 등)를 제공한다.
  • 데이터베이스보다 더 빠른 메모리에 더 자주 접근하고 덜 자주 바뀌는 데이터를 저장하자.

자바 코드에서 전역 변수를 선언해서 사용하는 것과 다른 점 ?

  자바에서 전역변수를 사용하면 메모리의 데이터 영역에 저장된다. 이 또한 메모리에 저장되는 것이지만, 해당 서버 내에서만 사용할 수 있다. 즉, 서버가 여러 대가 되면 다른 서버에서는 해당 데이터에 접근할 수가 없다. 또한, 멀티쓰레드 환경에서 Race condition이 발생할 수 있다.

언제 사용하는 것이 좋을까?

  • 여러 서버에서 같은 데이터를 공유할 때
  • 싱글 서버라도 Atomic 자료구조나 캐시를 사용할 때

주의할 점

  • 싱글 스레드로 동작하기 때문에 O(N)의 명령어(keys, flushall 등) 수행 시 뒤 명령어들이 대기해야 한다.
  • 메모리 파편화로 작은 공간이 빈번해서 큰 프로세스를 올려놓지 못하게 되면 프로세스가 죽을 수 있다.
  • 영속성을 위해 snapshot 시 프로세스를 fork해서 사용하는데, 메모리가 가득 차 있다면 제대로 복제를 수행하지 못한다.
  • 메모리를 여유있게 사용하자 !

Redis는 싱글 스레드이다.

  Redis는 싱글 스레드로 명령어를 처리하기 때문에 Atomic Critical Section에 대한 동기화를 제공한다. 모든 명령어가 순차적으로 처리된다는 뜻이다. 여러 명령어가 동시에 한 데이터에 접근할 수 없다. 여러 명이 동시에 같은 글에 좋아요를 눌러도 모든 수가 반영된다.

Transaction을 처리하려면 ?

  돈을 송금하는 비유처럼 여러 명령어 사이에 다른 명령어가 끼어들면 안되거나 각 작업의 고립성을 보장해야 하는 경우가 있다. Redis에서는 이런 경우 MULTI, EXEC, WATCH 등을 사용할 수 있다.

  • MULTI : 트랜잭션 시작, 이후 명령어는 바로 실행하지 않고 큐에 쌓인다.
  • EXEC : 큐의 명령어를 일괄적으로 실행한다. (RDB의 commit)
  • DISCARD : 큐의 명령어를 일괄적으로 폐기한다. (RDB의 Rollback)
  • WATCH/UNWATCH : WATCH 명령어로 낙관적 락을 걸면 UNWATCH 전에는 한 번의 EXEC 또는 트랜잭션이 아닌 명령어만 허용한다.

예를 들어 주문에 대하여 라이더를 매칭하는 경우(주문 객체에 라이더 추가하고, 라이더의 주문 목록에 주문을 추가해야 하는 경우)

...
public void match(Rider rider, Order order) {

    String keyO = String.format("order:%s", order.id);
    String keyR = String.format("rider:%s", rider.id);
	redisTemplate.execute(new SessionCallback() {
    	@Override
        public Object execute(RedisOperations redisOperations) throws DataAccessException {
        	try {
            	redisOperations.watch(keyO);
                redisOperations.multi();
                redisOperations.opsForHash().put(keyO, "rider", rider.id);
                redisOperations.opsForList().rightPush(keyR, order.id);
            } catch (Exception e) {
            	redisOperations.discard();
                e.printStackTrace();
            }
            return Operations.exec();
        }
    });
}

이런 식으로 해볼 수 있겠다. (급하게 만들어본 예시!)


새로 알게된 점

  Redis에 자바 객체를 그대로 저장할 수 없을까 고민했던 적이 있는데 Hashes를 사용하면 되는 것이었다. 객체의 각 필드와 값을 {필드:값} 형태로 해당 객체의 키에 대하여 저장하면 된다. 나는 여태껏 그저 한 키에 대해 여러 값을 저장하고 싶을 때 Hashes를 사용했는데 이 경우에는 Lists를 사용하는 것이 맞았겠구나 ..!


[참조]
* https://wildeveloperetrain.tistory.com/137
* https://www.youtube.com/watch?v=Gimv7hroM8A
profile
BE Developer

0개의 댓글