2014년 12월 21일

Redis Replication (레디스 복제)

본 문서는 http://redis.io/topics/replication 의 번역입니다.

Replication

Redis replication is a very simple to use and configure master-slave replication that allows slave Redis servers to be exact copies of master servers. The following are some very important facts about Redis replication:
Redis 복제는 매우 간단합니다. 사용하기 쉽고 마스터-슬레이브 관계의 복제 구성도 간단합니다. 이 복제구성은 슬레이브 Redis 서버가 마스터 서버의 완전한 복사본이 되게 해줍니다. Redis 복제에 대해서 매우 중요한 사실이 몇 가지가 있습니다.

  • Redis uses asynchronous replication. Starting with Redis 2.8, however, slaves will periodically acknowledge the amount of data processed from the replication stream.
    Redis는 비동기 복제입니다. 그러나, Redis 버전 2.8 이후부터는 슬레이브들이 복제 스트림으로부터 복제한 데이터의 총량을 주기적으로 알려줄 것입니다.

  • A master can have multiple slaves.
    하나의 마스터는 여러 개의 슬레이브를 가질 수 있습니다.

  • Slaves are able to accept connections from other slaves. Aside from connecting a number of slaves to the same master, slaves can also be connected to other slaves in a graph-like structure.
    슬레이브들은 다른 슬레이브들로부터의 연결을 받아들일 수 있습니다. 슬레이브는 같은 마스터에 연결하고 있는 것과는 별도로, 그래프 구조와 유사하게 다른 슬레이브에 연결될 수 있습니다.

  • Redis replication is non-blocking on the master side. This means that the master will continue to handle queries when one or more slaves perform the initial synchronization.
    Redis 복제는 마스터 입장에서는 비블록입니다. 즉, 마스터는 하나 또는 그 이상의 슬레이브가 동기화 작업을 시작하더라도, 클라이언트의 요청을 처리할 수 있을 것입니다. 

  • Replication is also non-blocking on the slave side. While the slave is performing the initial synchronization, it can handle queries using the old version of the dataset, assuming you configured Redis to do so in redis.conf. Otherwise, you can configure Redis slaves to return an error to clients if the replication stream is down. However, after the initial sync, the old dataset must be deleted and the new one must be loaded. The slave will block incoming connections during this brief window.
    복제는 슬레이브 입장에서도 비블록입니다. 슬레이브는 설정파일 redis.conf에 그렇게 동작하도록 설정했다는 가정하에, 동기화 작업을 시작하는 동안에도 과거의 데이터셋을 이용해서 클라이언트의 요청을 처리할 수 있습니다. 이렇게 설정하지 않고, 복제가 진행되는 동안에 클라이언트로 에러를 전달하도록 할 수도 있습니다. 그러나, 초기 싱크가 시작된 이후에는 과거의 데이터셋은 지워져야만 하고 새로운 데이터셋이 로드 되어야 합니다. 슬레이브는 잠시동안 클라이언트의 새로운 연결을 블록하게 됩니다.

  • Replication can be used both for scalability, in order to have multiple slaves for read-only queries (for example, heavy SORT operations can be offloaded to slaves), or simply for data redundancy.
    복제는 확장성(scalability)이라는 관점에서, 읽기 전용을 위한 다중 슬레이브를 구성할 수 있고(예를 들면, 무거운 정렬 작업을 슬레이브에 맡길 수 있음), 간단하게는 잉여 데이터로도 활용될 수 있습니다. 

  • It is possible to use replication to avoid the cost of having the master write the full dataset to disk: just configure your master redis.conf to avoid saving (just comment all the "save" directives), then connect a slave configured to save from time to time. However in this setup make sure masters don't restart automatically (please read the next section for more information).
    복제 서버는 마스터가 전체 데이터셋을 디스크에 저장하는 할 때 소요될 수 있는 비용이 들지 않도록 하는데 이용될 수 있습니다. 마스터 서버의 redis.conf 설정에서 저장 옵션을 제거하는 것으로 가능한 일입니다(즉, save로 시작하는 지시어를 주석처리 하는 것). 슬레이브로 설정된 서버가 가끔씩 연결하여 데이터를 가져갑니다. 그러나, 이러한 설정을 포함하고 있다면, 마스터는 자동으로 재시작하지 않도로 해야한다는 것을 명심하십시오(좀 더 자세한 사항은 다음 세션을 읽어 보십시오).


Safety of replication when master has persistence turned off

마스터 서버의 데이터 영속성(persitence) 설정이 오프일 때, 복제의 안정성



In setups where Redis replication is used, it is strongly advised to have persistence turned on in the master, or when this is not possible, for example because of latency concerns, instances should be configured to avoid restarting automatically.
To better understand why masters with persistence turned off configured to auto restart are dangerous, check the following failure mode where data is wiped from the master and all its slaves:
Redis 복제를 이용하는 설정에서, 마스터에 데이터 영속성(persistence, 역자주: redis 메모리에 있는 dataset를 RDB 또는 AOF 형식으로 디스크에 남기는 모드) 설정은 켜는 것이 좋습니다. 그런데, 처리 지연 등의 이유로, 이 설정을 On 시킬 수 없다면 redis 서버를 자동으로 재시작하지 않도록 설정해야 합니다.
좀 더 쉬운 이해를 위해서 데이터 영속성이 off 상태이고, 자동 재시작 하도록 설정되었을 때, 이 상태가 왜 위험한지 다음의 시나리오를 통해서 설명하도록 하겠습니다. 이 상황은 마스터로 인해 슬레이브들의 데이터가 모두 사라지는 상황에 대한 것입니다.

  1. We have a setup with node A acting as master, with persistence turned down, and nodes B and C replicating from node A.
  2. A crashes, however it has some auto-restart system, that restarts the process. However since persistence is turned off, the node restarts with an empty data set.
  3. Nodes B and C will replicate from A, which is empty, so they'll effectively destroy their copy of the data.

  1. 마스터로 동작하는 노드A 서버가 있습니다. 이 서버는 데이터 영속성이 켜져있지 않습니다. 이제 노드 B,C 라고 불리는 노드가 있고, 이것들은 노드A의 복제입니다.
  2. 크래쉬 발생. 마스터에 크래쉬가 발생했지만, 자동 재시작되어서 마스터가 재시작됩니다. 그러나, 데이터 영속이 켜져있지 않았으므로 이 노드A는 비어있는 데이터셋으로 시작합니다.
  3. 노드B,C는 노드A로부터 복제를 시작합니다. 그런데, 데이터셋이 비어있는 상태이고 슬레이브 노드B,C 데이터가 모두 사라지게 됩니다.

When Redis Sentinel is used for high availability, also turning off persistency on the master, together with auto restart of the process, is dangerous. For example the master can restart fast enough for Sentinel to don't detect a failure, so that the failure mode described above happens.
Every time data safety is important, and replication is used with master configured without persistence, auto restart of instances should be disabled.
HA(High Availability)를 위해서 센티널을 사용중이고, 마스터에 데이터 영속성을 off인 경우에, 자동재시작하도록 설정하였다면, 이 경우에도 마찬가지로 위험합니다. 예를 들면, 마스터 서버는 센티널이 마스터 서버의 장애상황을 인지하는 것보다 더 짧은 시간내에 재시작할 수 있습니다. 
데이터 안전한 보관은 항상 중요한 사항입니다. 그래서, 데이터 영속성 없는 마스터를 복제하도록 사용하는 경우에는, 마스터의 자동재시작은 받드시 off로 되어야 합니다.

How Redis replication works

Redis 복제는 어떻게 동작하는가.

If you set up a slave, upon connection it sends a SYNC command. It doesn't matter if it's the first time it has connected or if it's a reconnection.
The master then starts background saving, and starts to buffer all new commands received that will modify the dataset. When the background saving is complete, the master transfers the database file to the slave, which saves it on disk, and then loads it into memory. The master will then send to the slave all buffered commands. This is done as a stream of commands and is in the same format of the Redis protocol itself.
You can try it yourself via telnet. Connect to the Redis port while the server is doing some work and issue the SYNC command. You'll see a bulk transfer and then every command received by the master will be re-issued in the telnet session.
Slaves are able to automatically reconnect when the master <-> slave link goes down for some reason. If the master receives multiple concurrent slave synchronization requests, it performs a single background save in order to serve all of them.
When a master and a slave reconnects after the link went down, a full resync is always performed. However, starting with Redis 2.8, a partial resynchronization is also possible.

슬레이브를 시작하고 마스터와의 연결도 이루어지면 SYNC 명령어를 보냅니다. 이 상황이 최초 연결이 이루어진 경우에 발생하거나 재연결이 이루어진 경우에 발생한다면 문제가 되지는 않습니다.
마스터는 백그라운드 저장을 시작합니다. 그리고, 이후에 인입되는 명령어 중에서 데이터셋을 변경하는 것이 있다면 buffer에 저장하기 시작합니다. 백그라운드 저장이 완료되면, 마스터는 데이터 파일을 슬레이브에 전송합니다. 슬레이브는 이 데이터를 디스크에 적은 후에 메모리에 적재합니다. 마스터는 buffer에 저장되어 있는 커맨드들을 슬레이브에 전송할 것입니다. 이 데이터는 Redis 프로토콜로 구성된 연속된 커맨드입니다.
이 상황을 telnet를 이용하여 확인할 수 있습니다. Redis 서버 포트에 telnet으로 연결합니다. 그리고 SYNC 커맨드를 전송합니다(물론, Redis 프로토콜에 맞게 전송해야함). 그러면, 일련의 데이터 전송이 출력되는 것을 볼 수 있고, 마스터로 인입되는 모든 명령어가 telnet 연결 세션으로 그대로 전달되어 화면에 보여집니다.
슬레이브는 마스터와의 연결이 끊어졌을 때, 자동으로 재연결수행하게 할 수 있습니다. 만약 마스터 서버가 여러 슬레이브들로부터 동시에 동기(sync)를 원하는 요청을 받게 된다면, 마스터는 이 요청을 모두 처리하기 위한 하나의 백그라운드 저장을 수행합니다.
마스터, 슬레이브 사이의 연결이 끊어졌을 때, 항상 전체 동기화(sync)가 이루어집니다. 그러나, Redis 2.8 버전부터 부분 동기화(partial sync)가 가능하게 되었습니다.

Partial resynchronization

부분 재동기화

Starting with Redis 2.8, master and slave are usually able to continue the replication process without requiring a full resynchronization after the replication link went down.
This works by creating an in-memory backlog of the replication stream on the master side. The master and all the slaves agree on a replication offsetand a master run id, so when the link goes down, the slave will reconnect and ask the master to continue the replication. Assuming the master run id is still the same, and that the offset specified is available in the replication backlog, replication will resume from the point where it left off. If either of these conditions are unmet, a full resynchronization is performed (which is the normal pre-2.8 behavior).
The new partial resynchronization feature uses the PSYNC command internally, while the old implementation uses the SYNC command. Note that a Redis 2.8 slave is able to detect if the server it is talking with does not support PSYNC, and will use SYNC instead.
Redis 2.8 부터는 마스터와 슬레이브의 연결이 끊어지더라도 전체 데이터를 다시 동기화하지 않고 복제을 계속할 수 있게 되었습니다.
이 기능은 마스터상에서 복제 스트림을 위한 메모리 백로그(in-memory backlog)를 만드는 작업 덕분에 동작할 수 있습니다. 마스터와 모든 슬레이브들은 복제 오프셋과 마스터 run id 라는 값으로 동일한 복제상태를 표시합니다. 그래서, 마스터, 슬레이브 연결이 끊어지면 슬레이브는 마스터에 다시 연결한 후에 복제를 계속할 것을 요청합니다. 마스터 run id가 여전히 동일하다는 가정과 복제 백로그에서 특정 오프셋이 가능한 상태이면, 복제는 그 지점부터 복구할 것입니다. 이 조건들 중에서 하나라도 일치하지 않는다면 전체 재동기화가 이루어지게 됩니다(이는 2.8 버전에서 일어나는 동작임).
새로운 부분 재동기화 기능은 내부적으로 PSYNC 명령어를 사용합니다. 구 버전의 구현에서는 SYNC 명령어를 사용했었습니다. Redis 2.8 버전의 슬레이브는 마스터 서버가 PSYNC 명령어를 지원하는지 여부를 판단하는 기능을 가지고 있습니다. 판단 결과에 따라 SYNC 명령어를 사용할 수도 있습니다.

Diskless replication

디스크에 저장없이 복제하기
Normally a full resynchronization requires to create an RDB file on disk, then reload the same RDB from disk in order to feed the slaves with the data.
With slow disks this can be a very stressing operation for the master. Redis version 2.8.18 will be the first version to have experimental support for diskless replication. In this setup the child process directly sends the RDB over the wire to slaves, without using the disk as intermediate storage.
The feature is currently considered experimental.
일반적으로, 전체 재동기화를 하기 위해서는 디스크에 RDB 파일을 생성해야합니다. 이 파일을 적재(reload)하여 같은 데이터를 필요로 하는 슬레이블들에게 전달하게 됩니다.
느린 디스크의 경우에 이러한 작업은 마스터 서버 입장에서는 간단한 수행이 아닙니다. Redis 2.8.18에는 실험적으로 디스크없는 복제 기능이 처음 포함되었습니다. 이러한 설정에는 자식 프로세스가  직접 RDB 파일을 슬레이브에 보냅니다. 이 과정에서 중간에 디스크 스토리지를 이용하지 않습니다.
현재 이 기능은 시험 단계에 있습니다.

Configuration

설정하기

To configure replication is trivial: just add the following line to the slave configuration file:
slaveof 192.168.1.1 6379
Of course you need to replace 192.168.1.1 6379 with your master IP address (or hostname) and port. Alternatively, you can call the SLAVEOFcommand and the master host will start a sync with the slave.
There are also a few parameters for tuning the replication backlog taken in memory by the master to perform the partial resynchronization. See the example redis.conf shipped with the Redis distribution for more information.
Diskless replication can be enabled using the repl-diskless-syncconfiguration parameter. The delay to start the transfer in order to wait more slaves to arrive after the first one, is controlled by the repl-diskless-sync-delay parameter. Please refer to the example redis.conf file in the Redis distribution for more details.

복제를 설정하는 것은 매우 간단합니다: 다음의 내용을 설정 파일에 추가하하면 됩니다.
slaveof 192.168.1.1 6379
위의 예에서 192.168.1.1 6379의 내용은 여러분이 사용하는 Redis 마스터 IP 주소(또는 호스트이름)와 포트는 대체하시고요. 다른 방법으로, SLAVEOF 라는 명령어를 이용할 수 있습니다. 마스터로 동작하고 있는 서버에 이 명령어를 내리면 슬레이브로 동작하게 되엇 동기화를 시작하게 될 것입니다.
마스터에서는 부분 재동기화(partial resynchronization)를 위해 존재하는, 메모리 상의 복제 백로그가 있고, 이를 튜닝하기 위한 몇 가지 파라미터가 있습니다. 더 자세한 사항은 Redis 배포 파일에서 redis.conf를 참고하시면 됩니다.
디스크 없이 복제하는 기능은 repl-diskless-syncconfiguration 라는 파라미터를 이용하면 됩니다. 첫 번째 복제 요청 이후에 더 많은 슬레이브들의 복제 요청을 기다리기 위해서 복제를 시작하기까지의 지연 시간을 설정할 수 있는데, 이 설정은 위한 파라미터는  repl-diskless-sync-delay 입니다. 더 자세한 부분은 redis.conf 파일의 내용 참고하십시오.

Read-only slave

읽기 전용 슬레이브

Since Redis 2.6, slaves support a read-only mode that is enabled by default. This behavior is controlled by the slave-read-only option in the redis.conf file, and can be enabled and disabled at runtime using CONFIG SET.
Read-only slaves will reject all write commands, so that it is not possible to write to a slave because of a mistake. This does not mean that the feature is intended to expose a slave instance to the internet or more generally to a network where untrusted clients exist, because administrative commands like DEBUG or CONFIG are still enabled. However, security of read-only instances can be improved by disabling commands in redis.conf using the rename-command directive.
You may wonder why it is possible to revert the read-only setting and have slave instances that can be target of write operations. While those writes will be discarded if the slave and the master resynchronize or if the slave is restarted, there are a few legitimate use case for storing ephemeral data in writable slaves. However in the future it is possible that this feature will be dropped.
Redis 2.6 버전 이후부터, 슬레이브는 기본 설정으로 읽기전용 모드를 지원합니다. 이 동작은 redis.conf 설정 파일의 slave-read-only 라는 옵션으로 설정합니다. 그리고, 실행중이더라도 CONFIG SET 명령어를 통해서 동작여부를 변경할 수 있습니다.
읽기전용 슬레이브는 모든 쓰기 명령을 거부합니다. 그래서, 실수로라도 슬레이브에 쓰기 작업이 되는 경우는 없습니다. 이 기능은 슬레이브 서버가 외부 인터넷 또는 신뢰할 수 없는 클라이언트가 있는 네트웍에 노출되었을 때를 의도하여 있는 기능은 아닙니다. 왜냐하면, 관리자가 DEBUG, CONFIG 같은 명령어는 사용가능한 상태이기 때문입니다. 그러나, 보안 측면에서볼 때, rename-command 지시어로 redis.conf에 이 명령어를 사용할 수 없게 설정하는 것보다 읽기 전용으로 사용하는 것이 더욱 안전합니다.
여러분은 슬레이브가 읽기전용으로 설정 가능하거나, 쓰기가 가능한 서버로 변경이 가능한 것에 대해서 의문점을 가질 수도 있을 것입니다. 슬레이브가 마스터와 재동기화 중이거나, 슬레이브가 재시작되어서 이러한 쓰기 작업이 무시되는 동안에, 쓰기 가능한 슬레이브에 임시 데이터를 저장하기 위한 정상적인 사용 케이스가 있습니다. 그러나, 이 기능은 향후에 없어질 가능성도 있습니다.

Setting a slave to authenticate to a master

슬레이브가 마스터에 인증하도록 설정하기
If your master has a password via requirepass, it's trivial to configure the slave to use that password in all sync operations.
To do it on a running instance, use redis-cli and type:
config set masterauth 
To set it permanently, add this to your config file:
masterauth 
마스터 서버가 requirepass 설정을 가지고 있어서 패스워드를 요구한다면, 이를 위한 슬레이브의 설정도 매우 간단합니다.
실행 중인 상태에서 redis-cli 등을 사용해서 다음의 명령어를 입력하면 됩니다.
config set masterauth 
설정파일을 통해서도 다음과 같이 설정할 수 있습니다.
masterauth 

Allow writes only with N attached replicas

N개의 복제를 가진 쓰기 전용 마스터
Starting with Redis 2.8, it is possible to configure a Redis master to accept write queries only if at least N slaves are currently connected to the master.
However, because Redis uses asynchronous replication it is not possible to ensure the slave actually received a given write, so there is always a window for data loss.
This is how the feature works:
  • Redis slaves ping the master every second, acknowledging the amount of replication stream processed.
  • Redis masters will remember the last time it received a ping from every slave.
  • The user can configure a minimum number of slaves that have a lag not greater than a maximum number of seconds.
If there are at least N slaves, with a lag less than M seconds, then the write will be accepted.
You may think at it as a relaxed version of the "C" in the CAP theorem, where consistency is not ensured for a given write, but at least the time window for data loss is restricted to a given number of seconds.
If the conditions are not met, the master will instead reply with an error and the write will not be accepted.
There are two configuration parameters for this feature:
  • min-slaves-to-write 
  • min-slaves-max-lag 
For more information, please check the example redis.conf file shipped with the Redis source distribution.
Redis 2.8 버전부터, 적어도 N개의 슬레이브가 연결되어 있는 마스터의 경우에, 이 마스터를 쓰기 전용 요청만 처리하도록 설정하는 것이 가능하게 되었습니다.

그러나, Redis는 비동기 복제를 사용하기 때문에, 슬레이브에 이 쓰기 작업이 실제로 이루어졌다고 확신할 수 없는 상태입니다. 그래서, 데이터 손실을 고려한 일종의 윈도우가 존재합니다.

이 기능은 다음과 같이 동작합니다:

  • 슬레이브는 매초마다 마스터에게 Ping을 보냅니다. 이것은 슬레이브가 복제를 어느 시간까지 수행했는지를 표시하기 위함입니다.
  • 마스터는 모든 슬레이블로부터 이러한 ping을 받은 최종 시간을 기록합니다.
  • 사용자는 지연을 허용하는 최대 시간(초)과 최소 슬레이브 수를 설정할 수 있습니다.

최소 N개의 슬레이브가 있고, M초보다 적은 지연이 있을 때, 그 쓰기 작업은 성공하게 됩니다.

여러분은 CAP 이론(역자주: RDBMS 또는 NoSQL에서 일관성(Consistency), 가용성(Availability), 생존성(Partition tolerance)를 의미함.)의 유연한 ‘C’를 떠올릴 수도 있다고 생각합니다. 여기에서의 일관성(consistency)는 모든 쓰기 작업을 보장하지 않는다는 것입니다. 그러나, 데이터 손실을 고려한 최소 시간 윈도우를 지정하고 이 시간을 제약사항으로 인정하는 것이라 할 수 있습니다.

이러한 조건들을 만족하지 못하는 상황이라면, 마스터는 쓰기 요청에 대해서 에러를 응답하게 됩니다.

다음과 같은 2개의 설정 파라미터가 있습니다.
  • min-slaves-to-write 
  • min-slaves-max-lag 

더 자세한 사항은 Redis와 함께 배포되는 redis.conf 파일의 내용을 참고하시기 바랍니다.




댓글 없음:

댓글 쓰기