자바에서 전역변수를 사용하면 메모리의 데이터 영역에 저장된다. 이 또한 메모리에 저장되는 것이지만, 해당 서버 내에서만 사용할 수 있다. 즉, 서버가 여러 대가 되면 다른 서버에서는 해당 데이터에 접근할 수가 없다. 또한, 멀티쓰레드 환경에서 Race condition이 발생할 수 있다.
Redis는 싱글 스레드로 명령어를 처리하기 때문에 Atomic Critical Section에 대한 동기화를 제공한다. 모든 명령어가 순차적으로 처리된다는 뜻이다. 여러 명령어가 동시에 한 데이터에 접근할 수 없다. 여러 명이 동시에 같은 글에 좋아요를 눌러도 모든 수가 반영된다.
돈을 송금하는 비유처럼 여러 명령어 사이에 다른 명령어가 끼어들면 안되거나 각 작업의 고립성을 보장해야 하는 경우가 있다. Redis에서는 이런 경우 MULTI, EXEC, WATCH 등을 사용할 수 있다.
예를 들어 주문에 대하여 라이더를 매칭하는 경우(주문 객체에 라이더 추가하고, 라이더의 주문 목록에 주문을 추가해야 하는 경우)
...
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