멤베이스는 멤캐시드 서버에 연결하면 모든 멤캐시드 서버와 "온더와이어" 호환이 가능합니다. 표준 멤캐시드 포트 (2009년에 제가 직접 등록했습니다), 그래서 어떤 "멤캡 가능한" 클라이언트로도 멤베이스에 액세스할 수 있어야 합니다. 이 포트를 지원하는 것은 moxi라는 이름의 멤베이스 프록시이며, 이 프록시는 백그라운드에서 SASL 인증을 수행하고 사용자가 원하는 항목이 포함된 올바른 멤베이스 서버로 요청을 프록시합니다. 멤베이스와 멤캐시드의 차이점 중 하나는 각 항목을 지정된 위치에 저장한다는 점입니다. vbucket 서버에 매핑됩니다. 클러스터를 늘리거나 줄이면 멤베이스가 v버킷을 새 서버로 이동합니다.
공짜 점심 같은 것은 없으므로, moxi를 통해 멤베이스에 액세스하는 것은 개별 노드와 직접 대화하는 것보다 '비용'이 더 많이 듭니다. 저희는 이러한 클라이언트를 "스마트 클라이언트"라고 부릅니다. 멤캐시드 개발자로서 저는 다양한 것들을 테스트해야 했기 때문에 테스트를 쉽게 하기 위해 이러한 라이브러리의 프로토타입을 간단히 해킹했습니다. 처음에는 이 기능으로 libmemcached를 확장하고 싶었지만, 당시에는 용기가 없어서 큰(그리고 위험한) 변화를 시도하지 못했습니다.
현재 라이브러리의 상태는 프로덕션 품질과는 거리가 멀고 지원되는 기능 목록도 최소한의 수준입니다. 그렇다면 왜 지금 발표하는 걸까요? 제가 모든 것을 직접 구현할 시간이 없을 것 같아서 사람들이 라이브러리에 없는 기능이 필요할 때 저와 함께 추가해 주기를 바라는 마음에서입니다.
라이브러리를 100% 콜백 기반으로 설계하고 libevent와 통합하여 애플리케이션에 쉽게 연결할 수 있도록 했습니다.
따라서 TAP 스트림을 만들고 클러스터에서 발생하는 모든 수정 사항을 듣고 싶다고 가정해 보겠습니다. 이렇게 하면 됩니다:
구조체 event_base *evbase = event_init();
libmembase_t 인스턴스 = libmembase_create(호스트, 사용자명, 패스워드, 버킷, evbase);
libmembase_connect(인스턴스);
라이브러리_멤버베이스_탭_필터_필터;
libmembase_callback_t callbacks = {
.tap_mutation = 탭_변이
};
libmembase_set_callbacks(인스턴스, &콜백);
libmembase_tap_cluster(인스턴스, 필터, 참);
그런 다음 탭 콜백 함수를 다음과 같이 구현합니다:
*데이터, 크기_t n바이트, uint32_t 플래그, uint32_t 확장, const void *es, 크기_t 네스)
{
// 오브젝트로 원하는 대로 작업하기
}
전체 클러스터를 탭하기 위해 필요한 것은 이것뿐입니다 :-) 이 예제를 확장하여 여러 버킷을 사용할 수 있습니다.
구조체 event_base *evbase = event_init();
libmembase_t 인스턴스1 = libmembase_create(호스트, 사용자명, 패스워드, 버킷1, evbase);
libmembase_t 인스턴스2 = libmembase_create(호스트, 사용자명, 패스워드, 버킷2, evbase);
libmembase_connect(instance1);
libmembase_connect(instance2);
라이브러리_멤버베이스_탭_필터_필터;
libmembase_callback_t callbacks = {
.tap_mutation = 탭_변이
};
libmembase_set_callbacks(instance1, &콜백);
libmembase_set_callbacks(인스턴스2, &콜백);
libmembase_tap_cluster(instance1, filter, false);
libmembase_tap_cluster(instance2, filter, false);
이벤트_베이스_루프(evbase, 0);
인스턴스 핸들은 콜백 함수에 전달되므로 각 변이 이벤트가 어느 버킷에 속하는지 알 수 있어야 합니다.
앞서 말했듯이 API의 모든 함수는 콜백 기반이므로 객체를 검색하려면 다음에 대한 콜백을 등록해야 합니다. get
전화하기 전에 libmembase_mget
. Ex:
.get = get_callback
};
libmembase_set_callbacks(인스턴스, &콜백);
libmembase_mget(instance, num_keys, (const void * const *)keys, nkey);// 자체 이벤트 루프를 실행하고 싶지 않다면, 다음 메서드를 호출할 수 있습니다.
// 스풀링된 모든 명령을 실행하고 응답을 기다린 후 실행합니다.
//의 이벤트 루프
libmembase_execute(인스턴스);
get 콜백의 서명은 다음과 같습니다:
size_t nkey, const void *bytes, size_t nbytes, uint32_t flags, uint64_t cas)
{
// 원하는 대로 하세요...
}
그렇다면 지금 라이브러리에서 누락된 것은 무엇일까요?
- 적절한 오류 처리. 지금은 어서트와 abort()를 사용하여 오류 상황을 처리하고 있는데, 이로 인해 애플리케이션이 충돌하게 됩니다... 프로덕션 환경에서는 원치 않으실 겁니다 ;-)
- 타임아웃... 지금은 TCP 시간 초과 시에만 시간 초과됩니다.../.
- 많은 작업! 가져오기/추가/바꾸기/설정만 지원합니다...
- 복제본 가져오기...
- v버킷 목록에서 변경 사항을 우아하게 처리하기
- +++
해킹을 해보고 싶으신가요?
libmemcached를 구하고 빌드하는 방법에 대한 자세한 내용은 여기를 클릭하세요.