์ข์ ์ ์์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ค์ฉ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ ๋ pub/sub์ ๋ํด ์๋นํ ํผ๋์ค๋ฌ์ํฉ๋๋ค.
+1, ๋น๋๊ธฐ libev pub/sub์ ์ด๋ ค์์ด ์์ต๋๋ค.
ng
๋ํด ์ ๊ณ ๋์์ต๋๋ค.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "hiredis/hiredis.h"
#include "hiredis/async.h"
#include "hiredis/adapters/libevent.h"
void onMessage(redisAsyncContext *c, void *reply, void *privdata) {
redisReply *r = reply;
if (reply == NULL) return;
if (r->type == REDIS_REPLY_ARRAY) {
for (int j = 0; j < r->elements; j++) {
printf("%u) %s\n", j, r->element[j]->str);
}
}
}
int main (int argc, char **argv) {
signal(SIGPIPE, SIG_IGN);
struct event_base *base = event_base_new();
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
if (c->err) {
printf("error: %s\n", c->errstr);
return 1;
}
redisLibeventAttach(c, base);
redisAsyncCommand(c, onMessage, NULL, "SUBSCRIBE testtopic");
event_base_dispatch(base);
return 0;
}
Ubuntu 14.04์์ ์ด ์์ ๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ์ปดํ์ผํ๋ ค๋ฉด libevent-dev
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค. ๋ํ ์ปดํ์ผํ๋ ๋์ -levent
ํ๋๊ทธ๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค.
๋ฌธ์์ ๋ฌธ์ ๋ ๊ตฌ๋ ํ ์ ์์ง๋ง ๋ค๋ฅธ ์ด๋ฒคํธ๋ฅผ ๊ตฌ๋ ํ๋ ๊ฒ ์ธ์๋ ์๋ฌด ๊ฒ๋ ํ ์ ์๋ค๋ ๋ด์ฉ์ด ์ด๋์๋ ์์ฑ๋์ง ์์๋ค๋ ๊ฒ์ ๋๋ค.
๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ์๋ํ์ญ์์ค.
redisAsyncCommand(c, onMessage, NULL, "SUBSCRIBE testtopic");
redisAsyncCommand(c, onAnotherMessage, NULL, "SUBSCRIBE anothertopic");
redisAsyncCommand(c, onReply, NULL, "SET toto 5");
redisAsyncCommand(c, onReply, NULL, "PUBLISH testtopic \"hello\"");
redisAsyncCommand(c, onReply, NULL, "GET toto");
๊ทธ๋ฆฌ๊ณ 2๊ฐ์ ์ฒซ ๋ฒ์งธ ๋ช
๋ น๋ง ์๋ํฉ๋๋ค. ๋ค๋ฅธ ํ๋๋ REDIS_OK
์๋ตํ์ง๋ง onReply()
์ฝ๋ฐฑ์ NULL
์๋ต์ ๋ฐ์ต๋๋ค.
์ผ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ํํ๋ ์ ์ผํ ๋ฐฉ๋ฒ์ 2๊ฐ์ redis ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ํ๋๋ ๊ตฌ๋ (๋ฐ MONITOR)์ฉ์ด๊ณ ๋ค๋ฅธ ํ๋๋ ๋๋จธ์ง์ฉ์ ๋๋ค. ์ด ์ ํ ์ฌํญ์ ๋ฐ์ํ๋๋ก ๋ฌธ์๋ฅผ ์ ๋ฐ์ดํธํด์ผ ํ ๊น์?
EACH API์ ๋ํ ๋ฌธ์๊ฐ ์์ต๋๊น?
์์ผ์ด ๊ฒฐ๊ตญ ๋ซํ ๋ ์ด๋ฒคํธ๋ฅผ ์ด๋ป๊ฒ ์บก์ฒํฉ๋๊น?
์์ผ์ด ๊ฒฐ๊ตญ ๋ซํ ๋ ์ด๋ฒคํธ๋ฅผ ์ด๋ป๊ฒ ์บก์ฒํฉ๋๊น?
์๋๋ฉด ๋น ๋ฅด๊ฒ ์๊ฐ ์ด๊ณผ๋ฅผ ๊ฐ์งํ๊ณ ์ ์ฐ๊ฒฐ์ ๋ค์ ์คํํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น? ์๋ฅผ ๋ค์ด, ๊ทธ ์ฌ์ด์ ์๋ ๋ฐฉํ๋ฒฝ์ด ์ฐ๊ฒฐ์ ๋ซ๊ณ ๊ทธ ํ์ ํจํท์ ์ญ์ ํ๋ ๊ฒฝ์ฐ์ ๋๋ค.
ํด๋น ์ฐ๊ฒฐ์์ ๊ตฌ๋ ๋ง ํ๋ฉด ์๊ฐ ์ด๊ณผ๋ฅผ ํ์ธํ๊ธฐ ์ํด ๋ฌด์ธ๊ฐ๋ฅผ ๋ณด๋ด๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. ๋ํ TCP keepalives๋ ASYNC์ ํจ๊ป ์กด์ฌํ์ง ์๋ ๊ฒ ๊ฐ์ผ๋ฉฐ ์ด์จ๋ ์ด๋ค์ ์๋ฅผ ๋ค์ด ๋์ปค ์ปจํ ์ด๋ ๋ด๋ถ์ Linux์์ ์ ๋๋ก ๊ตฌ์ฑํ๊ธฐ ์ด๋ ต์ต๋๋ค(์: ๊ฐ๊ฒฉ, ์ฌ์๋ ๋ฑ).
์ผ๋ฐ์ ์ผ๋ก TCP ์์ผ์ ์ฌ์ฉํ๋ฉด ์์ผ์์ ์งง์ ์ฝ๊ธฐ/์ฐ๊ธฐ ์๊ฐ ์ด๊ณผ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฉฐ ๋ฌด์ธ๊ฐ๋ฅผ ๋ณด๋ธ ํ ์๊ฐ ์ด๊ณผ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ณ ๋น ๋ฅด๊ฒ ๋ค๋ฅธ ์๋ฒ์ ๋ค์ ์ฐ๊ฒฐํ๊ฑฐ๋ ๋ค๋ฅธ ์์ ์ ์๋ํ ์ ์์ต๋๋ค...
ping ๋ช ๋ น์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ณด๋ด๊ณ ์ฐ๊ฒฐ ํด์ ๋ฅผ ํธ๋ฆฌ๊ฑฐํ๋๋ก ์ฝ๊ธฐ/์ฐ๊ธฐ ์ ํ ์๊ฐ์ ๊ตฌ์ฑํ ์ ์๋ ๋ค๋ฅธ ๊ฒ์ด ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
@Gerporgl
๋ด ์์ ์ ๊ตฌํ์์ redisAsyncSetDiconnectCallback์ ํ์ฉํ์ผ๋ฉฐ ์ด๊ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง์ ๋ํ ๋ฉ์ปค๋์ฆ์ ์ฐ๊ตฌํ์ง ์์์ต๋๋ค.
https://github.com/nidhhoggr/twemproxy_sentinel/commit/602e07cfdbd57a307ff008e8e9d41909ac34b004
์ ๊ฒฝ์ฐ์๋ ์ฐ๊ฒฐ ํด์ ์ด๋ฒคํธ๊ฐ ๋ด๊ฐ ํญ์ "์๋ ์ฐ๊ฒฐ ํด์ "๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒฝ์ฐ์ ๋ํด ์ถฉ๋ถํ ๋นจ๋ฆฌ(๋๋ ์ด๋ค ๊ฒฝ์ฐ์๋ ์ ํ ๋ฐ์ํ์ง ์๋) ๋ฐ์ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฝ๋๋ค(5์๊ฐ ์ด์ ๊ธฐ๋ค๋ ธ์ต๋๋ค. ๋ช ๋ถ ๋์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ง ๋ชปํ์ง๋ง 10-15๋ถ ํ์ ๋ง์นจ๋ด ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ต๋๋ค)
์ฃผ์ ์ ๋ํด ์กฐ๊ธ ๋ ์ฝ์ ํ ๊ตฌ๋
ํ๋ ๋์ ์ฌ์ ํ PING ๋ช
๋ น์ ์ํํ ์ ์๋ค๋ ๊ฒ์ ์๊ฒ ๋์๊ณ ๊ฒ์๋ ๋ฉ์์ง์ธ ๊ฒ์ฒ๋ผ ์์ ์ PING ์๋ต ์ด๋ฒคํธ๋ฅผ ๊ตฌ๋
ํ ์ ์๋ค๊ณ ์ธ๊ธํ๋ ์ด ๊ฒ์๋ฌผ์ ๋ฐ๊ฒฌํ์ต๋๋ค.
https://github.com/redis/hiredis/issues/351
๊ธฐ๋ณธ์ ์ผ๋ก ์ง๊ธ ์ ์๋ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ๊ฒ์ ์๋ฅผ ๋ค์ด 1์ด ๊ฐ๊ฒฉ์ผ๋ก PING์ ๋ณด๋ด๋ ๊ฒ์ด๋ฉฐ, ๋ ์ด์ ํ ์๋ต์ ๋ฐ์ง ๋ชปํ๋ฉด(๋๋ ํน์ ํ์ฉ ํ๊ณ ์๊ณ๊ฐ์ ํ์ฉํ๋ฉด) ์ฐ๊ฒฐ์ด ๋์ด์ก๋ค๊ณ ๊ฐ์ ํ๊ณ ์ ๋ฆฌ๋ฅผ ์ํํ ๋ค์ ๋ค์ ์ฐ๊ฒฐํฉ๋๋ค. ํจ์ฌ ๋ ๊ฐ๋ ฅํ๊ณ ๋น ๋ฅธ ๊ฒ ๊ฐ์ต๋๋ค.
libevent ๋ฐ hiredis๋ฅผ ์ฌ์ฉํ๋ฉด ์ผ๋ฐ ๋ฉ์์ง ์ ๋ฌ์ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ฉด์ PING์ ๋ํ ํ์ด๋จธ ์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ์ฌ ์์ ํ ๋น๋๊ธฐ ๊ตฌ๋ ๊ตฌํ์ ์ํํ ์ ์์ต๋๋ค.
@Gerporgl
์ด๊ฒ์ ๋งค์ฐ ๋์์ด๋์์ต๋๋ค!
ํน์ ํค ๊ณต๊ฐ ์ด๋ฒคํธ ์๋ฆผ์ ๋ํด ๋์ผํ redisAsyncCommand/Async ์ปจํ
์คํธ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ๋ ค๊ณ ํ์ต๋๊น?
๋๋ ๊ทธ ๋ถ๋ถ์ด ์๋ํ๋๋ก ๋
ธ๋ ฅํ๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ถํํ๋ ๋ฉ์์ง๋ฅผ ๋ฐ์ง ๋ชปํฉ๋๋ค.
์ด๊ฒ์ ์๋ ํ์ต๋๊น?
redis-cli config set notify-keyspace-events KEA
redisAsyncCommand(c, subscribeCallback, NULL, "PSUBSCRIBE __key*__:*");
@joe-at-startupmedia
๊ฐ์ฌ ํด์! ๋๋ ์ด๋ฏธ ์ด๊ฒ์ ์๋ํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ด๊ฐ ์ป๋ ๋ชจ๋ ๊ฒ์ ์ฒซ ๋ฒ์งธ psubscribe ์๋ต์ธ ๊ฒ ๊ฐ์ต๋๋ค.
๋ฐ์ดํฐ์ ์
๋ฐ์ดํธ๋ ์ค์ ๋ก ์ฝ๋ฐฑ์์ ์์ ๋์ง ์์ต๋๋ค.
์ํ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
`
๋ฌดํจ์
onPubsubMessage(redisAsyncContext *c, ๋ฌดํจ *์๋ต, ๋ฌดํจ *privdata)
{
redisReply *r = (redisReply *) ๋ต์ฅ;
if (์๋ต == NULL) ๋ฐํ;
/* What if reply type is something else... */
if (r->type == REDIS_REPLY_ARRAY) {
for (int j = 0; j < r->elements; j++) {
if (r->element[j]->type == REDIS_REPLY_STRING) {
myPubsubFile.open(PUBSUB_FILE, fstream::in | fstream::out | fstream::app);
myPubsubFile << r->element[j]->str << endl;
myPubsubFile.close();
} else if (r->element[j]->type == REDIS_REPLY_INTEGER) {
cout << "Integer : "<< r->element[j]->integer << endl;
}
}
}
return;
}
๋ฌดํจ์
onKeyspaceMessage(redisAsyncContext *c, ๋ฌดํจ *์๋ต, ๋ฌดํจ *privdata)
{
redisReply *r = (redisReply *) ๋ต์ฅ;
if (์๋ต == NULL) ๋ฐํ;
cout << "Got keyspace event notification from REDIS.. " << endl;
/* What if reply type is something else... */
if (r->type == REDIS_REPLY_ARRAY) {
cout << "Type is an array.. " << endl;
cout << "Number of elements here: " << r->elements << endl;
for (int j = 0; j < r->elements; j++) {
cout << "\t\t Type for element : " << r->element[j]->type << endl;
if (r->element[j]->type == REDIS_REPLY_STRING) {
cout << "\t\t\t" << r->element[j]->str << endl;
} else if (r->element[j]->type == REDIS_REPLY_INTEGER) {
cout << "\t\t\t" << "Integer : "<< r->element[j]->integer << endl;
}
}
} else {
cout << "This is the type for response : " << r->type << endl;
}
return;
}
๋ฌดํจ์*
pubsubRecipient(๋ฌดํจ* ์ธ์)
{
๊ตฌ์กฐ์ฒด event_base *base = event_base_new();
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
if (c->err) {
printf("error: %s\n", c->errstr);
return NULL;
}
redisLibeventAttach(c, base);
redisAsyncCommand(c, onPubsubMessage , NULL, SUBSCRIBE_CHANNEL);
redisAsyncCommand(c, onKeyspaceMessage , NULL, SUBSCRIBE_KEYEVENT);
`
PS REDIS์์ ํค ๊ณต๊ฐ ์๋ฆผ์ ํ์ฑํํ๋ ๊ตฌ์ฑ ๋ถ๋ถ์ ๋ณ๋์ ํ๋ก์ธ์ค์ ์์ต๋๋ค. ๋ณ๋์ ํฐ๋ฏธ๋์์ redis-cli ์ธ์คํด์ค๋ฅผ ์คํํ ๋ ํด๋น ๊ตฌ์ฑ์ ํจ๊ณผ๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์์ ๋๋ฝ๋ ๊ฒ์ด ์์ง๋ง keyevent ๊ตฌ๋ ๋ฌธ์์ด์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
"PSUBSCRIBE 'key*:*'"
ํด๋น ํจํด์ ๋ง๊ฒ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํด์ผ ํ์ง ์์๊น์?
"PSUBSCRIBE __key*__:*"
์ค.. ์ด ํธ์ง๊ธฐ์์ ์ด์ํ ์ผ์ด ๋ฒ์ด์ง๊ณ ์์ต๋๋ค... ๋ด ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ ๋ ํค ๋ฅผ ๋๋ฌ์ผ ๋ฐ์ค์ด ์์์ต๋๋ค.
๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ๋ฌธ์ ๋ ๋ด _ _ ํค * _ _ ํจํด์ ๋๋ฌ์ผ -> ' ' <-(์์ ๋ฐ์ดํ)์ธ ๊ฒ ๊ฐ์ต๋๋ค.
redis-cli๋ ๋ฌธ์ ์์ด ์ด๋ฅผ ์๋ฝํฉ๋๋ค. ๊ทธ๋ฌ๋ redis ๋ช
๋ น์ ํตํด ๋ณด๋ผ ๋ ์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
์ค๋๋ ๋ฌธ์ ๋ฅผ ๊ฒช๊ณ ์์ต๋๋ค. ๋ช ๋ ์ ์ Wiki์ ์์ ๊ฐ ์ถ๊ฐ๋์์ต๋๋ค(@aluiken์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค).
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ