Client-side caching
많은 application server에서 일부 데이터를 캐싱해서 사용하고 있다.
장점
- 빈번하게 호출되는 쿼리나 데이터에 대해 매우 작은 latency로 데이터를 조회할 수 있다.
- 데이터베이스의 요청 수를 줄일 수 있다.
하지만 client-side caching같은 경우 동기화의 문제가 존재
기존에는 다음과 같은 방법으로 문제를 어느정도 해결
- 데이터 정합성이 크게 중요하지 않은 경우에는 TTL을 사용
- pub/sub 시스템을 사용해서 application에 stale된 데이터를 알려줌
- 데이터가 변경될 때마다 모든 client에게 메세지를 보내야 하므로 bandwidth 관점에서 좋지 않다.
- application에서 데이터를 변경하는 쿼리를 보낼 때마다 database에서 publishing해야 하므로 DB의 cpu 관점에서도 좋지 않다.
The Redis Implementation of client-side caching
redis6에서부터는 위와 같은 문제를 해결하기 위해 Tracking이라 불리는 기능을 제공
Tracking 기능은 다음 두 가지 모드가 존재
- default mode : 서버가 특정 키에 대해 어떤 클라이언트가 접근했는지를 서버 메모리에 기록. 이후 해당 키가 변경이 되면 접근한 client에게 키가 변경되었음을 전달
- 서버에서 메모리를 사용한다는 단점이 있지만, 해당 키를 캐싱하고 있는 클라이언트에게만 메세지를 보낼 수 있다는 장점이 있다.
- broadcasting mode : 서버에서는 특정 키가 변경되면 모든 클라이언트에게 메세지를 전달. 클라이언트에서는 특정 key의 prefix만을 구독하고 있어, 서버에서 전달한 메세지의 키와 일치하는 경우에만 수정
- 서버에서 메모리를 사용하지 않지만, 모든 클라이언트에게 전달된다는 단점이 있다.
default mode 기준으로 설명
Client 1 -> Server: CLIENT TRACKING ON
Client 1 -> Server: GET foo
(The server remembers that Client 1 may have the key "foo" cached)
(Client 1 may remember the value of "foo" inside its local memory)
Client 2 -> Server: SET foo SomeOtherValue
Server -> Client 1: INVALIDATE "foo"
위와 같은 방식은 겉으로 보기에는 괜찮아 보이지만 만약 연결된 클라이언트의 수가 1만개가 넘어가고 모든 클라이언트가 connection 시간 동안 백만개 이상의 키를 요청한다고 가정한다면 서버의 메모리와 cpu 부담이 매우 커지는 상황이 발생한다.
redis에서는 다음과 같은 방식으로 위의 문제를 해결
- redis에서는 하나의 Invalidation Table로 각 키와 해당 키를 tracking하고 있는 client id를 가지고 있다.
- 새로운 key가 들어왔을 때, 만약 invalidation table의 최대 entries 개수를 넘는 다면, 가장 오래된 key의 정보를 제거하고, 해당 client들에게 해당 key가 수정된 것처럼 메세지를 전달
- 이렇게 함으로써 서버에서의 가용 메모리를 조절
- 새로운 key가 들어왔을 때, 만약 invalidation table의 최대 entries 개수를 넘는 다면, 가장 오래된 key의 정보를 제거하고, 해당 client들에게 해당 key가 수정된 것처럼 메세지를 전달
- 서버에서는 client의 포인터를 갖고 있는 것이 아닌 단순히 client-id만을 가지고 있다.
- 따라서 client의 포인터는 client connection 부분에서만 갖고 있게 되므로 client connection이 종료되면 carbage connection에 의해 해당 client connection과 client의 caching slot이 자동으로 제고됩니다.
- redis에서 데이터베이스를 구분하지 않고 단일 keyspace를 사용합니다.
- 만약 client는 2번 DB의 foo key를 캐싱하고 있지만, 3번 DB의 foo key가 수정되어도 동일하게 메세지를 전달받게 됩니다.
- 위 방식의 장점은 server에서의 메모리 사용량과 구현 복잡도를 줄이기 위함입니다.
'Redis(레디스)' 카테고리의 다른 글
| Redis Replication (0) | 2023.12.10 |
|---|---|
| Redis Sentinel (1) | 2023.12.10 |
| Redis pipelining (0) | 2023.12.10 |
| Redis pub/sub & redis stream과의 차이점 (1) | 2023.12.10 |
| Redis Transaction (1) | 2023.12.10 |