티스토리 뷰
Single 로 사용하던 세션서버 용도의 Redis 를 노드를 늘릴 수 있는 기회가 생겨서 어떤 구성을 적용할 지 고민을 하게 되었다. 이상적인 구조는 Master 하나와 2대 이상의 Slave 그리고 3대 이상의 Sentinel 이지만 현재의 서버가 부족하여 2대로 구성을 해야 했다.
처음 생각했던 것은 Master 1, Slave 1 구성하고 Replication 을 사용하고 Slave 의 read only 를 사용하지 않는 것이었다. 마스터 장애 시 slave 에 쓸 수 있고 장애가 복구되면 다시 master 를 사용하려는 목적이었다.
하지만 slave 의 데이터가 master 로 가지 않는 단점이 있어서 slave 의 사용 시간이 늘어날 수록 복구 후 손실되는 데이터가 많아지는 단점을 갖고 있었다. (master 의 데이터를 동기화 하기 때문에 slave 에게만 있는 데이터는 master 가 복구된 후 모두 사라진다.)
그래서 생각한 것이 위 구성에서 Sentinel 1 를 더 구성하는 것이었다. 그럼 클라이어트에서 장애 감지 후 Slave 에 데이터를 쓰는 동안 Sentinel 이 장애를 감지하고 slave 를 master 로 승격시켜주게 되고 데이터가 손실되지 않기 때문이다.
아래 설명 중 slave only 를 비활성화 해주는 이유는 master 가 죽게 되면 잠깐 동안이라도 데이터를 쓰기 위해서인다. (개발한 redis connectino pool 이 장애를 감지해서 다른 서버를 사용하게 된다.)
Master 설치
특별히 해줄 것은 없지만 장애 후 slave 가 될 경우를 대비해서 redis.conf 의 slave-read-only 를 no 로 변경해 준다. 위 설명 중 slave 의 read only 를 비활성화하는 이유와 같다.
실행 : ./src/redis-server ./redis.conf
Slave 설치
redis.conf 의 slaveof <masterip> <msaterport> 에 master node 의 ip port 를 설정해 준다. 그리고 master 에서 했던 것과 같이 slave-read-only 설정을 no 로 변경해준다.
실행 : ./src/redis-server ./redis.conf
Sentinel 설치
sentinel을 위한 설정파일은 sentinel.conf 로 별도로 있다.
1. sentinel monitor <master-name> <ip> <redis-port> <quorum> 에 master node의 정보를 적어준다. 기본은 mymaster 로 되어 있다.
master-name : 이름을 지정해 줄 수 있는데 나중에 클라이언트에서 master 의 정보를 sentinel 을 통해서 가져올 때 사용할 수 있다.
quorum : sentinel 들이 투표를 통해서 master 의 교체가 필요하다고 판단하는데 사용되는 투표수를 지정하는 것이다. 보통은 sentinel 수 - 1 을 설정하지만 여기서는 sentinel 이 하나이므로 1로 설정한다. (혼자 판단한다!)
2. protected-mode 설정을 no 로 해준다. 내부망에서만 사용하는 것이고 클라이언트(redis 를 사용하는 application)에서 master 의 정보를 가져올 때 쉽게 가져올 수 있다.
3. sentinel down-after-milliseconds mymaster 60000 master 가 죽었다고 판단하는데 사용하는 시간으로 지금 설정은 1분동안 응답이 없으면 죽었다고 판단한다. mymaster 는 위에 <master-name> 에 적은 이름이다.
클라이언트에서 master 정보 가져오기
Jedis jedis = new Jedis("127.0.0.1", 26379) // setinel 정보
System.out.println(jedis.sentinelGetMasterAddrByName("mymaster"));
결과 : ["127.0.0.1", 6379] //배열이 반환되며 0:ip, 1:port 정보이다.
FailOver 가 가능한 jedis pool 만들기
Jedis 는 JedisPool 이라는 커넥션 풀을 이미 제공해 주고 있다. 이를 사용하여 master, slave 모두 관리 할 수 있도록 한다.
Map<Address, JedisPool> pools = new LinkedHashMap<>();
Address masterAddress;
그리고 항상 master를 사용한다.
Jedis jedis = pools.get(masterAddress).getResource();
만약 장애 발생시 slave 에서 가져온다.
그리고 별도의 HealthChecker 가 주기적으로 master 의 주소를 sentinel 에게서 가져와 masterAddress 의 정보를 변경해 준다.
'IT > 개발' 카테고리의 다른 글
객체지향 이란 (0) | 2018.06.10 |
---|---|
레거시에 Solr 적용하기 (0) | 2018.05.22 |
Github 에 개인 maven repository 생성하기 (0) | 2018.02.14 |
Garbage Collection (0) | 2017.02.04 |
Object class (0) | 2017.02.01 |