Redis๋Š” ์™œ ์ด๋ ‡๊ฒŒ ๋น ๋ฅผ๊นŒ?

1. In-Memory ๊ธฐ๋ฐ˜

DB ์„ฑ๋Šฅ ์ €ํ•˜(๋ณ‘๋ชฉ ๋“ฑ)์˜ 99%๋Š” ๋””์Šคํฌ I/O์—์„œ ๋ฐœ์ƒํ•œ๋‹ค.

์ œ1๊ณตํ•™๊ด€ 23๋™์—์„œ ๋“ค์—ˆ๋˜ ์šด์˜์ฒด์ œ ๊ฐ•์˜ ์‹œ๊ฐ„์œผ๋กœ ์ž ๊น ํšŒ๊ท€ํ•ด๋ณด์ž. ๋””์Šคํฌ, ํ”ํžˆ HDD๋Š” ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ Page ๋‹จ์œ„๋กœ RAM์— ๊ฐ€์ ธ์™€์„œ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋งŒ์•ฝ ํŠน์ • ํ”„๋กœ์„ธ์Šค๊ฐ€ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์œผ๋ ค๊ณ  ํ•  ๋•Œ, L1/L2/L2 Cache์—์„œ Miss๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ , RAM์—๋„ ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ Page Fault๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

์ดํ›„, ๋””์Šคํฌ์—์„œ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜๋Š” ํŽ˜์ด์ง€๋ฅผ ์ฐพ์•„์„œ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋˜๋Š”๋ฐ, ๋งŒ์•ฝ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ชจ๋‘ Use ์ƒํƒœ๋ผ๋ฉด Replacement Policy์— ์˜ํ•˜์—ฌ Page Replacement๊ฐ€ ์ผ์–ด๋‚œ๋‹ค. ๊ฐ€๋”์”ฉ ์—„์ฒญ ๋ฌด๊ฑฐ์šด ์ž‘์—…์„ ํ•  ๋•Œ๋ฉด ๋””์Šคํฌ๊ฐ€ ๋ฝ๋ฝ ๊ฐˆ๋ฆฌ๋Š” ๋‚ด๋ฉฐ ์‚ด๋ ค๋‹ฌ๋ผ๊ณ  ์™ธ์นœ๋‹ค๋Š” ๊ต์ˆ˜๋‹˜์˜ ๋ง์”€์ด ์ƒ๊ฐ๋‚œ๋‹ค.

๊ทผ๋ฐ ๋„๋Œ€์ฒด ์–ผ๋งˆ๋‚˜ ์†๋„ ์ฐจ์ด๊ฐ€ ๋‚˜๊ธธ๋ž˜ CPU, L1, L2, L3, RAM ๊ทธ๋ฆฌ๊ณ  DISK ๋ ˆ๋ฒจ๊นŒ์ง€ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ผ๊นŒ? ์‹ค์งˆ์ ์ธ ์ˆ˜์น˜๋กœ ์‚ดํŽด๋ณด์ž.

์ €์žฅ์žฅ์น˜์ ‘๊ทผ ์‹œ๊ฐ„ (Latency)
L1 Cache~1 ns
L2 Cache35 ns
L3 Cache1020 ns
RAM (DRAM)50100 ns
SSD (NVMe)50150 ฮผs
HDD510 ms

์œ„ ํ‘œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, RAM์˜ ๋ ˆ์ดํ„ด์‹œ๋Š” HDD๊ฐ€ ์•„๋‹Œ SSD๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•˜๋”๋ผ๋„ ์ตœ์†Œ 1,000๋ฐฐ๊นŒ์ง€ ์ฐจ์ด๊ฐ€ ๋‚˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. RDBMS๊ฐ€ ๋””์Šคํฌ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์œผ๋ ค๋ฉด OS์— read() ์‹œ์Šคํ…œ ์ฝœ์„ ๋ณด๋‚ด๊ณ , ๋””์Šคํฌ์—์„œ ์›ํ•˜๋Š” ํŽ˜์ด์ง€๋ฅผ ์ฐพ์•„ ๋ฉ”๋ชจ๋ฆฌ์— ๋ณต์‚ฌํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์น˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

Redis๋Š” ์ด ๋ชจ๋“  ๊ณผ์ •์„ ์ƒ๋žตํ•œ๋‹ค.

2. Single Thread

ํ”ํžˆ ์„ฑ๋Šฅ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด์„œ๋Š” Multi-Thread๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ, Redis๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ GET/SET ๋“ฑ๊ณผ ๊ฐ™์ด ๊ธฐ๋ณธ์ ์ธ ๋ฉ”์ธ ๋กœ์ง์— ๋Œ€ํ•˜์—ฌ๋Š” Single-Thread ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค. ์™œ ๊ทธ๋Ÿด๊นŒ?

2-1. Context Switching์˜ ํ•จ์ •

์ด ์—ญ์‹œ ์šด์˜์ฒด์ œ ์‹œ๊ฐ„์œผ๋กœ ๋Œ์•„๊ฐ€์•ผ ํ•œ๋‹ค. Thread๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๋ฉด CPU๋Š” ์ด๋“ค์„ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉฐ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋•Œ, ํŠน์ • ์Šค๋ ˆ๋“œ์—์„œ I/O ์ž‘์—…์ด ๋ฐœ์ƒํ•˜๋ฉด Context Switching์ด ์ผ์–ด๋‚˜๊ฒŒ ๋˜๋Š”๋ฐ, ํ•ด๋‹น I/O ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ Thread๊ฐ€ ์‹คํ–‰๋œ๋‹ค.์ด ๊ณผ์ •์—์„œ ์‹คํ–‰ ํ๋ฆ„์˜ ๋ฌธ๋งฅ, ์ฆ‰ ๋ง ๊ทธ๋Œ€๋กœ Context๋ฅผ Switchingํ•˜๋Š” ์ž‘์—…์ด ์ด๋ฃจ์–ด์ ธ์•ผ ํ•˜๊ณ , ์ด ์—ญ์‹œ 1~5 ฮผs์˜ ๋น„์šฉ์ด ์†Œ๋ชจ๋œ๋‹ค. Redis GET์€ ์•ฝ 100 ฮผs, SET์€ ์•ฝ 200~500 ฮผs ์ •๋„์˜ ์‹œ๊ฐ„์ด ์†Œ๋ชจ๋˜๊ธฐ ๋•Œ๋ฌธ์— Switching ๋น„์šฉ์ด ๋” ๋น„์‹ธ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

2-2. Lock-Free

Multi-Thread ํ™˜๊ฒฝ์—์„œ, ๋งŒ์•ฝ ์—ฌ๋Ÿฌ Thread๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ฒŒ ๋˜๋ฉด Race Condition ๋“ฑ์˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Mutex ๋“ฑ์˜ Lock์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ Lock์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ํ•˜๋‚˜์˜ Thread๊ฐ€ Lock์„ ์–ป์—ˆ์„ ๋•Œ, ๋‚˜๋จธ์ง€ Thread๋“ค์€ Blocking, ์ฆ‰ Lock์„ ์–ป์„ ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๊ทน์‹ฌํ•œ ๋ณ‘๋ชฉ์ด ์ƒ๊ธฐ๊ฒŒ ๋œ๋‹ค.

2-3. Atomicity

Single-Thread ํ™˜๊ฒฝ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•œ ๋ฒˆ์— ๋‹จ ํ•˜๋‚˜์˜ ๋ช…๋ น์–ด๋งŒ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค. Redis๋Š” Single-Thread ํ™˜๊ฒฝ์ด๋ฏ€๋กœ Lock์ด ํ•„์š”์—†๊ฒŒ ๋˜๊ณ , ์ด๋กœ์จ Atomicity๋„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

2-ษ‘. Redis 6.0 ์ดํ›„

๋„ˆ๋ฌด ๋งŽ์€ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด I/O ๋‹จ์—์„œ๋„ ๋ณ‘๋ชฉ์ด ๋ฐœ์ƒํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ตœ์‹  Redis๋Š” ๋„คํŠธ์›Œํฌ I/O(์†Œ์ผ“ ์ฝ๊ธฐ/์“ฐ๊ธฐ)์—๋งŒ Multi-Thread๋ฅผ ๋„์ž…ํ•˜๊ณ , ์‹ค์ œ ๋ช…๋ น์–ด ์‹คํ–‰์€ ์—ฌ์ „ํžˆ Single-Thread๋ฅผ ์œ ์ง€ํ•˜์˜€๋‹ค.