gmail smtp 서버를 이용시에 534-5.7.14 오류가 발생하면….

smtp 를 이용한 어플리케이션에서 메일발송…

아마 다들 gmail smtp 서버를 많이 쓸것이다.

하지만 만약 534-5.7.14 오류가 발생한다면

https://www.google.com/settings/security/lesssecureapps

를 방문하여

Screen Shot 2016-03-31 at 12.36.59 AM

이미지와 같이 보안설정이 낮은 앱에서 허용 체크를 해주면 된다. (ㅜㅜT-T 어쩌겠어…)

자바스크립트 함수 실행방식의 속도 차이를 테스트 해 보았습니다.

자바 스크립트 function 을 변수에 바로 할당해서 실행 시키는 방식과
일반적으로 실행 시키는 방식… 모든 브라우저에서 속도 차이가 어마어마 한데요.
왜 이렇게 실행 속도가 많이 나는 것일까요?
1. A 스크립트의 경우 var sum 의 경우는 함수내에 선언된 지역 변수 이기 때문에 접근 속도가 빠름
2. B 스크립트의 경우 var sum 의 경우는 전역 변수 이기 때문에 접근 속도가 느림
이래서 react js 가 전부 이런 방식으로 돌아가나 봅니다.
잼있네요.

12604849_998384390220762_8470489402657079381_o

구글의 이미지 포멧 Webp 를 소개 합니다..

안녕하세요. 오늘은 아는 사람은 알지만 대부분이 모른다는 이미지 포멧인 webp 를 소개 합니다.

(이미지 포멧이란 ? jpg 나 png 같은 이미지 파일의 형식을 말합니다.)

webp 는 나온지 좀 되었습니다. 제 기억에 2009 년에 처음 발표 했을꺼에요.
간단하게 어떻게 탄생하게 되었나 알아보면… 구글이 youtube 를 운영 하려고 하다보니 뭔기 더 좋은 동영상 포멧이 필요 했습니다.
그래서 On2 라는 회사를 인수한뒤 이 회사에서 개발한 VP8 엔진을 이용하여 webm 이라는 동영상 포멧을 만들고 youtube를 운영 했었죠.

이 webm 의 동생 프로젝트가 webp 입니다. 그래서 webp 는 이미지 이지만 VP8 영상 엔진을 사용하고 있죠.
Jpg 를 대체하기 위해서 만든것이고 jpg 대비 용량의 작게는 10% ~ 70% 이상 줄일수가 있습니다. 동일한 이미지 퀄리티를 유지하고도 말이죠.

요즘은 모바일 시대이다 보니 사람들이 전부 다 스마트폰을 들고 다니죠. 하지만 LTE 요금은 아직 비쌉니다. 따라서 서비스의 대부분을 차지하고
있으며 트래픽 비용을 많이 먹는 이미지 파일의 용량을 줄이는 것이 정말 중요한 숙제 입니다.

특히나 제가 몸담고 있는 e-commerce 에서는 상품을 웹상에서 팔다보니 고객에게 직접 보여줄수 있는 이미지가 정말 중요하죠. 따라서 이미지로 도배
를 할수밖에 없습니다. 그러다 보면 트래픽의 압박과 고객 입장에서는 서비스 로딩도 느리면서 LTE 데이타 용량도 많이 먹기 때문에 서비스를 사용하기
꺼려지죠. 예를들어 전에 제가 일했던 어느 회사에서 CS 가 들어왔는데 앱을 사용한지 일주일도 안되었는데 데이타를 1G나 먹었다고 항의가 들어왔었죠.
그래서 확인해 보니 이미지가 원본 사이즈 그대로 쓰이고 있더군요. (개당 용량이 막 15M 넘음)

아무튼 그래서 저도 찾아 보다가 webp 를 발견했고 제가 지금 일하고 있고 제가 담당하고 있는 부분중에 하나인 파일 업로드 쪽에 적용을 해보았는데
제가 몸담고 있는 조직은 플랫폼 개발이라 고객과의 접점이 없어요… 그래서 팀내에 발표를 했었는데 반응이 그냥 그렇네요. ㅎㅎㅎ ㅜㅜ

뭐 고객과의 접점이 없고 그 부분을 담당하는 조직이 따로 있기 때문에 어쩔수 없죠뭐 이해 합니다.

언젠간 기회가 오겠죠… 아무튼.. 이런 webp 는 기사를 검색하다 보니 facebook 에서 2013년에 cdn 비용을 줄이기 위해 도입 하겠다라고
뉴스에 나온적이 있는데 확인결과 아직 적용을 안했더라구요.

아무튼 jpg 와 동일한 퀄리티에 용량은 3분의1이라니 매력이 넘치지 않습니까? 하지만 커다란 단점이 몇가지 있습니다… ㅜㅜ

1. 일단 브라우저에서 webp 를 지원해야 합니다….

Screen Shot 2016-03-29 at 12.18.51 PM

자 보시죠… 에이 뭐야 라고 생각 하실수도 있는데 역시 구글의 이미지 포멧 답게 크롬과 안드로이드에선 (!) 다 지원합니다!
우리나라의 스마트폰 사용자의 대부분이 안드로이드를 사용하고 있죠? 따라서 충분히 가능성이 있습니다.

2. 이미지 파일을 컨버팅 하는 리소스가 필요하다… 이건 뭐 당연하죠?;;

이정도의 문제점이 있으나 제 개인적인 생각으론 브라우져에서 webp 를 지원하는지 않하는지에 따라 분기를 탄다면 충분히 가능성이 있습니다.
(이미 만들어서 제 깃헙에 올려놨어요. 글 하단에서 공개 합니다.)

그리고 webp 의 인코딩 모듈은 c 로 개발되어있습니다. 따라서 c 모듈을 서버에 설치하고 java 에서 사용하려면 jni 를 쓰셔서 로드를 해야 합니다.

제가 webp 를 테스트를 할수있는 데모를 만들었습니다.

http://webp.leekyoungil.com/

Screen Shot 2016-03-29 at 12.17.12 PM

대략 이런식으로 이미지 파일을 선택하고 업로드를 해보면 webp 로 변환되어 나오며 이미지 퀄리티와 용량을 확인할수 있습니다.
(클릭하면 팝업으로 원본 사이즈로 뜸)
webp의 압축 방식은 Lossy 와 Lossless 방식 2가지가 있습니다. 말그대로 손실과 무손실 방식이며 용량에 차이가 있습니다.

해당 데모의 소스는 github 에 올렸습니다. https://github.com/LeeKyoungIl/webp-java-sample

제 생각에는 e-commerce 에서 사용하면 많은 트래픽 비용을 절약할수 있을꺼 같으니 꼭한번 써보시기를 추천 합니다.

데모 – http://webp.leekyoungil.com/
이미지 출처 – http://caniuse.com/#feat=webp
webp 프로젝트 홈 – https://developers.google.com/speed/webp/

[ptcompare.com] 귀차니스트를 위한.. 한눈에 네이버 다음 인기 키워드 및 추천 검색 결과를 볼수 있는 서비스

목요일에 팀 동료에게 GoLang이 재미있다고 들었습니다.
그때 잘 기억해 두었다가 주말에 프로젝트나 하나 해봐야지 라고 생각 했고

주말에 조금 보니 와… 정말 재미있네? 흥미가 가더라구요. 그래서 간단하게 프로젝트나 하나 해보자 하고
git 에 repository 를 만들고 프로젝트를 시작했어요.

어여 기획한다음 뚝딱 해서 하루만에 만든 결과물 입니다.

이름하여 ptcompare.com 귀차니스트를 위한 포털 사이트 검색 서비스 이며

네이버와 다음의 유저가 입력한 특정 키워드로 자동완성결과를 한눈에 비교할수 있으며
실시간 hot 한 키워드도 두 포털의 데이타를 한눈에 확인할 수 있습니다.

아직 ver 0.1 시험판이라 간단한 기능만 있습니다.

해당 프로젝트는

backend – GoLang 1.5.2
frontend – Reactjs 0.14.6 <- (이것도 이번에 프로젝트 하면서 이번에 처음 써봤는데... 뭐.. view 에만 써봐서 딱히 강력한줄을 잘 모르겠어요.) 으로 만들었구요 스케줄러 및 프록시 등등을 개발 했습니다. http://www.ptcompare.com <- 여기 가서 구경해보시고 후기좀 부탁 드려요.

[Hibernate] name strategy 설정 관련…

보통 스프링 jpa 에서 hibernate 사용할때 기본적으로 Entity 를 만들고 Spring 을 구동하면
Hibernate 에서 테이블을 데이타 베이스에 자동으로 생성해주는데 문제가 camel case 로 테이블 명이나 컬럼명
을 만들어 버린다는것..

그래서 Hibernate 에서 naming strategy 옵션을 제공하여 underscore case 로 생성 될수 있도록 해주는 방식이 있다.
해당 옵션 설정 properties 명이 hibernate.naming-strategy 인데 아마 5.0 부터 deprecate 된거 같다.. 동작을 하지 않는다.

그래서 hibernate.implicit_naming_strategy 또는 hibernate.physical_naming_strategy를 사용하면 된다.

spring boot + jpa 사용하면 application.properties 에

spring.jpa.hibernate.naming-strategy 이런식으로 쓰면 된다고 구글링에 많이 나와있는데

이렇게 하면 동작을 안하고..

spring.jpa.properties.hibernate.physical_naming_strategy 이렇게 해주어야 한다. ㅜㅜ

Tomcat 을 운영하다 보면 manager 에 무단 접근을 시도하는 경우가 있다.

Tomcat 을 운영하다 보면

Screen Shot 2015-07-30 at 9.49.35 AM

이런식으로 manager 에 접속을 시도하는 bot 들이 있다.

해결책은

1. manager 를 외부에서 접근하지 못하도록 막거나
2. 앞단에 proxy 른 둔다던지
3. 접근 시도 아이피를 막아준다던지

이 방법중에 나는 일단은 3번을 택했다. (어차피 테스트 서버라..)

Tomcat 의 conf/server.xml 파일을 열어서

해당 인스턴스의 host 설정 부분을 찾아가서

<Host></Host> 사이에

를 추가 해주면 되고 아이피 란에 여러개의 아이피를 등록하고 싶으면 | 로 구분 하도록 하면 되고
대역으로 막으려면 121.12.34.* 이렇게 해주면 된다.

하지만 운영 서버라면 나중에는 해킹 시도하는 아이피가 늘어나면 | 구분자로 관리가 힘들어 지기 때문에
proxy 서버를 앞단에 두는것이 좋다.

Too many open files 해결하기

IO 관련해서 개발을 하다보면 자주 마주치는 부분중 하나가 이 오류일 것이다.

java.io.IOException: Too many open files

일단 해당 메시지로 구글 검색을 하면 대부분 해결책이

“시스템의 open files 를 올려라 리눅스의 경우 ulimit -n 65535” 이정도 및 limit.conf 파일 수정 하는 것이
나오는 것이 대부분 일것이다.

하지만 그전에 프로그램에서 뭔가 파일을 열고 닫는 부분에서 버그가 있어야 하지 않을까? 라는 것으로 접근하는 것이
가장 우선시 되어야 할 사항 이라고 생각한다.

일단 이렇게 접근 하기 위해서는 프로그램이 실행이 될때 (어떠한 액션이 발생할때) 지금 열린 파일의 갯수를 알아야 할것이 아닌가?

os 가 linux 라고 가정 할때 대상 프로세스에서 열린 파일의 수를 실시간으로 확인이 가능한 간단한 스크립트를 소개하겠다.

가령 대상 프로세스가 java 프로세스라고 가정하면

shell # ps aux | grep java

해당 프로세스 리스트를 확인하면

아래와 같이 593228 라는 프로세스 아이디가 나온다.

그러면 아래처럼 linux shell 상에서 명령어를 실행하면…

라고 실행하면 2초 단위로 해당 프로세스에서 열린 파일의 갯수가 출력되니 디버깅에 참고하기 바란다.

[NoSQL] Redis cluster tutorial

Redis cluster 를 프로젝트에 사용하기 위해 스터디를 하려고 하는데 역시 튜토리얼을 읽어보며 해보는것이 가장 좋을꺼 같더라구요.
Redis 사이트에 들어가면 튜토리얼이 있습니다. http://www.redis.io/topics/cluster-tutorial 이 튜토리얼을 읽어가며 해봤는데요.
다른분들께 도움이 될까해서 번역을 좀 해봤습니다.

중간중간 번역이 잘 안되는 부분도 있는데 원문과 같이 보며 참고 정도로 하시면 될듯 합니다.
(아 번역이 어려운 부분이 ㅜㅜ 영어 공부 더 열심히 해야지 이거원 )

그리고 마지막 부분에 “Redis 클러스터를 마이그레이션 하기” 부분이 있는데 아직 이부분은 해보지 못했고 잘 이해도 힘들어서 번역을 하지는 못했으니
참고하세요. 나중에 한번 필요할떄 해보고 (아직까진 이 기능까진 필요가 없네요.) 그때 이어서 번역을 하도록 하겠습니다.

——————————————————————————————————————————

Redis 클러스터 튜토리얼

이 문서는 매우 쉽게 Redis 클러스터에 관해서 소개하고 있습니다. 이 문서는 복잡하지 않게 분산 시스템의 컨셉을 이해할수 있습니다.
이 문서는 어떻게 Redis 클러스터를 설치하고 테스트하고 운영할것인지의 설명을 제공합니다.
또한 Redis 클러스터의 자세한 사양을 빼고 단지 유저 입자에서 시스템을 어떻게 사용해야할지 묘사하고 있습니다.

그래도 이 문서는 Redis 클러스터의 사용자 관점에서 본 유용하고 톡특한 특징에 관해서 심플하게 이해 시키기 위해서 노력하고 있습니다.
시작하게 전에 확인할것이 있는데 이 문서는 Redis 버전 3.0 이상이 필요합니다.

만약 당신이 심각하게 Redis 클러스터를 사용하기 위해 계획을 세우기 시작했다면 좀더 기본적인 설계서를 읽는것을 추천 합니다. 하지만 이 문서로
Redis 클러스터를 먼저 시작하고 나중에 설계서를 읽는것도 좋은 생각입니다.

Redis 클러스터 101 (? 101? 이 뭐지? one of one 이라는 것일까요?)

Redis 클러스터는 여러개의 Redis 노드들에 데이타를 자동으로 분배가 가능하도록 설치할수 있는 몇가지 방법을 제공 하며 또한 효율적인 파티션의 분활 방식을 제공합니다.
이것은 사실상 어떤 노드들이 실패가 발생해서 통신을 할수 없는 경우에도 작업이 계속된수 있는 기능입니다. 그러나 심각한 오류가 발생해서 클러스터가 정지가 될수도 있갰지요.
(예를들어 대부분의 마스터들이 다운 된다던지.)

그래도 당신은 Redis 클러스터를 사용하면 무었을 얻을수 있을까요?

당신의 데이타들을 여러 노드에 자동으로 분배해 주는 기능
일부 노드들이 실패하며 다른 클러스터들과 통신이 불가능 해도 운영을 계속할수 있는 기능

Redis 클러스터 TCP 포트들에 관하여

모든 Redis 클러스터 노드들은 2개의 TCP 컨넥션 포트가 꼭 필요합니다. 일반적으론 Redis는 TCP 포트를 클라이언트를 위해 사용하지만 (예를들어 기본 포트인 6379)
여기에 추가로 10000 을 더해서 데이타 포트를 만드는데 예를들어 16379 를 생성합니다.

이 높은 번호의 두번째 포트는 클러스터 버스에 사용되며. 이것은 노드와 노드간에 통신 체널이고 바이너리 프로토콜을 사용합니다.
클러스터 버스는 노드들이 실패 했는데 체크 하는데 사용되고 설정의 수정 및 페일오버시 인증 등에 사용됩니다.
사용자들은 클러스터 버스와 통신할 필요가 없습니다. 그러나 항상 기본적인 Redis 명령 포트와 같이 당신의 방화벽에 해당 포트를 등록 시켜주어야 합니다.
그렇지 않으면 Redis 클러스터는 노드들과 통신을 할수 업습니다. (예를들어 redis 포트가 6379 라면 방화벽에 6379 와 16379 를 등록시켜 주어야 한다는 뜻)

Redis 명령 포트와 클러스터 버스는 항상 포트번호가 10000이 차이가 납니다.
당신이 Redis 클러스터를 사용하기 원하면 각 노드들에서 체크하세요.

일반적인 사용자 포트 (6379)는 사용자들과 통신하기 위해 그리고 모든 클러스터에 접근하기 위해 열려있어야 합니다. (키 마이그레이션에 클라이언트 포트를 (6379) 사용)
클러스터 버스 포트는 다른 클러스터 노드 들에서 접근할수 있어야 합니다. (클라이언트 포트 + 10000번 포트)

만약 당신이 두 TCP 포트를 열지 않았다면, 정상적인 동작을 기대하지 마세요.
클러스터 버스는 각 노드간에 데이타 교환하는 바이너리 프로토콜과 다른 바이너리 프로토콜을 사용하는데 이는 노드들간에 정보를 주고 받을떄 좀더 적은 대역폭과 조금 더 빠른 처리가 가능합니다.

Redis 클러스터 데이타 분배

Redis 클러스터는 컨시스턴스 해싱 방식을 (consistent hashing,) 사용하지 않습니다. 그러나 키를 분배 하는데 있어서 개념은 약간 다르며 우리는 Hash slot 이라고 부릅니다.
(그러니깐 데이타 분배 방식이 Memcached 의 경우 consistent hashing 을 사용하는데 Redis 는 다른 방식의 키 분배 방식을 사용하며 이걸 Hash slot 라고 부른다는..)
Redis 클러스터에 16384 Hash slot 이 있습니다. 그리고 지정된 Hash slot 의 키를 계산 해서 우리는 간단히 CRC16 의 검증된 키를 받을수 있습니다.
모든 Redis 클러스터 노드에는 작은 부분의 Hash slot이 있고 이것은 3개의 노드에 있다고 예를 들면

노드 A 는 0 에서 5500 까지의 Hash slot 이 있습니다.
노드 B 는 5501 에서 11000 까지의 Hash slot 이 있습니다.
노드 C 에는 11001 에서 16384까지의 Hash slot 이 있습니다.

이것은 클러스터에 노드를 추가하거나 뺴는것을 쉽게 합니다. 예를들어 내가 새로운 노드 D 를 추가하고 싶으면 나는 Hash slot을 노드 A, B, C 로 부터 옮기면 됩니다. 노드를 삭제하는것도
비슷합니다. 나는 단지 Hash slot을 A 에서 B 로 혹은 C로 옮기면 됩니다. A 노드가 비워질때 나는 클러스터에서 완벽하게 뺄수 있습니다.
(이게 쉬운건가??? 운영중인 노드를 다른 노드로 옮긴다니.. 뭐 뒤에 쉽게 옮기는 방법이 나오겠죠? 일단 진행 합니다.)
떄문에 Hash slot을 노드에서 다른 노드로 이동하는것은 운영을 꼭 중지할 필요가 없습니다. (오 나오려나봐요.) 노드를 추가하거나 삭제하거나 또는 Hash slot 이 할당된 비율을 변경하는것은
다운타임이 필요 없습니다.
Redis 클러스터는 다중 키관련 작업을 지원하며 모든 키들은 단일 명령으로 실행되기 때문에 같은 Hash slot 에 속하게 됩니다.유저는 강제적으로 다중 키들을 같은 Hash slot 에 위치하게
할수 있으며 이 컨셉은 Hash tags 라고 불립니다.
Hash tags 는 Redis 클러스터 설계에 문서화 되어있습니다. 이것의 요지는 만약 대괄호 ‘{}’ 사이에 문자열이 있으면 이 버킷이 키가 됩니다. 오로지 어떤 문자열이 이 버킷 안에 있는지. 이것이 해시
화 되는 것 입니다. 예를들어 여기에 ‘{foo}’ 키와 다른 ‘{foo}’ 키가 있으면 이것들은 같은 Hash slot 에 생성됩니다. 그리고 다중키에 파라메타 (혹은 인수) 로 같이 사용될수 있습니다.

Redis 클러스터 마스터 슬레이브 모델

마스터 노드가 실패를 하거나 대부분의 노드와 통신을 하지 못하게 되는 상황에서 살아남기 위해서 Redis 클러스터는 마스터-슬레이브 모델을 사용합니다. 모든 Hash slot 1개에는 N개의 복제 슬롯이 있습니다.
우리의 예제에서 클러스터는 노드 A, B, C가 있고 만약 B 노드가 실패되면 클러스터는 계속 진행을 할수가 없습니다 즉 우리는 더이상 5501 부터 11000까지의 Hash slot 을 사용할수 없는 것 입니다.
그렇지만 만약 클러스터를 생성할때 (혹은 나중에) 우리가 슬레이브 노드를 모든 마스터 노드에 추가 했으면 클러스터는 A, B, C 의 마스터 노드와 A1, B1, C1 의 슬레이브 노드로 구성되었을 것 입니다.
이 시스템은 만약 B 노드가 문제가 생겨도 계속 진행될수 있습니다.
노드 B1 는 B를 복제하고 있기 때문에 B 가 문제가 생겨도 클러스터는 노드 B1 을 새로운 마스터 노드로 승격을 시켜 시스템이 정상적으로 계속 운영되도록 합니다.
그렇지만 노드 B 와 B1 가 같이 문제가 생기면 Redis 클러스터는 더이상 운영할수가 없어집니다.

Redis 클러스터의 일관성 보증

Redis 클러스터는 획실한 일관성을 보증하지 않습니다. 사실상 이 의미는 특정한 조건에서 Redis 클러스터는 클리이언트가 쓴 데이타를 잃을수도 있습니다.
첫번째 이유는 Redis 클러스터는 비동기 식으로 데이타 복제를 하기 떄문에 데이타를 쓰기 를 할때 데이타를 잃을수도 있습니다. 이 의미는 쓰는동안 아래의 일이 일어난다는 것입니다.

당신의 클라이언트가 마스터 B 에 데이타를 기록한다.
마스터 B 는 클라이언트에게 쓰기가 완료 되었다고 OK 응답을 한다.
마스터 B 는 슬레이브 노드 B1, B2, 그리고 B3 에게 데이타를 복제 시킵니다.

당신이 보듯이 B 는 슬레이브 노드 B1, B2, B3 에게 데이타가 복제가 완료될때까지 기다렸다가 클라이언트에 응답을 하지 않습니다.
이 떄문에 Redis 를 안좋게 보면 안됩니다. 왜 그러냐면 만약 너의 클라이언트가 어떤 데이타를 기록할때 노드 B에(마스터에) 데이타 기록이 되었는데 만약 슬레이브 노드로 데이타를
복제하기전에(슬레이브 서버들은 아직 데이타를 받지 못했음) 마스터 서버에 오류가 나면 슬레이브 서버중 하나가 마스터로 승격 되고 기록한 데이타는 영원히 사라 집니다.

이것은 대부분의 데이타 베이스들에서 일어나는 일과 흡사 합니다. 데이터 베이스 서버들은 대부분 매초마다 디스크에 쓰도록 설정이 되어있습니다. 이것은 분산 시스템과 관련이 없는 전통적인
데이타 베이스 시스템에서 경험했던 것 입니다. (전통적인 데이타베이스 시스템은 디스크에 데이타를 쓰기전에 버퍼에 쓰는데 버퍼에서 디스크로 쓰기전에 오류가 나면 데이타가 날아가는 그
상황과 같다고 이야기 하는것 같네요) 비슷하게 당신은 일관성을 개선시키기 위해서 강제적으로 데이타 베이스 서버가 클라이언트에 응답을 주기전에 데이타를 디스크에 쓰게 할수는 있습니다.
그러나 일반적으로 퍼포먼스가 떨어지기 때문에 엄두를 내지 못합니다. Redis 클러스터에서 데이터 복제를 동기화 한다면 이와 같을 것 입니다.

기본적으로 성능과 일관성 사이에서는 하나를 얻으면 하나를 잃습니다.
Redis 클러스터에서는 꼭 필요하다면 WAIT 명령어를 이용하여 동기쓰기를 사용할수 있습니다. 이는 쓰기에서 많은것을 잃습니다. 그렇지만 동기화 복제를 사용하더라도 확실한 일관성을 보장하진
않습니다. 이것은 항상 슬레이브가 데이터를 받기전에 마스터로 선출되는 복잡한 실패 시나리오 하에 발생 할수도 있습니다.

Redis 클러스터가 데이타를 잃는 또다른 주목할만한 시나리오가 또 있습니다. 네트워크를 나누는(파티션) 와중에 클라이언트는 마스터를 포함한 소수의 인스턴스에 격리될수 있습니다. (뭔소리야 -_-)

우리의 예제를 살펴보면 6개의 노드가 A, B, C, A1, B1, C1 명으로 클러스터로 구성되어 있고 이것은 3개의 마스터와 3개의 슬레이브로 이루어져 있습니다. 또한 클라이언트는 Z1 이라고 부릅시다.
네트워크를 나누면 (파티션 한뒤), 한쪽 파티션에는 노드 A, C, A1, B1, C1 그리고 다른 쪽 파티션에는 B 그리고 Z1 이 있다고 합니다.

Z1 은 여전히 노드 B 에 쓸수 있습니다. 만약 파티션을 매우 짧은 시간에 복구하면 클러스터는 아마 정상적으로 진행될것입니다. 그러나 만약 파티션이 오랜 시간 물고 있을경우 B1 이 마스터로 승격됩니다.
Z1 이 쓰기 데이타를 보내는 B 는 컨넥션을 잃어버리게 됩니다.

(아.. 뭔소린지 알겠음 가령 클라이언트 Z1 이 Redis 클러스터에 데이타를 쓰기위해 클러스터 B 에 접속후 데이타를 쓰려는데 그 때 네트웍이 느리다던지 네트웍에 부하가 생겨서 오랫동안 데이터를
쓰기위해 컨넥션을 물고 있으면 Redis 클러스터는 이 B가 장애라고 판단하여 B 를 클러스터에서 빼고 B1을 마스터로 승격 시켜서 B 에 물려있던 컨넥션 및 데이타는 소실된다는 이야기 인듯)

또 체크할것이 만약 한번에 보내낼수 있는 최대 데이타량을 Z1 에서 B로 보낼수 있다고 하고 만약 슬레이브를 마스터로 선택할만큼 시간이 경과되면 모든 마스터 노드의 쓰기는 중지 됩니다.

이 시간 값은 Redis 클러스터 설정에서 매우 중요한 값 입니다. 이 값은 노드 타임아웃 (node timeout) 이라고 불립니다. 노드의 타임아웃이 경과하면 마스터 노드는 실패한것으로 관주 합니다. 그리고
슬레이브 노드중에 하나도 바꿉니다. (슬레이브 노드를 마스터 노드로 승격한다는 소리) 유사하게 마스터 노드 없이 타임아웃이 경과하고 다른 마스터 노드들을 감지할수 있도록, 오류 상태로 진입하고
쓰기를 멈춥니다.

Redis 클러스터 설정 파라메타들

클러스터를 구축하는 예제에 관하여 알아보도록 합시다. 진행하기 전에 설정 파라메타 값들을 소개하겠습니다. 이것들은 redis.conf 파일 안에 있습니다. 몇개는 명백하고 나머지는 좀더 읽을수록 명확해질 것입니다.

cluster-enabled : 만약 yes 로 하면 Redis 클러스터를 사용하는 것이고 no 로 하면 그냥 일반적으로 독립적으로 Redis 서버를 구동하는 것입니다.
cluster-config-file : 이 옵션의 이름에도 불구하고 이 설정파일은 유저가 수정할수 없습니다. 그러나 이 파일은 Redis 클러스터 노드에 위치하고 자동적으로 클러스터의 설정을 지속시킵니다 (상태나 기본적인것) 매 시간 마다 바뀌며 시작시에 순서대로 다시 읽힙니다다. 이 파일 클러스터 안에 다른 노드들, 노드들의 상태, 변수의 변화 등의 리스트가 나열되어 있습니다. 종종 이 파일은 다시 쓰여지고 메시지의 결과가 디스크에 플러시 됩니다.
cluster-node-timeout : Redis 클러스터 노드에 접속할수 없을때까지의 실패로 간주하지 않을 최대 시간을 나타냅니다. 만약 마스터 노드가 이 시간까지 응답이 없으면 슬레이브 노드로 페일오버 됩니다. 이 파라메터는 Redis 클러스터에서 다른 중요한 파라메타들을 제어합니다. 확실하게 모든 노드는 대부분의 마스터 노드에 지정된 시간동안 접근할수 없습니다. 모든 승인된 쿼리가 중단됩니다.
cluster-slave-validity-factor : 만약 값이 0 이면 슬레이브 노드는 항상 마스터의 오류에 대기합니다. 시간이 얼마나 걸리든 마스터와 슬레이브 사이의 남아있는 링크를 끊어버린립니다. 만약 설정값이 명확할 경우 최대 접속을 끊는 타임은 노드의 타임아웃 값에 이 값으로 곱해집니다. 그리고 만약 노드가 슬레이브이면 만약 마스터 링크가 지정된 시간동안 끊어져있어도 페일오버를 시작하지 않습니다. 예를들어 노드타입아웃이 5초로 설정했다면 이 옵션 (validity factor) 값을 10으로 설정하면 슬레이브 노드는 50초 후에 마스터 노드와 접속이 끊기게 되며 마스터 노드로 페일오버 하려고 하지 않습니다. 기억할것이 어떤 값이든 기본값인 0과 다를경우 Redis 클러스터의 마스터에 문제가 생기면 페일오버를 할 슬레이브가 없는경우 결과를 사용할수 없습니다. 이 경우 오로지 원래 마스터가 클러스터에 다시 들어와야 복구될수 있습니다. ( 아 번역이 힘드네요;; 이 옵션값은 이해가 힘든데 보통은 0 으로 쓰는걸로 알고 있습니다.)
cluster-migration-barrier : 마스터와 연결되어 있어야 하는 최소 슬레이브 갯수, 다른 슬레이브 노드는 슬레이브화 되어있지 않은 다른 마스터 노드로 마이그레이션 될수 있습니다. 자세한 내용은 이 설명서의 복제 마이그레이션 부분을 참고하세요. (뭔소린지 저도 잘 모르겠습니다… 일단 마스터당 설정해야 하는 최소 슬레이브 수를 말하는거 같네요.)
cluster-require-full-coverage : 만약 이값을 yes로 설정하면 (yes 가 기본값이다.) 노드들에 키 저장공간의 일부 분을 저장하기에 노드 공간이 부족하면 쓰기를 멈춥니다. 만약 옵션 값을 no 로 설정하면 클러스터는 처리할수 있는 키값의 요청에만 일을 처리합니다.

Redis 클러스터를 만들고 사용하기

수동으로 Redis 클러스터를 설정하고 사용하려면 동작 하는 방식을 이해하는것이 매우 중요합니다. 그러나 만약 당신이 빨리 Redis 클러스터를 실행 시키고 싶으면 다음 색션인 ‘Redis 클러스터를 클러스터 생성 스크립트를 이용해서 구축하기” 로 넘어가세요.
클러스터를 만들려면 처음할일이 몇개의 비어있는 클러스터 모드로 동작하고 있는 Redis 인스턴스가 필요합니다. 기본적으로 일반 Redis 인스턴스는 클러스터로 만들수 없습니다. 때문에 Redis 를 설정하여 인스턴스를 특별한 모드로 동작하게 할 필요가 있습니다. 그러면 Redis 인스턴스는 클러스터 기능과 명령을 사용할수 있습니다.

다음의 예는 최소한의 Redis 클러스터 설정 파일 입니다.

port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
보다시피 클러스터 모드를 사용하는것은 매우 간단하게 cluster-enabled 옵션을 설정하면 됩니다. 모든 인스턴스가 또한 해당 노드를 설정하기 위한 설정파일이 어디있는지 포함되어있으며 기본파일 명은 nodes.conf
입니다. 이 파일은 결코 유저가 수정할수 없으며 Redis 클러스터가 시작될때 생성되고 필요하면 매 시간 업데이트 됩니다.
이것은 최소한의 클러스터가 동작하기 위한 설정으로 3대의 마스터 노드가 있어야 합니다. 너의 첫번째 테스트는 6개의 노드에 3개의 마스터와 3개의 슬레이브로 구성되어 있는 환경을 권장 합니다.
자 이제는 새로운 디렉토리로들어가서 새로운 디렉토리를 만듭니다 디렉토리 이름은 인스턴스의 포트 이름대로 만듭니다. 해당 포트의 인스턴스는 해당 폴더 안에서 실행 됩니다.

아래 처럼 합니다.
mkdir cluster-test
cd cluster-test
mkdir 7000 7001 7002 7003 7004 7005
각 폴더 7000 에서 7005까지 안에 redis.conf 파일을 생성하도록 합니다. 템플릿을 이용해 당신의 설정파일을 만듭니다 여기에 위애 설정을 이용하도록 합니다. 한가지 확인할것이 디렉토리 명에 따라서
옳바른 포트 번호로 수정해야 합니다.
이제 당신의 Redis 서버를 실행 시키기 위해 GitHub 에서 최신의 소스를 받고 컴파일을 하고 cluster-test 디렉토리에 집어 넣고 당신의 가장 좋아하는 터미널 어플리케이션을 이용해 6개의 터미널을 열도록
합니다.

모든 텝안의 인스턴스에서 아래처럼 실행을 시킵니다.

cd 7000
../redis-server ./redis.conf
이제 당신은 모든 인스턴스에 node.conf 파일이 있다면 아래처럼 새로운 아이디가 할당된 로그를 볼수 있습니다.

[82462] 26 Nov 11:56:55.329 * No cluster configuration found, I’m 97a3a64667477371c4479320d683e4c8db5858b1

이 아이디는 당신의 클러스터 구성에서 해당 인스턴스의 유니크한 아이디로 계속 쓰이게 됩니다. 모든 노드는 모드 다른 노드가 사용하는 아이디를 기억하며 그리고 이것은 아이피나 포트에 의해
결정되는것이 아닙니다. IP 주소나 포트들은 계속 바뀌지만 해당 아이디는 이 노드가 살아있는 동안은 바뀌지 않습니다. 우리는 이 아이디를 간단히 노드 아이디라고 부릅니다.

클러스터를 만들기

지금 우리는 몇개의 실행중인 인스턴스를 가지고 있습니다. 우리는 클러스터를 만들기 위해 몇가지 설정을 해주어야 합니다.
우리는 Redis 클러스터의 커맨드라인 유틸리티를 이용해서 도움을 받아서 매우 쉽게 클러스터를 설정할수 있습니다. 이 유틸리티의 이름은 redis-trib 이며 이것은 루비로 만들어져 인스턴스안에서
클러스터를 만들거나 체크를 하거나 다시 할당을하거나 등등의 특별한 명령어를 실행할수 있습니다.
이 redis-trib 유틸리티는 Redis 소스코드폴더 src 안에 있습니다. 간단하게 클러스터를 만들기 위해서는

./redis-trib.rb create –replicas 1 127.0.0.1:7000 127.0.0.1:7001
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
이 명령어는 클러스터를 생성하는 명령어 입니다. 우리가 새로운 클러스터를 만들려고 할때 옵션중에 –replicas 1 을 사용하는데 이것은 우리는 모든 마스터 노드에 슬레이브를 1개씩 만들겠다는 것을 의미합니다.
다른 값들은 새로 생성할 클러스터가 사용할 인스턴스들의 주소 리스트 입니다.
확실하게 우리가 요구하는것은 클러스터를 3마스터와 3슬레이브로 만드는 것을 설정하는 것 입니다.
redis-trib 유틸리티를 위와같이 실행시키면 당신에게 물어볼것 입니다. yes 로 입력을 하는것은 클러스터를 설정하고 구성하는것을 의미합니다. 인스턴스는 다른 인스턴스 들과 같이 통신하며 기동 됩니다.
결국 모든것이 다 정상적으로 기동되면 당신은 아래의 메시지를 볼수 있을것이다.
[OK] All 16384 slots covered
이것은 슬롯 16384 들이 마스터 들에 생성 되었습니다 작동할 준비가 되었다라고 생각 하시면 됩니다.

클러스터 생성 스크립트를 이용하여 클러스터를 생성하기

만약 당신이 Redis 클러스터를 위에 설명처럼 직접 설정하고 인스턴스를 배포하고 하는것을 원하지 않는다면 여기에 훨씬 심플한 시스템이 있습니다. (그러나 운영 하는 법을 배울수 없습니다.)
Redis 가 설치된 폴더의 utils 폴더 안에 create-cluster 폴더안에 create-cluster 스크립트를 확인해보면 이것은 심플한 bash 스크립트 입니다. (폴더명과 이름이 같다) 3개의 마스터 와 3개의 슬레이브로
이루어져 있는 6개의 노드를 시작하기 위해 단지 아래의 명령어만 입력하면 됩니다.

create-cluster start
create-cluster create

2번째 스텝에서 redis-trib 유틸리티가 실행되어 클러스터 레이아웃을 수락하길 원하면 yes 라고 대답합니다.
이제 클러스터를 사용할수 있습니다, 첫번째 노드가 기본값인 포트 30001로 실행이 돌것이며 당신이 클러스터를 정지 하고 싶을때는

create-cluster stop.

더 정보를 원하면 디렉토리 안에 들어있는 README 를 읽어 보세요. 어떻게 스크립트를 실행하는지 나와 있습니다.

클러스터와 시작하기

이 장은 Redis 클러스터의 클라이언트 라이브러리의 관해 다룹니다.
나는 아래와 같이 구현된 라이브러리들을 알고 있습니다.

redis-rb-cluster 은 내가 (@antiez) 다른 언어를 참고로 루비를 이용하여 구현 하였습니다. 이것은 간단하게 redis-rb 를 랩핑해서 최소한으로 효율적으로 사용하도록 클러스터를 구현 하였습니다.
redis-py-cluster 파이썬으로 redis-rb-cluster를 컨버팅 히고 있습니다. redis-py 의 기능을 대부분 지원하며 아직 개발중 입니다.
인기 있는 Predis (PHP Redis 클라이언트) 는 최근 업데이트로 Redis 클러스터를 지원하며 계속 개발중에 있습니다.
많은 곳에서 사용되는 자바 클라이언트인 jedis 는 최근에 Redis 클러스터를 지원합니다. 프로젝트의 README 를 확인해 보세요.
StackExchange.Redis 는 C# 을 지원 합니다. (그리고 대부분의 .NET 언어에서 사용가능 하다. VB, F#, etc…)
thunk-redis 는 Node.js 와 io.js 를 지원 합니다. 이것은 thunk/promise-based 와 파이프라인 클러스터를 지원하는 클라이언트 입니다.
redis-cli 유틸리티는 Redis 아직 정식 버전이 아닌 GitHub 저장소에 있고 실행시 -c 옵션을 주면 매우 기본적으로 클러스터를 지원합니다.

Redis 클러스터를 테스트를 하는 방법은 위의 클라이언트 들을 사용하던지 redis-cli 유틸을 사용하던지 매우 쉽습니다. 아래의 예는 redis-cli 를 사용하는 예제 입니다.

$ redis-cli -c -p 7000
redis 127.0.0.1:7000> set foo bar
-> Redirected to slot [12182] located at 127.0.0.1:7002
OK
redis 127.0.0.1:7002> set hello world
-> Redirected to slot [866] located at 127.0.0.1:7000
OK
redis 127.0.0.1:7000> get foo
-> Redirected to slot [12182] located at 127.0.0.1:7002
“bar”
redis 127.0.0.1:7000> get hello
-> Redirected to slot [866] located at 127.0.0.1:7000
“world”
확인사항 : 만약 당신이 스크립트를 이용해서 클러스터를 만들어 사용하는 중이라면 아마도 포트가 다를것 입니다. (참고로 30001이 기본값 입니다.)

redis-cli 는 매우 기본적인 기능을 지원합니다. 때문에 이것은 사실상 항상 클러스터 노드들은 올바른 노드로 리다이렉트 되는것만 사용 됩니다.
(아마도 B 에서 SET 해도 슬롯이 생성되어있는 A 로 리다이렉트되어 SET 되는 방식을 이야기 하는듯)
심각하게 이야기 해서 클라이언트 라이브러리는 이것보다 좋습니다. 맵을 캐쉬 하고 해쉬 슬롯이나 노드의 주소등을 바로 올바른 노드로 올바르게 접속하도록 합니다.
해당 맵은 오로지 클러스터의 설정이 변경이 될때 갱신됩니다. 예를들어 페일오버 후나 또는 시스템 관리자가 노드를 추가 하거나 삭제해서 클러스터 레이아웃을 변경할때만 가능합니다.

redis-rb-cluster 을 이용하여 예제 앱 만들기

진행 하기전에 어떻게 Redis 클러스터를 운영할지 생각해 보세요 어떻게 페일오버를 하는지 또는 재할당을 하는지 우리는 예제 어플리케이션을 만들거나 적어도 Redis 클라이언트
라이브러리가 어떻게 동작하는지 이해해야 할 필요가 있습니다.
이 방법은 우리는 예제를 실행하며 동시에 노드를 실패 하도록 할거나 또는 재할당을 하도록 하여 Redis 클러스터가 실제 어떻게 동작하는지 확인할 것입니다.
이것은 아무나 데이타를 클러스터에 쓰기를 할떄 별로 도움은 되지 않습니다. (뭔소린지;;)
이 장에서는 redis-rb-cluster 의 기본적인 사용 방법을 2개의 예제를 들어 설명합니다. 첫번째로 exampl.rb 이며 파일 안에 redis-rb-cluster 가 포함되어 있습니다.

이 어플리케이션은 매우 간단합니다. 이것은 키들을 숫자만큼 foo<번호> 만큼 set 하며 만약 이 프로그램을 실행하면 해당 결과는 다음과 같습니다.

SET foo0 0
SET foo1 1
SET foo2 2
And so forth…

이 프로그램을 더 발전시키면 모든 연산에서 클러스터와 함께 rescue 안에 감싸서 오류 발생시에 프로그램에서 나가는 것보다 오류를 스크린에 보여주는 것으로 디자인 되어야 합니다.
7번 라인이 이 프로그램에서 처음으로 흥미 있는 부분 인데요. 이것은 Redis 클러스터 객체를 노드들의 정보 그리고 노드별로 최대 접속 컨넥션수 마지막으로 타입아웃 값을 가지고 생성 합니다.
시작 노드의 정보는 꼭 전체노드의 정보를 적을 필요는 없습니다. 중요한것은 적어도 한개의 노드에 접속을 할수 있는것 입니다. 또한 redis-rb-cluster는 이 리스트를 첫번째 노드와 접속하자마자
갱신 합니다. 당신은 다른 중요한 클라이언트들도 비슷할 것이라고 기대할 것 입니다.
지금 우리는 Redis 클러스터 객체를 rc 변수 안에 저장했고 만약 Redis 객체가 정상이라면 우리는 이 오브젝트를 이용하여 클러스터에 접근하수 있는것입니다.
11에서 19라인 사이에 일어나는 일을 정확하게 살펴보면 우리가 이 예제를 재시작 할떄 우리는 다시 foo0 과 같이 시작하길 원하지 않습니다. (이미 캐싱 했으니) 따라서 우리는 카운터 번호를 Redis
자체에 저장해야 합니다. 코드는 카운터를 읽도록 설계되거나 또는 카운터값이 없으면 0을 설정해야 합니다.
그러나 확인해야 할것이 루프를 돌리며 계속 요청하는 중에 만약 클러스터가 다운되어 오류를 발생하는것을 주의해야 합니다.
21에서 30라인 사이에이 키를 set 하거나 오류를 출력하는 메인 루프를 시작합니다.
루프의 마지막에 sleep 를 호출하는것을 볼수 있는데 만약 당신이 테스트에서 더 빨리 클러스터에 데이타를 저장 하기를 원한다면 sleep 을 지우면 됩니다. (상대적으로 병렬처리 없이 바쁘게 루프를 돌릴려면
일반적으로 상태가 좋을때 초당 10000번의 작업요청에 응답 해야한다.)
보통 예제 프로그램들은 사람이 따라하기 쉽도록 쓰기작업들은 속도가 느려집니다. (뭔소린지…)
어플리케이션의 실행 결과를 보도록 합시다.
ruby ./example.rb
1
2
3
4
5
6
7
8
9
^C (I stopped the program here)
이것은 별로 흥미있지 않은 프로그램이고 우린 더 좋은것을 사용하겠지만 이미 프로그램이 동작하는 중에 데이타가 재할당 되는 부분에서 어떤일이 일어나는지 알수 있습니다.

클러스터 재할당

지금 우리는 클러스터 데이타를 재할당을 할 준비가 되어있습니다. 이것을 하려면 example.rb 프로그램을 실행중인 상태로 놔두세요. 그리고 프로그램 실행에 문제가 있을떄 당신이 볼수 있도록 해 놓으세요.
또한 당신은데이타가 재할당 될때 더 심각한 로드가 걸릴때 영향도를 최소화 하기 위해서 sleep 이 호출을 할수 있습니다.
재할당 하는것은 기본적으로 한 노드에서 다른 노드로 Hash slot 을 이동시키는것을 의미 합니다다. 이것은 redis-trib 유틸을 이용하여 클러스터를 만드는 작업과 같습니다.
재할당 하기 위해 이렇게 치면 됩니다.
./redis-trib.rb reshard 127.0.0.1:7000
당신은 단지 이동시킬 노드를 지정하면 됩니다. redis-trib 유틸은 자동으로 나머지 노드들을 찾아냅니다.
일반적으로 redis-trib를 이용한 재할당은 오로지 관리자가 개입을 해야 합니다. 당신은 단지 다른 노드로 데이타의 5%만 이동하라고 말할순 없습니다. (구현은 매우 간단하지만)
떄문에 이렇게 질문이 시작됩니다. 얼마나 많은 데이타를 재할당 하려고 합니까?
How many slots do you want to move (from 1 to 16384)?
우리는 이 예제가 sleep 을 호출하지 않고 중요한 키를 포함하고 있는 1000 Hash slot들을 재할당 하려고 합니다.
그렇다면 redis-trib 는 재할당할 타켓을 정확하게 아는것이 필요하고 이것은 Hash slot 을 받을 노드를 알아야 합니다. 나는 첫번째 마스터 노드를 사용할 것 입니다. 이것은
127.0.0.1의 7000번 포트를 사용하고 있고 인스턴스의 노드 아이디가 필요 합니다. 이 값은 이미 redis-trib 에 의해 출력되어 있고 아래의 명령어로 찾을수 있습니다.

$ redis-cli -p 7000 cluster nodes | grep myself
97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master – 0 0 0 connected 0-5460
내 목표 노드의 아이디는 97a3a64667477371c4479320d683e4c8db5858b1 입니다.
지금 당신은 이렇게 물을것 입니다. 당신이 옮기가 원하는 키들의 노드가 뭐냐고. 그에 나는 단지 모든 마스터 노드에서 약간의 Hash slot들을 옮기기 위한다고 대답할것 입니다.
마지막 확인을 한뒤에 아마 당신은 redis-trib 가 해당 노드에서 다른 노드로 이동시키는 메시지를 보실수 있을껍니다. 그리고 키가 한족에서 다른쪽으로 이동할때 점(.) 이 프린트 되는것을 볼수 있을껍니다.
재분배 작업이 일어나는 동안 당신은 당신의 예제 프로그램이 실핼되는데 문제가 없는것을 볼수 있을껍니다. 당신은 원한다면 재분배 하는 동안 정지후 다시 시작을 시킬수 있습니다.
샤딩이 끝나면 당신은 클러스터의 상태를 아래와 같은 명령어로 할수 있습니다.
./redis-trib.rb check 127.0.0.1:7000
모든 슬론의 상태는 체크 됩니다. 그러나 지금 마스터 127.0.0.1:7000 는 더 많은 Hash slot 을 가지고 있는것을 확인할수 있다.

재분배 작업에 관하여 설명

재분배 작업은 파라메터를 따로 입력할 필요 없이 자동으로 진행이 된다. 하지만 아래에 명령어를 몇가지 더 설명해 두었습니다.
./redis-trib.rb reshard : –from –to –slots –yes
만약 당신이 종종 재분배 작업을 한다면 어느정도는 자동화 할수 있습니다. 그러나 일반적으로 redis-trib 를 이용한 클러스터의 재분배 라던지 키들이 클러스터 노드에 걸쳐 슬롯에
잘 분배되어 있는지 자동으로 체크할수 있는 방법은 없습니다. 이 기능은 미래에 언젠가 추가 되겠죠. (ㅎㅎ)

좀더 흥미있는 예제를 봅시다.

처음 우리가 예제로 사용한 어플리케이션을 별로 좋지 않았습니다. 이것은 클러스터에 체크하는 기능없이 그냥 데이타를 쓰는 어플리케이션 이었죠.
우리가 주의깊게 봐야할 사항은 클러스터에 키명 예를들어 foo 에서 40까지 모든 키를 쓰는 과정만 볼수 있고 모든것을 알수는 없습니다.
그래서 redis-rb-cluster 저장소 안에는 좀더 재미있는 어플리케이션이 있는게 그것은 consistency-test.rb 입니다. 이것은 카운터를 저장할때 쓰이고 기본값은 1000 이며
INCR 명령어를 사용하여 순서대로 카운터를 증가 시킵니다.
때문에 그냥 쓰기 전에 어플리케이션에 아래의 두가지를 추가 시키도록 합시다.

응용프로그램에서 카운터를 업데이트 하는것을 INCR 을 사용해서 하도록 합시다.
이것은 또한 모든 쓰기를 하기 전에 메모리 안에 어떠한 값이 있는지 체크하고 비교 하도록 합시다.

이것은 무었을 의미하냐 하면 이 어플리케이션은 심플하게 일관성을 체크할수 있는 것이다. 그리고 이것은 만약 클러스터가 어떠한 데이타 쓰기가 실패 하거나 또는 승인되지 않은 데이타를
쓸때 당신에게 알려줄수 있습니다. 첫번째 케이스에서 카운터에 어떤값이 들어있는지 알수 있고 그것은 아마 우리가 기억하고 있는 값보다 작을것입니다다. 두번째 케이스에서는 이 값이 커질것입니다.
consistency-test 어플리케이션이 실행되는동안 매초마다 데이타가 출력될 것입니다.

$ ruby consistency-test.rb
925 R (0 err) | 925 W (0 err) |
5030 R (0 err) | 5030 W (0 err) |
9261 R (0 err) | 9261 W (0 err) |
13517 R (0 err) | 13517 W (0 err) |
17780 R (0 err) | 17780 W (0 err) |
22025 R (0 err) | 22025 W (0 err) |
25818 R (0 err) | 25818 W (0 err) |
이 라인들은 지금 수행되고 있는 읽기 쓰기가 수를 보여줍니다 그리고 오류의 수도 같이 보여줍니다. (시스템의 오류 때문에 쿼리가 실행되지 않음)
만약 이상한점이 발젼괴면 새로운 라인이 출력 됩니다. 이게 어떤 상황 이냐면 예를들어 프로그램이 동작하는 중에 카운터를 수동으로 리셋하면

$ redis 127.0.0.1:7000> set key_217 0
OK

(in the other tab I see…)

94774 R (0 err) | 94774 W (0 err) |
98821 R (0 err) | 98821 W (0 err) |
102886 R (0 err) | 102886 W (0 err) | 114 lost |
107046 R (0 err) | 107046 W (0 err) | 114 lost |
카운터 값을 원래 값인 144에서 0으로 설정하면 프로그램은 144값이 사라졌다고 리포팅을 해줍니다. (INCR 명령어는 클러스터에 저장되지 않습니다.)
이 프로그램은 훨씬 더 재미있는 테스트 상황이 있습니다. 우리는 이 프로그램을 Redis 클러스터의 페일오버를 테스트 하는데 사용헤보겠습니다.

페일오버 테스트

확인할점 : 당신은 새로운 창을 열어서 일관성을 확인하는 테스트 어플리케이션을 실행시켜야 합니다.
페일오버를 발생시키기 위해서 우리는 제일 간단한 방법인 싱글 마스터 서버에서 싱글 프로세스에 오류를 내는 방식을 사용할것입니다. (이것은 가장 심플한 시스템 장애의 예가 된다)
(마스터 슬레이브 들의 클러스터 들이 아닌 마스터들로만 구성되어있는 클러스터에서 마스터중 하나에 장애를 발생 시킨다는 이야기인듯)
우리는 클러스터에 장애를 발생시키기 위해 아래의 명령어로 노드의 id 를 알아낼수 있습니다.
$ redis-cli -p 7000 cluster nodes | grep master
3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master – 0 1385482984082 0 connected 5960-10921
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 master – 0 1385482983582 0 connected 11423-16383
97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master – 0 0 0 connected 0-5959 10922-11422
7000, 70001번 그리고 70002번 포트의 마스터가가 있고 이중에 7002번 마스터에 DEBUG SEGFAULT 명령어를 실행시킬 것입니다.
$ redis-cli -p 7002 debug segfault
Error: Server closed the connection
우린 이제 일관성 테스트의 경과를 볼수 있습니다.

18849 R (0 err) | 18849 W (0 err) |
23151 R (0 err) | 23151 W (0 err) |
27302 R (0 err) | 27302 W (0 err) |

… many error warnings here …

29659 R (578 err) | 29660 W (577 err) |
33749 R (578 err) | 33750 W (577 err) |
37918 R (578 err) | 37919 W (577 err) |
42077 R (578 err) | 42078 W (577 err) |
당신은 페일오버를 하는 동안 578 읽기와 577 쓰기가 실패한것을 볼수 있습니다. 그러나 데이타의 일관성은 유지 되었습니다. 이말은 이 튜토리얼에서 처음 Redis 클러스터를 공부하며
이야기 했던 비동기식 데이타 복제 덕분에 예상치 못하게 쓰기 데이타를 잃을수도 있다는 소리 입니다. 우리는 이런 상황이 자주 일어날 가능성이 높다고 말할수는 없습니다. 때문에
Redis 는 클라이언트에게 응답을 주는 동시에 슬레이브로 데이타 복제가 일어납니다. 때문에 데이타를 잃을 가능성은 매우 적습니다. 때문에 사실은 이런 케이스를 발생시키기 어렵지만
불가능 한것을 의미하지는 않습니다. 때문에 Redis 클러스터가 일관성을 보장한다는것은 변하지 않습니다.
우리는 확인해야 할것이 있는데 페일오버가 일어난 후에 클러스터의 설정은 어떻게 하는지 입니다. (즉 문제가 발생한 인스턴스를 다시 시작하고 어떻게 슬레이브로 클러스터에 다시 편입
시킬껀지)
$ redis-cli -p 7000 cluster nodes
3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385503418521 0 connected
a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385503419023 0 connected
97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master – 0 0 0 connected 0-5959 10922-11422
3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master – 0 1385503419023 3 connected 11423-16383
3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master – 0 1385503417005 0 connected 5960-10921
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385503418016 3 connected
클러스터의 상태를 확인하는 명령을 실행하면 나오는 결과를 봅시다
지금 마스터들은 포트 7000, 7001 그리고 7005번으로 동작하고 있고 전에는 마스터가 7002번이 있었는데 지금은 7005번이 마스터로 동작하고 있습니다.
이 클러스터 노드들의 정보를 보여주는 결과는 그냥 보기에 매우 보기 힘들어 보이지만 매우 간단합니다 그리고 아래 정보들을 포함하고 있습니다.

노드의 아이디
아이피 주소와 포트명
노드의 위치 : 마스터 인지 슬레이브인지 단독 인지 실패났는지…
만약 해당 노드가 슬레이브이면 해당 마스터 노드의 아이디
응답 속도
마지막 응답 일자
해당 노드의 구성 상태 (클러스터의 설명서를 보면 나옴).
해당 노드의 연결 상태
해당 노드에 설정된 슬롯 범위

수동으로 페일오버 하기

가끔 강제로 페일오버 시키는것은 매우 마스터의 문제를 발생시키지 않게하여 매우 유용합니다. 예를들어 마스터 노드중 하나의 Redis 를 업그레이드 할때 강제로 슬레이브중 하나를 마스터로
페일오버 하는것은 매우 좋은 생각입니다.
수동으로 페일오버 하는 기능은 Redis 클러스터에서 CLUSTER FAILOVER 명령어로 사용이 가능합니다. 이것은 슬레이브 노드중 하나에서 마스터로 바꾸기 위해 실행할수 있습니다.
수동 페일오버는 실재로 마스터에서 장애가 나서 장애 조치를 하는것보다 안전합니다. 즉 오류가 발생하여 작업중 데이타를 잃기전에 새로운 마스터에서 기존 작업을 계속 이어나갈수 있도록
모든 데이타의 복제가 완료된 상태일때 새로운 마스터로 바라보도록 클라이언트들을 바꿔줄수 있다는 소립니다.
아래의 로그는 수동으로 페일오버를 시켰을때 슬레이브의 로그입니다.
# Manual failover user request accepted.
# Received replication offset for paused master manual failover: 347540
# All master replication stream processed, manual failover can start.
# Start of election delayed for 0 milliseconds (rank #0, offset 347540).
# Starting a failover election for epoch 7545.
# Failover election won: I’m the new master.
기본적으로 페일오버되는 마스터에 접속한 클라이언트는 작업이 중지됩니다. 이와 동시에 마스터는 슬레이브 에게 복제의 실패한 부분을 보냅니다. 즉 해당 상실된 데이타가 새로운 마스터에 도달할떄
까지 대기하게 됩니다. 이 데이타가 도달하면 페일오버가 시작되게 됩니다. 그리고 페일오버 되기전 마스터는 스위칭 설정이 변경되게 됩니다. 접속했던 클라이언트들이 예전 마스터에서 새로운 마스터로
이동 됩니다.

새로운 서버 추가하기

기본적으로 새로운 서버를 추가하는것은 기본적으로 새로운 비어있는 노드를 추가하고 데이타를 이곳에 재할당 하는것입니다. 이런 경우를 새로운 마스터 또는 새로운 슬레이브를 추가하는 것 이라 합니다.
우리는 먼저 새로운 마스터 인스턴스를 추가하는 것을 시작으로 2가지 경우를 다 확인할 것입니다.
두 경우중에 첫번째로 비어있는 노드를 추가하는 것 입니다.
이경우 간단하게 새로운 노드를 포트 7006으로 다른 노드들의 이전에 사용 되었던 설정중에 포트 부분을 빼고 같게 설정합니다 (우리는 이미 7000에서 7005번으로 6개의 노드를 추가한 상황)
그리고 어떤것을 해야하는지 알아 보도록 하겠습니다.

새로운 터미널을 하나 더 열도록 하겠습니다.
Redis 클러스터를 설치한 디렉토리로 이동 합니다.
디렉토리명 7006을 새로 생성 합니다.
redis.conf 파일을 만들고 다른 노드들과 같게 설정을 하되 포트 번호를 7006번으로 해줍니다.
다 끝나면 해당 명령으로 Redis 서버를 실행 시킵니다…/redis-server ./redis.conf

문제가 셋팅을 했다면 서버가 실행이 될것 입니다.

이제 redis-trib 명령을 이용하여 기존 클러스터에 쉽게 노드를 추가할수 있습니다.
./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
이제 당신은 내가 addnode 명령어를 첫번째 파라메터로 아이피 주소와 새로운 노드의 포트 번호를 적고 클러스터에 포함되어 있는 노드중 하나의 주소와 포트번호를 적어 명령어를 실행한것을
확인할수 있습니다.
사실상 redis-trib 유틸은 당순이 노드정보에 CLUSTER MEET 메시지를 보낸것 뿐 입니다. 또한 redis-trib 는 또한 실행후에 클러스터의 상태를 체크하기 때문에 클러스터에 어떠한 일을
진행 시키거나 내부의 어떠한 일을 하는데 있어 사용하기에 매우 좋은 유틸리티라고 생각 됩니다. (모든 작업을 실행후에 항상 클러스터의 상태를 자동으로 체크해 주니 좋다는 말인듯)

이제 우리는 새로운 노드가 클러스터에 조인이 되었는지 확인이 가능 합니다.
redis 127.0.0.1:7006> cluster nodes
3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master – 0 1385543178575 0 connected 5960-10921
3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385543179583 0 connected
f093c80dde814da99c5cf72a7dd01590792b783b :0 myself,master – 0 0 0 connected
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543178072 3 connected
a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385543178575 0 connected
97a3a64667477371c4479320d683e4c8db5858b1 127.0.0.1:7000 master – 0 1385543179080 0 connected 0-5959 10922-11422
3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master – 0 1385543177568 3 connected 11423-16383

새로운 노드를 슬레이브로 추가하기

새로운 슬레이브 노드를 추가하는 방식은 2가지 방법이 있습니다. 확실한 방법은 redis-trib 를 다시 사용하는 것입니다 하지만 추가로 아래처럼 –slave 옵션을 붙여줘야 합니다.
./redis-trib.rb add-node –slave 127.0.0.1:7006 127.0.0.1:7000
이 명령어는 명확하게 마스터 추가하는 것과 유사합니다. 그래서 우리는 명확하게 어떤 마스터에 슬레이브를 붙일지 적지 않았습니다. 이 경우 redis-trib 는 새로운 슬레이브 노드를 마스터
중에 가장 적은 슬레이브를 가지고 있는 마스터에 붙일것입니다.
그러므로 당신은 명확하게 어떤 마스터에 슬레이브를 붙일지 지정해 줘야 합니다. 예를들어 …

./redis-trib.rb add-node –slave –master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7006 127.0.0.1:7000

이 방법은 새로운 슬레이브노드를 명확하게 특정 마스터에 붙이는 방법입니다.
좀더 수동적인 방법으로 슬레이브를 추가하는 방법이 몇가지 더 있는데 이는 비어있는 마스터를 새로운 노드에 추가하는 것입니다. 그뒤에 CLUSTER REPLICATE 명령어로 슬레이브로 전환이
가능합니다. 이것은 또한 슬레이브 노드가 추가된후 다른 마스터의 슬레이브로도 바꿀수 있습니다.
예를들어 노드 127.0.0.1:7005번 마스터에 슬레이브 노드를 추가하려고 한다면 이 마스터 노드는 이미 11423-16383 범위의 Hssh slot 을 가지고 서비스를 하고 있고 노드의 아이디는
3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 입니다 여기에 새로운 노드를 슬레이브로 추가하기 위해서는 아래의 명령어를 사용하면 됩니다. (이미 비어있는 마스터 노드로 추가되어
있다고 가정함)
redis 127.0.0.1:7006> cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
이게 다다 이제 우리는 새로운 슬레이브 노드를 가질수 있고 동일한 Hash slot 이 설정 되었다 그리고 이미 모든 다른 노드들에서는 해당 리플리카가 설정되었다는 것을 알게 되었습니다.
(다른 노드들의 설정이 업데이트 되는데 몇초정도는 걸린다) 우리는 아래의 명령어로 확인할수 있습니다.
$ redis-cli -p 7000 cluster nodes | grep slave | grep 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
f093c80dde814da99c5cf72a7dd01590792b783b 127.0.0.1:7006 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543617702 3 connected
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543617198 3 connected
3c3a0c 로 시작하는 노드는 2개의 7002(원래있던것), 7006(지금 추가된것)으로 동작하는 슬레이브를 가지고 있습니다.

노드를 삭제하기

노드를 삭제하는 방법은 단지 del-node 명령어를 redis-trib를 이용하여 사용하면 됩니다.
./redis-trib del-node 127.0.0.1:7000
첫번째 파라메터는 클러스터중에 아무 노드나 적으면 되고 두번째 파라메타는 당신이 삭제하기 원하는 노드의 아이디를 적으면 됩니다.
당신은 동일한 방법으로 마스터 노드를 지울수 있습니다. 한가지 확인할것은 마스터노드를 지우기 위해선 꼭 비어있어야 한다는 것 입니다. 만약 마스터 노드가 비어있지 않다면 당신은
다른 모든 마스터 노드들에 데이타를 재할당 한뒤 삭제를 시도해야 합니다. 마스터 노드를 지우는 방법은 슬레이브중에 마스터 노드로 수동으로 페일오버를 시키고 슬레이브중 하나가
마스터로 바뀌면 이제는 슬레이브 이니 비어있지 않아도 삭제가 가능하다. 확실하게 당신의 클러스터안에서 노드를 줄이기를 원할때 별로 도움은 되지 않습니다. 이경우에 재할당이 더
필요합니다.

슬레이브를 마이그레이션 하기

Redis 클러스터에서는 다음 명령어로 다른 마스터의 슬레이브 설정을 하여 쉽게 복제(이동?) 할수있습니다.
CLUSTER REPLICATE
그러나 특별한 시나리오가 있는데 시스템 관리자의 도움을 받지 않고 당신은 하나의 마스터에서 슬레이브를 이동하길 원한다면. 자동으로 슬레이브를 재설정 할수있는데 이것을 슬레이브
마이그레이션 이라고 불리며 Redis 클러스터의 신뢰성이 더 증가합니다.
당신은 슬레이브 마이그레이션에 관해서 Redis 클러스터 설명서 에서 더 자세하게 내용을 알아볼수 있습니다. 여기서는 우리는 오로지 당신이 이것에서 얻어야 하는 중요한 점은 무었인지
일반적인 생각에 관해서 제공할뿐 입니다.
왜 당신이 당신의 클러스터의 슬레이브들을 어떠한 마스터에서 특정 조건에서 이동시키기 원하는지 이유는 일반적인 Redis 클러스터는 슬레이브 복제본들을 할당함으로 오류에 대비할수
있기 때문일 것입니다.
예를들어 클러스터의 모든 마스터는 하나의 단일 슬레이브만 있는 상황에서 만약 마스터와 슬레이브가 동시에 오류가 발생하면 작업을 계속 할수 없습니다. 간단하게 말해서 마스터가
가지고 있던 Hash slot 을 가지고 있는 또다른 인스턴스가 없기 때문이죠. 그러나 netsplits 처럼 일정수의 노드 들이 동시에 단절돠수도 있습니다. 보통 다른 많은 종루의 실패들은
하나의 노드에 하드웨어적이나 소프트웨어적인 실패들이고 이는 매우 주목할만하지만 동시에 일어날 가능성이 거의 없는 오류의 계층이다. 그래서 이것은 너의 클러스터에 모든 마스터에
슬레이브가 존재 한다고 하면 슬레이브는 오전 4시에 죽고 마스터는 오전 6시에 죽는다면 더이상 클러스터는 작동할수 없습니다. (이부분이 좀 어려웠는데 그러니깐 보통은 하드웨어랑
소프트웨어가 동시에 뻗어서 문제가 생길리는 없다 즉 외부에 영향이 아니고서는 Redis 클러스터는 개런티를 할수 있다 뭐 이런뜻으로 이해 했습니다.)
시스템의 신뢰성을 향상시키기 위해서는 우리는는 마스터에 슬레이브를 추가해야 합니다. 그러나 이것은 매우 비용이 많이 듭니다. 슬레이브 마이그레아션은 몇대의 마스터들에 슬레이브를 좀더
추가할수 있습니다. 때문에 당신이 10개의 마스터들에 각각 한개의 슬레이브를 가지고 있다면 합쳐서 20개의 노드가 됩니다. 그러므로 예를들어 3개의 노드를 슬레이브로 추가한다고 하면
당신의 마스터서버중 하나는 한개 이상의 슬레이브를 가지고 있는게 되는것입니다.
슬레이브 마이그레이션은 일어나는 상황중 하나가 만약 마스터 서버가 슬레이브 서버 없이 클러스터에서 빠지게 돠면 안정성에 문제가 생길수도 있기 때문에 여러개의 슬레이브를 가진 마스터의
슬레이브중 하나를 슬레이브가 없는 마스터에 마이그레이션 해주는 경우가 발생을 합니다. 그러니깐 예제로 언급한것 처럼 당신의 슬레이브가 오전 4시에 죽고나면 다른 슬레이브가 그 자리를
대신할것 입니다. 그뒤에 마스터 서버가 오전 5시에 죽으면 이 슬레이브가 대신 클러스터에서 마스터로 승격되어 작업을 계속 수행할것입니다.
그래서 당신은 마이그레이션이 발생하는 짧은 순간에 어떤일이 발생하는지 알아야 합니다.

클러스터는 순간에 슬레이브 마이그레이션을 가장 많은 슬레이브를 가지고 있는 마스터의 슬레이브중에서 시도 합니다.
슬레이브 복제의 좋은점은 당신은 단지 클러스터안에 몇개의 슬레이브를 마스터에 추가해두면 그게 어떤 마스터에 추가해 두던 상관 없습니다. (즉 이미 1-1 상태의 마스터 슬레이브들이 클러스터에 있다고 하면 여기에 추가로 슬레이브를 아무 마스터에나 추가해 두면 클러스터 내에 어떤 마스터는 슬레이브를 하나 이상 가지고 있겠지만 신경쓸꺼 없다는 소리 즉 1-1 상태의 마스터 슬레이브 관계에서 어떠한 슬레이브가 죽어 어떤 마스터는 슬레이브가 없을수도 있는데 아떄 자동으로 남는 슬레이브를 거기에 붙여 준다는 소리같습니다.)
슬레이브 리플리케이션 설정은 cluster-migration-barrier 에서 설정해 줄수 있습닏. 이에관하여 더 알아보고 싶으면 redis.conf 파일에 더 정보가 있으니 살펴 보시면 됩니다.

Redis 클러스터에 있는 노드를 업데이트 하기

슬레이브 노드를 업그레이드 하는것은 매우 쉽습니다. 당신은 단지 노드를 정지하고 새로운 버전의 Redis 로 다시 시작하면 됩니다. 만약 클라이언트들이 슬레이브 노드를 이용해 읽기 작업을 하고
있을때 만약 그중에 하나가 문제가 생긴다면 클라이언트 들은 다른 슬레이브로 접속을 시도할수 있어야 합니다.
마스터를 업그레이드 하는것은 약간 복잡 합니다. 운영환경에서 다음의 방법을 추천합니다.

CLUSTER FAILOVER 을 사용하여 수동으로 업데이트 대상 마스터를 슬레이브중 하나로 페일오버를 시킵니다. (이 문서의 수동 페일오버의 항목을 보시면 됩니다.)
마스터가 슬레이브로 바뀔때까지 기다립니다.
마지막으로 해당 슬레이브를 업그레이드 합니다.
만약 당신이 방금 업그레이드된 노드를 마스터로 사용하고 싶으면 마스터를 업그레이드 한뒤 페일오버를 수동으로 시켜주면 됩니다.

해당 순서를 따라가면 당신은 모든 노드를 업그레이드를 할수 있을것입니다다. (가령 Redis 의 신버전이 나올떄 이렇게 하라는것)

[NoSQL & Cache] Redis vs Memcached ( 왜 Redis 를 사용해야 하는가? )

저는 Memcached 를 이용하여 프로젝트를 한적이 있습니다.
그리고 개인적으로 캐시 솔루션에 관심이 많습니다. (회사에서 하는 업무도 이쪽이 많습니다.)

여튼…

저희 팀원분과 어제 새벽에 Memcached 와 Redis 에 관해 채팅으로 의견을 주고 받다가 팀원분이 한번 읽어보라고 주신 글이 있는데
2014년 10월글 이지만 (아직 Redis 3.0 이 나오기 전글) Redis 와 Memcacheed 의 차이점을 알수있고 가볍게 읽어보기 좋은글 같아서
공유를 하고 제 생각을 조금 넣어서 해석을 해서 포스팅 하니 참고가 되었음 좋겠습니다. (대강 해석 했으니 원문보며 참고만 하세요. ^^)

원문 : http://www.infoworld.com/article/2825890/application-development/why-redis-beats-memcached-for-caching.html

————————————————————————————————————————-

Redis 는 더 강력하고 다루기 쉽기 떄문에 보통 캐시 솔루션을 선택할때 Redis 를 선택합니다, 그러나 Memcached 는 여전히 쓰여지고는 있습니다. (저도 쓰고 있습니다.)

Memcached 와 Redis 중에 어떤것이 더 좋을까? 이것은 최근 데이타 베이스 기반 웹 어플리케이션에 관해서 최대한 성능을 뽑아내기 위헤 토론할떄 항상 나오는 질문 입니다.
이것들은 유명한 캐시 엔진들로 비슷한점도 있지만 매우 중요한 차이점이 있습니다.
하지만 역시 Redis 는 Memcached 보다 더 새롬고 다양한 기능이 있기 때문에 대부분 Redis를 선택 하곤 하지만 그렇지 않은 경우도 있습니다.

유사점들

일단 유사한 부분부터 보도록 하겠습니다.

Memcached 와 Redis 는 in-memory 위에서 동작하는 key-value 스토리지로 둘다 NoSQL 에 속하는 데이타 관리 솔루션 이며 둘다 같은 key-value 데이타 모델을 기반으로 동작합니다.
모든 데이타는 메모리 안에 있으며 이는 때문에 캐시 관점에서 매우 유용합니다. 퍼포먼스 측면에서 두 데이타 스토리지는 처리량이나 지연속도 등 동일한 특성을 나타냅니다.
게다가 in-memory 데이타 스토리지들인 Memcached, Redis 둘다 인기 있는 완성된 오픈소스 프로젝트 입니다.

Memcached 는 원래 2003년에 Brad Fitzpatrick 에 의해 LiveJournal 웹사이트를 위해 개발 되었으며 그뒤로 Memcached 는 C 로 다시 개발되었습니다. (최초에는 perl 로 개발됨) 그리고 공개 되었고 새로운 웹 어플리케이션의 패러다임의 초석이 되었습니다. 그리고 지금까지 Memcached 는 새로운 기능보다는 안정성과 최적화에 중점을 두고 개발되고 있습니다.

Redis 는 2009년에 Salvatore Sanfilippo 애 의해 만들어 졌고 그는 여전히 Redis 의 개발을 리드하는 사람이고 혼자서 프로젝트를 작업하는 사람 입니다.
Redis 는 때로 “약빤 Memcached (ㅎㅎ)” 라고 묘사 됩니다. 이는 Memcached 를 사용하면서 좋은점을 기반으로 개발되었기 떄문 입니다.

Redis 는 Memcached 에 비해 기능이 많아 더 강력하고 다루기 쉽지만 좀더 복잡 합니다.

많은 회사들의 셀수도 없는 어플리케이션의 운영 환경에서 개발자들은 다양한 언어의 클라이언트 라이브러리들을 사용하여 Memcached 와 Redis 를 사용하고 있습니다.
사실상 웹 어플리케이션에서 둘중 하나를 사용하지 않는다는 것은 매우 드문이 입니다.

왜 Memcached 와 Redis 는 왜 엄청 인기가 있는것일까요? 뿐만 아니라 매우 효과적이고 상대적으로 심플한것일까요?
둘중 어떤것이든 개발자가 쉽게 사용하기 위해 고려되어있고 이로인해 불과 몇분만에 어플리케아션에 캐시를 적용할수 있습니다.
이것은 매우 작은 시간만 투자해서 즉시 효과를 볼수있고 일반적으로 정렬에서 성능에 극적으로 영향을 끼치며. (보통 데이타 베이스 기반에서 어떠한 데이타를 select 해올때 많은 비용을 차지하는 부분이 order 부분일 것 입니다. 하지만 이런 in-memory 기반의 Memcached 나 Redis 는 메모리에 저장되어 있어서 매우 빠른 정렬이 가능하다는 이야기 같습니다.)
그것은 마치 마법처럼 성능에 있어 간단한 해결책과 큰 이점을 주고 있습니다.

그러면 언제 Memcached 를 사용해야 할까요?

Redis 는 최근에 나왔고 새로운 기능들에 있어 Memcached와 비교된다. Memcached 보다 Redis 를 선택하는것이 항상 더 좋은 선택 이지만 Memcached 가 더 좋은 두가지의 상황이 있습니다.

첫번째로 작고 변하지 않는 데이타 예를들어 HTML 코드의 부분을 캐싱할때 내부 메모리 관리가 Redis 만큼 복잡하지 않아 능률적이기 떄문에 Memcached 는 메타 데이타에 있어 비교적 작은 메모리를 사용합니다. Memcached 에서 지원하는 유일한 데이타 타입인 String은 오로지 읽기 전용이고 더이상 처리가 필요 없기 때문에 데이터를 저장하기에 좋습니다.

두번째로 Memcached 는 여전히 Redis 에 비해 수평적 확장에서 약간의 좋은점이 있습니다. 기능 구현과 디자인 확장을 하는데 있어서 쉽지만. 사실 Redis 도 이런 목적으로(Memcached 처럼 수평적 확장이 쉽도록) 한대 이상으로 확장을 위한 클러스터링이 3.0 이후에 포함되어 있습니다.

언제 Redis 를 사용해야 할까요?

당신이 일할때 강제적을 Memcachd 를 사용해야 하거나 위의 2가지 사항이 아니고서는 항상 Redis 를 사용하는 것이 맞습니다.

당신을 Redis 를 캐시 용도로 매우 강력하게 사용할수 있고. 예를들어 캐시한 콘텐츠를 미세하게 튜닝하거나 그리고 지속성에 및 전반적인 효율성등을 조정할수 있습니다.

Redis 는 분명 캐쉬관리적인 측면에서 확실하게 우월하며. 캐쉬는 새로운 데이타를 캐시하기 위해 오래된 데이타를 지우는 방식의 메카니즘을 사용하고 있습니다. Memcached 도 데이타 관련 메카니즘은 LRU 알고리즘을 사용하고 있으며 Redis 는 이와는 대조적으로 6가지의 데이타 추출 정책이 있습니다. 또한 Redis 는 좀더 정교한 메모리 관리 방식을 사용한다.

Redis 는 당신이 어떠한 오브젝트들을 캐시할수 있도록 엄청 편리한 기능을 제공하며. 반면 Memcached 는 키의 이름이 250 바이트로 제한 되며 캐시 값의 용량은 1메가바이트로 제한됩니다. (10M였나? 그정도로 늘릴수도 있긴함) 그리고 오로지 문자열만 캐시할수 있다. Redis 는 키명과 값의 용량을 각각 512메가 바이트까지 크게 사용할수 있고 그것들은 안전한 바이너리로 관리 됩니다. Redis 는 6가지의 데이타 형식이 있어서 좀더 정교하고 효율적으로 데이타를 캐시하며 이로인해 어플리케이션 개발자에게 좀더 가능성 있는 세상을 열어줍니다.

대신 직렬화된 오브젝트를 저장해야하고 개발자는 Redis 의 해시 를 이용해 오브젝트의 필드 그리고 값을 유니크 하게 관리할수 있습니다. Redis의 해시는 개발자들이 필요한 기능을 제공합니다. 전체 문자열을 가지고 온다던지 역직렬화하고 그것의 값을 업데이트 하고 다시 시리얼 라이즈를하고 또 문자열을 바꾼다던지 자잘한 모든 업데이트 기능을 지원합니다. 그리고 그것은 작은 리소스를 소비하여 개발자의 퍼포먼스를 낼수 있게 한다는 것이좋습니다. 또한 Redis 가 제공하는 다양한 데이타 타입이 있는데 List 그리고 Set 이 있고 더 복잡한 캐시관리에 사용될수 있습니다.

또 다른 Redis 의 중요한점은 데이타를 저장하는 방식이 불투명하지 않다는 것입니다. 이 뜻은 데이타를 저장할떄 서버가 데이타를 직접적으로 조작한다는 것으로 Redis 에 있는 160가지 이상의 명령들은 서버측 내장 명명어로 데이타 를 처리하고 조직하며 이들의 내장된 명령어와 유저의 스크립트 들은 당신에게 손쉽게 데이타 처리를 다른 시스템에 네트웍으로 전달하지 않고 직접적으로 핸들링 할수 있도록 제공합니다.

Redis 는 캐시의 지속성(유사시에 데이타 백업의 의미) 옵션을 제공합니다, 이는 서버가 의도 되지 않게 오류가 나거나 셧다운이 일어났을때 재기동하면서 다시 복구될수있게 디자인 되었으며. 우리는 데이타를 캐시 하는동안 캐시는 휘발성의 성격이지만 이 데이타를 디스크에 저장 시킴으로서 캐싱 시나리오에서 매우 도움이 될수 있습니다. 그러니까 캐시 데이타가 Redis 에서 따로 백업 용도로 저장한 디스크에 존재하면 Redis 서버가 재시작후에 캐쉬를 다시 메인 데이타 스토리지에서 가지고 오는 부하를 덜수 있다는 소리 입니다.

마지막으로 Redis 는 리플레케이션을 제공 합니다. 리플리케이션은 어플리케이션에서 안정적인 캐시를 제공합니다. 생각해보면 캐시의 장애는 오로지 매우 짧은 순간에 유저경험이나 어플리케이션의 성능적인 측면에서 검증이 된 솔루션을 가지고 캐시의 내용 및 가용성을 보장 합니다. 이것은 대부분의 케이스에서 가장 좋은 장점으로 작용 합니다. (아 이부분은 뭔소린지 해석이 잘….. 대략 리플리케이션을 사용할수 있어서 장애를 최소화 할수 있다는 이야기 입니다.)

오픈소스 소프트웨어는 오늘날에 사용할수 있는 최고의 기술을 계속 제공 합니다. 캐시로 인해 어플리케이션의 성능을 개선할떄 Redis 와 Memcached 는 자연적으로 캐시 솔루션에 후보에 올라갔습니다. 그렇지만 좀더 괜찮은 기능과 좀더 발전된 디자인 으로 설계된 Redis 가 당신의 모든 시나리오에서 첫번쩨 선택이 될 것입니다.

————————————————————————————————————————-

지금은 유일하게 Redis 대비 Memcached 의 장점이었던 수평적 확장도 Redis 3.0 이 나오면서 사라지게 되었네요.. ㅜㅜ
결론은 닥치고 Redis 써라 !

[Hbase] 구동시에 regionserver 에서 마스터서버 주소를 localhost 로 접속을 시도할 경우 (Attempting connect to Master server at localhost)

네이버의 pinpoint 를 도입하기 위해 테스트를 하려고 하던중 이었다.

pinpoint 를 설치하기 위해서는 일단 hadoop + zookeeper + hbase 를 설치해야하는 상황…
일단 hadoop 부터 zookeeper 까지는 문제 없이 설치를 완료 했다.

하지만 hbase 는 자꾸 문제가 발생 ….

일단 문제가 hbase 의 regionserver 가 구동시에 master 서버로 접속을 해서 validation 체크를 해야 하는데
자꾸 로그상으로 regionserver 에서 master 서버의 아이피를 localhost 로 보고 있는…

Exception log를 보면

이런식 으로… Attempting connect to Master server at localhost,60000 을 보고 있다.

hbase 설정 파일에는

분명히 마스터로 namenode 를 잡아 놨는데도 저렇게 바라보니 정말 혼란스러웠다..
구글링을 해봤지만 쓸만한 답변은 찾을수가 없었다. (대부분 위에 설정 파일처럼 hbase.master 를 설정 해보라는 것)

이 상태에서 zookeeper 로 hbase 상태를 확인해 보면

이렇게 아무것도 안나오는 상황…

일단은 각 regionserver 들에 HRegionServer 프로세스가 잘 뜨고 있고 namenode 인 마스터 서버에도 HMaster 가 잘뜨고
있기 때문에 결국은 남은것은 host 설정 문제 뿐 이었다… (조언을 부탁 드린 네이버 분들도 이 부분을 알려주심)

이쪽으로 구글링을 집중적으로 해보았다.
결과는 127.0.0.1 localhost 설정을 없애 보라는것

일단 /etc/hosts 내용을 보면

* 참고사항
1. 총 서버는 4대
2. 각 서버의 호스트 명은 hadoop-1, hadoop-2, hadoop-3, hadoop-4
3. 아이피는 내부 아이피 이니 해킹 시도는 꿈에도 꾸지 말것!

이렇게 되어있고 namenode 가 마스터 이다.
그리고 regionserver 는 datanode01 ~ 03 이다.

여기서

이 부분을 이렇게 주석 처리 하고

이렇게 각 서버별로 서버명과 자신의 아이피를 설정해준뒤

zookeeper 클라이언트 에서 /hbase 삭제후에 다시 hbase 기동!

기동하면서 regionserver 로그를 tail 로 찍어놓고 보면

master 서버의 주소를 의도한대로 hadoop-1로 보고 있는것을 알수 있다.

잘 실행이 되는것을 알수 있다.

휴… 해결.. 이제 pinpoint 설치하러 가야겠다.

그런데 이 설정으로 localhost 127.0.0.1 설정이 없어졌는데..
이로 인해 문제가 다른곳에서 발생을 할지 … 좀 걱정이긴 합니다… 따라서… 좀 써보다가 문제가 발생하면
다시 포스팅 하도록 하겠습니다…

———————–추가————————————————————

아무래도 localhost 를 없앤것이 좀 찝찝한 나머지 좀 테스트를 해보았습니다.
결론적으로 말하면 linux 에서는 127.0.0.1 localhost 설정이 hosts 파일에 없어도 기본적으로 localhost 를 127.0.0.1
로 인식하는거 같네요.

이런식으로 인식이 됩니다.

그래도 혹시 어플리케이션 중에 hosts 파일의 localhost 설정을 사용하는 것이 있을수 있기 때문에
각 서버의 /etc/hosts 파일에 localhost 를 추가해 주기로 했습니다.

위의 설정의 요는 localhost 가 127.0.0.1 이 아닌 본인 서버의 아이피만 바라보면 되기 때문에

hadoop-1 서버

hadoop-2 서버

hadoop-3 서버

hadoop-4 서버

이렇게 추가시켜 주었고 잘 동작 하네요..

도움이 되시길 바랍니다.