Node-redis: νŒŒμ΄ν”„λΌμ΄λ‹

에 λ§Œλ“  2014λ…„ 01μ›” 13일  Β·  9μ½”λ©˜νŠΈ  Β·  좜처: NodeRedis/node-redis

μ•ˆλ…•ν•˜μ„Έμš” μ—¬λŸ¬λΆ„,

ν”„λ‘œκ·Έλž˜λ° λ°©μ‹μœΌλ‘œ node_redisμ—μ„œ νŒŒμ΄ν”„λΌμ΄λ‹μ„ ν™œμ„±ν™”ν•˜λŠ” 방법은 λ¬΄μ—‡μž…λ‹ˆκΉŒ?

λŒ€λΆ€λΆ„μ˜ 경우 μžλ™μœΌλ‘œ λ°œμƒν•œλ‹€λŠ” μ„€λͺ…μ„œλ₯Ό λ³΄μ•˜κ³  node_redisμ—μ„œ ν”„λ‘œκ·Έλž˜λ° λ°©μ‹μœΌλ‘œ μ‘μš© ν”„λ‘œκ·Έλž¨ μ½”λ“œμ—μ„œ κ°•μ œλ‘œ μ‹€ν–‰ν•˜λŠ” 방법이 μžˆλŠ”μ§€ μ•Œκ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

[ ec2-user@devops ~]$ redis-benchmark -n 100000 -t set, get -P 16 -q -h 10.0.1.10
SET: μ΄ˆλ‹Ή 199600.80 μš”μ²­
GET: μ΄ˆλ‹Ή 193050.19 μš”μ²­

[ ec2-user@devops ~]$ redis-benchmark -n 100000 -t set, get -q -h 10.0.1.12
SET: μ΄ˆλ‹Ή 14098.41 μš”μ²­
GET: μ΄ˆλ‹Ή 13743.82 μš”μ²­

Redis λ…Έλ“œμ—μ„œ 10λ°° 이상 차이가 λ‚©λ‹ˆλ‹€.

감사 ν•΄μš”,
λ“œλ―ΈνŠΈλ¦¬

Feature Request fixed / done

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

λͺ¨λ“  λͺ…령은 "νŒŒμ΄ν”„λΌμΈ"으둜 μ „μ†‘λ˜μ§€λ§Œ λ‹€μŒ 쀑 ν•˜λ‚˜ λ˜λŠ” 두 가지 이유둜 인해 λ™μΌν•œ νŒŒμ΄ν”„λΌμΈ μ“°κΈ° ν”„λ ˆμž„μœΌλ‘œ μ „μ†‘λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

  1. sismember에 λŒ€ν•œ μ½œλ°±μ€ hgetall ν˜ΈμΆœμ„ ν˜ΈμΆœν•˜λŠ” κ²ƒμ΄λ―€λ‘œ 주어진 sismember ν˜ΈμΆœμ— λŒ€ν•΄ μ΄λŸ¬ν•œ λͺ…령이 ν•¨κ»˜ νŒŒμ΄ν”„λΌμΈλ˜λŠ” 것을 μ•”μ‹œμ μœΌλ‘œ λ°©μ§€ν•©λ‹ˆλ‹€. Redisκ°€ 응닡할 λ•ŒκΉŒμ§€ 콜백이 ν˜ΈμΆœλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  2. base 및 client κ°€ λ‹€λ₯Έ Redis ν΄λΌμ΄μ–ΈνŠΈμΈ 경우 λ™μΌν•œ νŒŒμ΄ν”„λΌμΈμ„ _μ ˆλŒ€_ κ³΅μœ ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

νŒŒμ΄ν”„λΌμ΄λ‹μ˜ 이점을 보렀면 λ™μΌν•œ μ»¨ν…μŠ€νŠΈ*μ—μ„œ λͺ…령을 μ‹€ν–‰ν•΄μ•Ό ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ redis νŒŒμ΄ν”„λΌμ΄λ‹ λ¬Έμ„œμ˜ PING μ˜ˆμ œμ™€ μœ μ‚¬ν•©λ‹ˆλ‹€.

// These commands will all be pipelined together:
client.ping()
client.ping()
client.ping()
client.ping(function () {
  // This would *NEVER* be in the same pipeline frame as the other four because it requires a reply to be received first
  client.ping()
})

* λ˜λŠ” Redisκ°€ μ‘λ‹΅ν•˜λŠ” 것보닀 λΉ λ₯΄κ²Œ μ „μ†‘λœ 경우 λ³„λ„μ˜ μ»¨ν…μŠ€νŠΈμ—μ„œ μ „μ†‘λ˜μ§€λ§Œ 쒅속 μ»¨ν…μŠ€νŠΈμ—λŠ” μ‘λ‹΅ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λͺ¨λ“  9 λŒ“κΈ€

client.multi 및 multi.exec λͺ…령을 톡해 μˆ˜ν–‰λ©λ‹ˆκΉŒ?

μ•ˆλ…•ν•˜μ„Έμš” @saritasa -- νŒŒμ΄ν”„λΌμ΄λ‹μ€ μžλ™μž…λ‹ˆλ‹€. 항상 ν΄λΌμ΄μ–ΈνŠΈ λ‚΄λΆ€μ—μ„œ λ°œμƒν•©λ‹ˆλ‹€. ν™œμ„±ν™”ν•˜κΈ° μœ„ν•΄ multi λ˜λŠ” execλ₯Ό μ‚¬μš©ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.

μ•ˆλ…•ν•˜μ„Έμš” 브라이슀,

  1. λ‚˜λŠ” ν˜Όλž€ μŠ€λŸ½μŠ΅λ‹ˆλ‹€. node_redis λ‚΄λΆ€μ˜ "닀쀑"κΈ°λŠ₯의 λͺ©μ μ€ λ¬΄μ—‡μž…λ‹ˆκΉŒ?
  2. λͺ…령을 μžλ™μœΌλ‘œ νŒŒμ΄ν”„λΌμΈν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ€ λ¬΄μ—‡μž…λ‹ˆκΉŒ?

감사 ν•΄μš”,
λ“œλ―ΈνŠΈλ¦¬

닀쀑 μž‘μ—…μ€ Redis ν”„λ‘œν† μ½œ μ‚¬μ–‘μ—μ„œ κ°€μ Έμ™”μœΌλ©° νŒŒμ΄ν”„λΌμ΄λ‹ μ™ΈλΆ€μ˜ νŠΈλžœμž­μ…˜ λͺ©μ μ΄ μžˆμŠ΅λ‹ˆλ‹€ .

νŒŒμ΄ν”„λΌμ΄λ‹ μž‘λ™ 방식: http://redis.io/topics/pipelining 이것은 ν΄λΌμ΄μ–ΈνŠΈκ°€ λ‹€μŒ λͺ…령을 μž‘μ„±ν•˜κΈ° 전에 응닡을 기닀리지 μ•Šκ³  λ³΄λ‚΄λŠ” 만큼 λΉ λ₯΄κ²Œ Redis에 λͺ…령을 μž‘μ„±ν•˜λŠ” 문제일 λΏμž…λ‹ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈλŠ” μ „μ†‘λœ λͺ…령을 μΆ”μ ν•œ λ‹€μŒ Redisκ°€ μ‘λ‹΅ν•˜λ©΄ μ „μ†‘λœ λͺ…λ ΉμœΌλ‘œ 응닡을 μž¬μ •λ ¬ν•©λ‹ˆλ‹€.

Bryceμ—κ²Œ κ°μ‚¬ν•©λ‹ˆλ‹€. http://redis.io/topics/pipelining이 μž‘λ™ν•˜λŠ” 방식을 μ΄ν•΄ν•©λ‹ˆλ‹€. node.js μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ - μš”μ²­μ΄ νŒŒμ΄ν”„λΌμΈλ˜λ„λ‘ μ½”λ“œλ₯Ό μ–΄λ–»κ²Œ ꡬ성해야 ν•©λ‹ˆκΉŒ?

κ·Έλž˜μ„œ μ•„λž˜ μ˜ˆμ—μ„œ

hgetall 및 만료 - νŒŒμ΄ν”„λΌμΈμ΄ λ˜μ–΄ μžˆμŠ΅λ‹ˆκΉŒ? 호좜 쀑 ν•˜λ‚˜κ°€ 콜백 내뢀에 μžˆμŠ΅λ‹ˆλ‹€.


ν•¨μˆ˜ getByID(ν…Œμ΄λΈ”, ID, λ‹€μŒ) {
if (!success) return setTimeout(ν•¨μˆ˜() {
getByID(ν…Œμ΄λΈ”, 아이디, λ‹€μŒ);
}, 2000);

var end = utils.getEndTime(),
    base = getBase(),
    client = getClient(PK2str(table, id)),
    key = getHashID(table, id);

base.sismember(table, key, function (err, val) {
    if (err || !val) return next();

    client.hgetall(key, function (err, val) {
        if (err || !val) return next(new Error('Expired'), id);

        val = arrays_parse(table, val);
        next(null, val);
        client.expire(key, cfg.ttl.shards);

        if (!exports.silent) {
            profiler.log('cache', {
                'table': table,
                'id': key,
                'method': 'getByID',
                'data': val,
                'time': end()
            });
        }
    });  
});

}

λͺ¨λ“  λͺ…령은 "νŒŒμ΄ν”„λΌμΈ"으둜 μ „μ†‘λ˜μ§€λ§Œ λ‹€μŒ 쀑 ν•˜λ‚˜ λ˜λŠ” 두 가지 이유둜 인해 λ™μΌν•œ νŒŒμ΄ν”„λΌμΈ μ“°κΈ° ν”„λ ˆμž„μœΌλ‘œ μ „μ†‘λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

  1. sismember에 λŒ€ν•œ μ½œλ°±μ€ hgetall ν˜ΈμΆœμ„ ν˜ΈμΆœν•˜λŠ” κ²ƒμ΄λ―€λ‘œ 주어진 sismember ν˜ΈμΆœμ— λŒ€ν•΄ μ΄λŸ¬ν•œ λͺ…령이 ν•¨κ»˜ νŒŒμ΄ν”„λΌμΈλ˜λŠ” 것을 μ•”μ‹œμ μœΌλ‘œ λ°©μ§€ν•©λ‹ˆλ‹€. Redisκ°€ 응닡할 λ•ŒκΉŒμ§€ 콜백이 ν˜ΈμΆœλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  2. base 및 client κ°€ λ‹€λ₯Έ Redis ν΄λΌμ΄μ–ΈνŠΈμΈ 경우 λ™μΌν•œ νŒŒμ΄ν”„λΌμΈμ„ _μ ˆλŒ€_ κ³΅μœ ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

νŒŒμ΄ν”„λΌμ΄λ‹μ˜ 이점을 보렀면 λ™μΌν•œ μ»¨ν…μŠ€νŠΈ*μ—μ„œ λͺ…령을 μ‹€ν–‰ν•΄μ•Ό ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ redis νŒŒμ΄ν”„λΌμ΄λ‹ λ¬Έμ„œμ˜ PING μ˜ˆμ œμ™€ μœ μ‚¬ν•©λ‹ˆλ‹€.

// These commands will all be pipelined together:
client.ping()
client.ping()
client.ping()
client.ping(function () {
  // This would *NEVER* be in the same pipeline frame as the other four because it requires a reply to be received first
  client.ping()
})

* λ˜λŠ” Redisκ°€ μ‘λ‹΅ν•˜λŠ” 것보닀 λΉ λ₯΄κ²Œ μ „μ†‘λœ 경우 λ³„λ„μ˜ μ»¨ν…μŠ€νŠΈμ—μ„œ μ „μ†‘λ˜μ§€λ§Œ 쒅속 μ»¨ν…μŠ€νŠΈμ—λŠ” μ‘λ‹΅ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

이제 μ•Œμ•˜μŠ΅λ‹ˆλ‹€ - κ°μ‚¬ν•©λ‹ˆλ‹€! 이것은 맀우 κ·€μ€‘ν•œ μ˜κ²¬μž…λ‹ˆλ‹€!

node_redis "μžλ™ νŒŒμ΄ν”„λΌμ΄λ‹"은 곡식 redisμ—μ„œ μ°Έμ‘°ν•˜λŠ” νŒŒμ΄ν”„λΌμ΄λ‹μ΄ μ•„λ‹ˆλΌκ³  μƒκ°ν•©λ‹ˆλ‹€.

이 μ‹œκ°„μ„ RTT(왕볡 μ‹œκ°„)라고 ν•©λ‹ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈκ°€ μ—°μ†μ μœΌλ‘œ λ§Žμ€ μš”μ²­μ„ μˆ˜ν–‰ν•΄μ•Ό ν•˜λŠ” 경우(예: λ™μΌν•œ λͺ©λ‘μ— λ§Žμ€ μš”μ†Œλ₯Ό μΆ”κ°€ν•˜κ±°λ‚˜ λ§Žμ€ ν‚€λ‘œ λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό μ±„μš°λŠ” 경우) 이것이 μ„±λŠ₯에 μ–΄λ–€ 영ν–₯을 λ―ΈμΉ  수 μžˆλŠ”μ§€ 맀우 μ‰½κ²Œ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ RTT μ‹œκ°„μ΄ 250λ°€λ¦¬μ΄ˆ(인터넷을 ν†΅ν•œ 맀우 느린 링크의 경우)인 경우 μ„œλ²„κ°€ μ΄ˆλ‹Ή 100,000개의 μš”μ²­μ„ μ²˜λ¦¬ν•  수 μžˆλ”λΌλ„ μ΄ˆλ‹Ή μ΅œλŒ€ 4개의 μš”μ²­μ„ μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
μ‚¬μš©λœ μΈν„°νŽ˜μ΄μŠ€κ°€ 루프백 μΈν„°νŽ˜μ΄μŠ€μΈ 경우 RTTλŠ” 훨씬 더 μ§§μ§€λ§Œ(예λ₯Ό λ“€μ–΄ λ‚΄ ν˜ΈμŠ€νŠΈκ°€ 127.0.0.1을 ν•‘ν•˜λŠ” 0,044λ°€λ¦¬μ΄ˆλ₯Ό 보고함) μ—°μ†μœΌλ‘œ λ§Žμ€ μ“°κΈ°λ₯Ό μˆ˜ν–‰ν•΄μ•Ό ν•˜λŠ” 경우 μ—¬μ „νžˆ λ§ŽμŠ΅λ‹ˆλ‹€.

곡식 redis에 μ˜ν•œ νŒŒμ΄ν”„λΌμ΄λ‹μ΄ μ˜λ―Έν•˜λŠ” 것은 μ—¬λŸ¬ λͺ…령을 κ²°ν•©ν•˜κ³  node_redisμ—μ„œ μ²˜λ¦¬λ˜μ§€ μ•ŠλŠ” RTT둜 μΈν•œ λŒ€κΈ° μ‹œκ°„μ— λŒ€μ‘ν•˜κΈ° μœ„ν•΄ ν•œ 번만 λ³΄λ‚΄λŠ” κ²ƒμž…λ‹ˆλ‹€. 그리고 node_redis의 "automatica pipelining"은 μ‹€μ œλ‘œ Node의 비동기 ν”„λ‘œκ·Έλž˜λ° λͺ¨λΈμ„ μ‚¬μš©ν•˜μ—¬ λ™μ‹œμ— κ°€λŠ₯ν•œ ν•œ λ§Žμ€ λͺ…령을 λ³΄λ‚΄λŠ” κ²ƒμž…λ‹ˆλ‹€.

λ‹€μŒμ€ 이 문제λ₯Ό λ…Όμ˜ν•˜λŠ” 쒋은 κΈ°μ‚¬μž…λ‹ˆλ‹€. http://informatikr.com/2012/redis-pipelining.html

@Vizwind @saritasa .multi와

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰

κ΄€λ ¨ 문제

abhaygarg picture abhaygarg  Β·  5μ½”λ©˜νŠΈ

Mickael-van-der-Beek picture Mickael-van-der-Beek  Β·  6μ½”λ©˜νŠΈ

strumwolf picture strumwolf  Β·  4μ½”λ©˜νŠΈ

shmendo picture shmendo  Β·  6μ½”λ©˜νŠΈ

michaelwittig picture michaelwittig  Β·  3μ½”λ©˜νŠΈ