tarantool์„ ์œ„ํ•œ ์ž์ฒด ์ œํ•œ ๋งŒ๋ฃŒ ๋ชจ๋“ˆ ์ž‘์„ฑ

tarantool์„ ์œ„ํ•œ ์ž์ฒด ์ œํ•œ ๋งŒ๋ฃŒ ๋ชจ๋“ˆ ์ž‘์„ฑ

์–ผ๋งˆ ์ „ ์šฐ๋ฆฌ๋Š” ๊ณต๊ฐ„์˜ ํŠœํ”Œ์„ ์ •๋ฆฌํ•˜๋Š” ๋ฌธ์ œ์— ์ง๋ฉดํ–ˆ์Šต๋‹ˆ๋‹ค. ํƒ€๋ž€ํˆด. tarantool์— ์ด๋ฏธ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•  ๋•Œ๊ฐ€ ์•„๋‹ˆ๋ผ ์‚ฌ์ „์— ํŠน์ • ๋นˆ๋„๋กœ ์ฒญ์†Œ๋ฅผ ์‹œ์ž‘ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์ž‘์—…์„ ์œ„ํ•ด tarantool์—๋Š” Lua๋กœ ์ž‘์„ฑ๋œ ๋ชจ๋“ˆ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ๋ฃŒ. ์ด ๋ชจ๋“ˆ์„ ์งง์€ ์‹œ๊ฐ„ ๋™์•ˆ ์‚ฌ์šฉํ•œ ํ›„ ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์ด ์šฐ๋ฆฌ์—๊ฒŒ ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค. ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์†์ ์œผ๋กœ ์ •๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— Lua๋Š” GC์— ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ ์ฝ”๋“œ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ผ๋ฉด์„œ ์ž์ฒด์ ์œผ๋กœ ์ œํ•œ์ด ์žˆ๋Š” ๋งŒ๋ฃŒ ๋ชจ๋“ˆ์„ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ์—๊ฒŒ ์ข‹์€ ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ tarantool ๋ชจ๋“ˆ์ด์—ˆ์Šต๋‹ˆ๋‹ค. memcached. ์—ฌ๊ธฐ์— ์‚ฌ์šฉ๋œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ํŠœํ”Œ์˜ ์ˆ˜๋ช…, ์ฆ‰ ttl์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ณ„๋„์˜ ํ•„๋“œ๊ฐ€ ๊ณต๊ฐ„์— ์ƒ์„ฑ๋œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฑ๊ทธ๋ผ์šด๋“œ์˜ ๋ชจ๋“ˆ์€ ๊ณต๊ฐ„์„ ์Šค์บ”ํ•˜๊ณ  TTL์„ ํ˜„์žฌ ์‹œ๊ฐ„๊ณผ ๋น„๊ตํ•˜์—ฌ ํŠœํ”Œ์„ ์‚ญ์ œํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. memcached ๋ชจ๋“ˆ ์ฝ”๋“œ๋Š” ๊ฐ„๋‹จํ•˜๊ณ  ์šฐ์•„ํ•˜์ง€๋งŒ ๋„ˆ๋ฌด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. ์ฒซ์งธ, ํฌ๋กค๋ง ๋ฐ ์‚ญ์ œ๋˜๋Š” ์ธ๋ฑ์Šค ์œ ํ˜•์„ ๊ณ ๋ คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‘˜์งธ, ๊ฐ ํŒจ์Šค์—์„œ ๋ชจ๋“  ํŠœํ”Œ์ด ์Šค์บ”๋˜๋ฉฐ ๊ทธ ์ˆ˜๊ฐ€ ์ƒ๋‹นํžˆ ํด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งŒ๋ฃŒ๋œ ๋ชจ๋“ˆ์—์„œ ์ฒซ ๋ฒˆ์งธ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ๋‹ค๋ฉด(ํŠธ๋ฆฌ ์ธ๋ฑ์Šค๊ฐ€ ๋ณ„๋„์˜ ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌ๋จ) ๋‘ ๋ฒˆ์งธ ๋ฌธ์ œ๋Š” ์—ฌ์ „ํžˆ ๊ด€์‹ฌ์„ ๋ฐ›์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์„ธ ๊ฐ€์ง€ ์‚ฌํ•ญ์€ ๋‚ด ์ž์‹ ์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ์œ ๋ฆฌํ•œ ์„ ํƒ์„ ๋ฏธ๋ฆฌ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์ˆ 

tarantool์— ๋Œ€ํ•œ ๋ฌธ์„œ์—๋Š” ๋งค์šฐ ์ข‹์€ ๋‚ด์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๋„ ์‹œ๊ฐ„ C์—์„œ ์ €์žฅ ํ”„๋กœ์‹œ์ €๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์šฐ์„ , ์•„๋ž˜์— ํ‘œ์‹œ๋  ๋ช…๋ น๊ณผ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ ์‚ฝ์ž…์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด C์— ์ต์ˆ™ํ•ด์ง€๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ฃผ๋ชฉํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฐธ์กฐ ์ž์‹ ๋งŒ์˜ ์ œํ•œ ๋ชจ๋“ˆ์„ ์ž‘์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด, ์ฆ‰ ์ƒ์ž, ์„ฌ์œ , ์ƒ‰์ธ ะธ txn.

๋ฉ€๋ฆฌ์„œ ์‹œ์ž‘ํ•˜์—ฌ ์บก์ด ๋‹ซํžŒ ๋งŒ๋ฃŒ๋œ ๋ชจ๋“ˆ์ด ์™ธ๋ถ€์—์„œ ์–ด๋–ป๊ฒŒ ๋ณด์ด๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

fiber = require('fiber')
net_box = require('net.box')
box.cfg{listen = 3300}
box.schema.func.create('libcapped-expirationd.start', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.start')
box.schema.func.create('libcapped-expirationd.kill', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.kill')
box.schema.space.create('tester')
box.space.tester:create_index('primary', {unique = true, parts = {1, 'unsigned'}})
capped_connection = net_box:new(3300)

๋‹จ์ˆœํ™”๋ฅผ ์œ„ํ•ด libcapped-expirationd.so ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ tarantool์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋‘ ๊ฐ€์ง€ ํ•จ์ˆ˜(start ๋ฐ kill)๋ฅผ ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” box.schema.func.create ๋ฐ box.schema.user.grant๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Lua์—์„œ ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํŠœํ”Œ์— ์„ธ ๊ฐœ์˜ ํ•„๋“œ๋งŒ ํฌํ•จ๋˜๋Š” ๊ณต๊ฐ„์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋Š” ๊ณ ์œ  ์‹๋ณ„์ž, ๋‘ ๋ฒˆ์งธ๋Š” ์ด๋ฉ”์ผ, ์„ธ ๋ฒˆ์งธ๋Š” ํŠœํ”Œ์˜ ์ˆ˜๋ช…์ž…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ํ•„๋“œ ์œ„์— ํŠธ๋ฆฌ ์ธ๋ฑ์Šค๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์ด๋ฅผ ๊ธฐ๋ณธ์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ๋‹ค์Œ์œผ๋กœ ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ ๊ฐœ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

์ค€๋น„ ์ž‘์—…์ด ๋๋‚˜๋ฉด ์‹œ์ž‘ ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

capped_connection:call('libcapped-expirationd.start', {'non-indexed', box.space.tester.id, box.space.tester.index.primary, box.space.tester.index.primary, 3, 1024, 3600})

์ด ์˜ˆ์ œ๋Š” Lua๋กœ ์ž‘์„ฑ๋œ ๋งŒ๋ฃŒ๋œ ๋ชจ๋“ˆ๊ณผ ์ •ํ™•ํžˆ ๋™์ผํ•˜๊ฒŒ ์Šค์บ”ํ•˜๋Š” ๋™์•ˆ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. start ํ•จ์ˆ˜์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ์ž‘์—…์˜ ๊ณ ์œ  ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ๋Š” ๊ณต๊ฐ„ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค. ์„ธ ๋ฒˆ์งธ๋Š” ํŠœํ”Œ์ด ์‚ญ์ œ๋˜๋Š” ๊ณ ์œ  ์ธ๋ฑ์Šค์ž…๋‹ˆ๋‹ค. ๋„ค ๋ฒˆ์งธ๋Š” ํŠœํ”Œ์„ ํƒ์ƒ‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ธ๋ฑ์Šค์ž…๋‹ˆ๋‹ค. ๋‹ค์„ฏ ๋ฒˆ์งธ๋Š” ์ˆ˜๋ช…์ด ์žˆ๋Š” ํŠœํ”Œ ํ•„๋“œ์˜ ์ˆ˜์ž…๋‹ˆ๋‹ค(๋ฒˆํ˜ธ๋Š” 1์ด ์•„๋‹Œ 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค!). ์—ฌ์„ฏ๋ฒˆ์งธ์™€ ์ผ๊ณฑ๋ฒˆ์งธ๋Š” ์Šค์บ๋‹ ์„ค์ •์ž…๋‹ˆ๋‹ค. 1024๋Š” ๋‹จ์ผ ํŠธ๋žœ์žญ์…˜์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ํŠœํ”Œ ์ˆ˜์ž…๋‹ˆ๋‹ค. 3600 โ€” ์ „์ฒด ์Šค์บ” ์‹œ๊ฐ„(์ดˆ)์ž…๋‹ˆ๋‹ค.

์ด ์˜ˆ์—์„œ๋Š” ํฌ๋กค๋ง๊ณผ ์‚ญ์ œ์— ๋™์ผํ•œ ์ƒ‰์ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ํŠธ๋ฆฌ ์ธ๋ฑ์Šค๋ผ๋ฉด ์ž‘์€ ํ‚ค์—์„œ ํฐ ํ‚ค๋กœ ์ˆœํšŒ๊ฐ€ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํ•ด์‹œ ์ธ๋ฑ์Šค์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ํ•ญ๋ชฉ์ด ์žˆ์œผ๋ฉด ์ˆœํšŒ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฌด์ž‘์œ„ ์ˆœ์„œ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ณต๊ฐ„ ํŠœํ”Œ์€ ํ•œ ๋ฒˆ์˜ ์Šค์บ”์œผ๋กœ ์Šค์บ”๋ฉ๋‹ˆ๋‹ค.

์ˆ˜๋ช…์ด 60์ดˆ์ธ ์—ฌ๋Ÿฌ ํŠœํ”Œ์„ ๊ณต๊ฐ„์— ์‚ฝ์ž…ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

box.space.tester:insert{0, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{1, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{2, '[email protected]', math.floor(fiber.time()) + 60}

์‚ฝ์ž…์ด ์„ฑ๊ณตํ–ˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

tarantool> box.space.tester.index.primary:select()
---
- - [0, '[email protected]', 1576418976]
  - [1, '[email protected]', 1576418976]
  - [2, '[email protected]', 1576418976]
...

60์ดˆ ์ด์ƒ(์ฒซ ๋ฒˆ์งธ ํŠœํ”Œ ์‚ฝ์ž… ์‹œ์ž‘๋ถ€ํ„ฐ ๊ณ„์‚ฐ) ํ›„์— ์„ ํƒ์„ ๋ฐ˜๋ณตํ•˜๊ณ  ์ œํ•œ ๋งŒ๋ฃŒ ๋ชจ๋“ˆ์ด ์ด๋ฏธ ์ฒ˜๋ฆฌ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

tarantool> box.space.tester.index.primary:select()
---
  - []
...

์ž‘์—…์„ ์ค‘์ง€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

capped_connection:call('libcapped-expirationd.kill', {'non-indexed'})

ํฌ๋กค๋ง์— ๋ณ„๋„์˜ ์ƒ‰์ธ์ด ์‚ฌ์šฉ๋˜๋Š” ๋‘ ๋ฒˆ์งธ ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

fiber = require('fiber')
net_box = require('net.box')
box.cfg{listen = 3300}
box.schema.func.create('libcapped-expirationd.start', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.start')
box.schema.func.create('libcapped-expirationd.kill', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.kill')
box.schema.space.create('tester')
box.space.tester:create_index('primary', {unique = true, parts = {1, 'unsigned'}})
box.space.tester:create_index('exp', {unique = false, parts = {3, 'unsigned'}})
capped_connection = net_box:new(3300)

์—ฌ๊ธฐ์— ์žˆ๋Š” ๋ชจ๋“  ๋‚ด์šฉ์€ ๋ช‡ ๊ฐ€์ง€ ์˜ˆ์™ธ๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ฒซ ๋ฒˆ์งธ ์˜ˆ์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ์„ธ ๋ฒˆ์งธ ํ•„๋“œ ์œ„์— ํŠธ๋ฆฌ ์ธ๋ฑ์Šค๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์ด๋ฅผ exp๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์ด ์ธ๋ฑ์Šค๋Š” ๊ธฐ๋ณธ ์ธ๋ฑ์Šค์™€ ๋‹ฌ๋ฆฌ ๊ณ ์œ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ˆœํšŒ๋Š” exp ์ธ๋ฑ์Šค๋กœ ์ˆ˜ํ–‰๋˜๊ณ  ์‚ญ์ œ๋Š” ๊ธฐ๋ณธ์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด์ „์—๋Š” ๋‘ ๊ฐ€์ง€ ๋ชจ๋‘ ๊ธฐ๋ณธ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ๋งŒ ์ˆ˜ํ–‰๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•ฉ๋‹ˆ๋‹ค.

์ค€๋น„ ์ž‘์—…์ด ๋๋‚˜๋ฉด ์ƒˆ ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹œ์ž‘ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

capped_connection:call('libcapped-expirationd.start', {'indexed', box.space.tester.id, box.space.tester.index.primary, box.space.tester.index.exp, 3, 1024, 3600})

์ˆ˜๋ช…์ด 60์ดˆ์ธ ์—ฌ๋Ÿฌ ํŠœํ”Œ์„ ๋‹ค์‹œ ๊ณต๊ฐ„์— ์‚ฝ์ž…ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

box.space.tester:insert{0, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{1, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{2, '[email protected]', math.floor(fiber.time()) + 60}

30์ดˆ ํ›„์— ๋น„์œ ์ ์œผ๋กœ ๋ช‡ ๊ฐ€์ง€ ํŠœํ”Œ์„ ๋” ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

box.space.tester:insert{3, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{4, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{5, '[email protected]', math.floor(fiber.time()) + 60}

์‚ฝ์ž…์ด ์„ฑ๊ณตํ–ˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

tarantool> box.space.tester.index.primary:select()
---
- - [0, '[email protected]', 1576421257]
  - [1, '[email protected]', 1576421257]
  - [2, '[email protected]', 1576421257]
  - [3, '[email protected]', 1576421287]
  - [4, '[email protected]', 1576421287]
  - [5, '[email protected]', 1576421287]
...

60์ดˆ ์ด์ƒ(์ฒซ ๋ฒˆ์งธ ํŠœํ”Œ ์‚ฝ์ž… ์‹œ์ž‘๋ถ€ํ„ฐ ๊ณ„์‚ฐ) ํ›„์— ์„ ํƒ์„ ๋ฐ˜๋ณตํ•˜๊ณ  ์ œํ•œ ๋งŒ๋ฃŒ ๋ชจ๋“ˆ์ด ์ด๋ฏธ ์ฒ˜๋ฆฌ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

tarantool> box.space.tester.index.primary:select()
---
- - [3, '[email protected]', 1576421287]
  - [4, '[email protected]', 1576421287]
  - [5, '[email protected]', 1576421287]
...

๊ณต๊ฐ„์—๋Š” ์•„์ง 30์ดˆ ์ •๋„ ๋” ์œ ์ง€๋  ํŠœํ”Œ์ด ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ID๊ฐ€ 2์ด๊ณ  ์ˆ˜๋ช…์ด 1576421257์ธ ํŠœํ”Œ์—์„œ ID๊ฐ€ 3์ด๊ณ  ์ˆ˜๋ช…์ด 1576421287์ธ ํŠœํ”Œ๋กœ ์ด๋™ํ•  ๋•Œ ๊ฒ€์ƒ‰์ด ์ค‘์ง€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ˆ˜๋ช…์ด 1576421287 ์ด์ƒ์ธ ํŠœํ”Œ์€ ์ˆœ์„œ๋กœ ์ธํ•ด ๊ฒ€์ƒ‰๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. exp ์ธ๋ฑ์Šค ํ‚ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ์šฐ๋ฆฌ๊ฐ€ ์ฒ˜์Œ์— ๋‹ฌ์„ฑํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ๋น„์šฉ ์ ˆ๊ฐ์ž…๋‹ˆ๋‹ค.

์ž‘์—…์„ ์ค‘์ง€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

capped_connection:call('libcapped-expirationd.kill', {'indexed'})

ะ ะตะฐะปะธะทะฐั†ะธั

ํ”„๋กœ์ ํŠธ์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์„ค๋ช…ํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ์›๋ณธ ์†Œ์Šค์ž…๋‹ˆ๋‹ค. ์•”ํ˜ธ! ์ถœํŒ์˜ ์ผ๋ถ€๋กœ ์šฐ๋ฆฌ๋Š” ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์‚ฌํ•ญ, ์ฆ‰ ๊ณต๊ฐ„ ์šฐํšŒ ์•Œ๊ณ ๋ฆฌ์ฆ˜์—๋งŒ ์ค‘์ ์„ ๋‘˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

start ๋ฉ”์†Œ๋“œ์— ์ „๋‹ฌํ•˜๋Š” ์ธ์ˆ˜๋Š”expirationd_task๋ผ๋Š” ๊ตฌ์กฐ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

struct expirationd_task
{
  char name[256];
  uint32_t space_id;
  uint32_t rm_index_id;
  uint32_t it_index_id;
  uint32_t it_index_type; 
  uint32_t field_no;
  uint32_t scan_size;
  uint32_t scan_time;
};

name ์†์„ฑ์€ ์ž‘์—…์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. space_id ์†์„ฑ์€ ๊ณต๊ฐ„ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค. rm_index_id ์†์„ฑ์€ ํŠœํ”Œ์ด ์‚ญ์ œ๋  ๊ณ ์œ  ์ธ๋ฑ์Šค์˜ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค. it_index_id ์†์„ฑ์€ ํŠœํ”Œ์„ ํƒ์ƒ‰ํ•  ์ธ๋ฑ์Šค์˜ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค. it_index_type ์†์„ฑ์€ ํŠœํ”Œ์ด ์ˆœํšŒ๋˜๋Š” ์ธ๋ฑ์Šค ์œ ํ˜•์ž…๋‹ˆ๋‹ค. Filed_no ์†์„ฑ์€ ์ˆ˜๋ช…์ด ์žˆ๋Š” ํŠœํ”Œ ํ•„๋“œ์˜ ์ˆ˜์ž…๋‹ˆ๋‹ค. scan_size ์†์„ฑ์€ ํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ ์Šค์บ”๋˜๋Š” ์ตœ๋Œ€ ํŠœํ”Œ ์ˆ˜์ž…๋‹ˆ๋‹ค. scan_time ์†์„ฑ์€ ์ „์ฒด ์Šค์บ” ์‹œ๊ฐ„(์ดˆ)์ž…๋‹ˆ๋‹ค.

๊ตฌ๋ฌธ ๋ถ„์„ ์ธ์ˆ˜๋Š” ๊ณ ๋ คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํž˜๋“ค์ง€๋งŒ ๊ฐ„๋‹จํ•œ ์ž‘์—…์ด๋ฉฐ ๋„์„œ๊ด€์ด ์—ฌ๋Ÿฌ๋ถ„์„ ๋„์™€์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. msgpuck. ๊ฐ„๋‹จํ•œ ์œ ํ˜•์ธ mp_bool, mp_double, mp_int, mp_uint ๋ฐ mp_array๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  mp_map ์œ ํ˜•์˜ ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ Lua์—์„œ ์ „๋‹ฌ๋˜๋Š” ์ธ๋ฑ์Šค์—์„œ๋งŒ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ „์ฒด ์ธ๋ฑ์Šค๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๊ณ ์œ ์„ฑ์„ ํ™•์ธํ•˜๊ณ  ์œ ํ˜•์„ ๊ณ„์‚ฐํ•˜๊ณ  ์‹๋ณ„์ž๋ฅผ ์ถ”์ถœํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๊ตฌ๋ฌธ ๋ถ„์„์— ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“  ํ•จ์ˆ˜์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ๋‚˜์—ดํ•ฉ๋‹ˆ๋‹ค.

bool expirationd_parse_name(struct expirationd_task *task, const char **pos);
bool expirationd_parse_space_id(struct expirationd_task *task, const char **pos);
bool expirationd_parse_rm_index_id(struct expirationd_task *task, const char **pos);
bool expirationd_parse_rm_index_unique(struct expirationd_task *task, const char **pos);
bool expirationd_parse_rm_index(struct expirationd_task *task, const char **pos);
bool expirationd_parse_it_index_id(struct expirationd_task *task, const char **pos);
bool expirationd_parse_it_index_type(struct expirationd_task *task, const char **pos);
bool expirationd_parse_it_index(struct expirationd_task *task, const char **pos);
bool expirationd_parse_field_no(struct expirationd_task *task, const char **pos);
bool expirationd_parse_scan_size(struct expirationd_task *task, const char **pos);
bool expirationd_parse_scan_time(struct expirationd_task *task, const char **pos);

์ด์ œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ, ์ฆ‰ ๊ณต๊ฐ„์„ ์šฐํšŒํ•˜๊ณ  ํŠœํ”Œ์„ ์‚ญ์ œํ•˜๋Š” ๋…ผ๋ฆฌ๋กœ ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค. scan_size๋ณด๋‹ค ํฌ์ง€ ์•Š์€ ๊ฐ ํŠœํ”Œ ๋ธ”๋ก์€ ๋‹จ์ผ ํŠธ๋žœ์žญ์…˜์—์„œ ์Šค์บ”๋˜๊ณ  ์ˆ˜์ •๋ฉ๋‹ˆ๋‹ค. ์„ฑ๊ณตํ•˜๋ฉด ์ด ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹๋˜๊ณ , ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋กค๋ฐฑ๋ฉ๋‹ˆ๋‹ค. ๋งŒ๋ฃŒ_iterate ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ์ธ์ˆ˜๋Š” ์Šค์บ”์ด ์‹œ์ž‘๋˜๊ฑฐ๋‚˜ ๊ณ„์†๋˜๋Š” ๋ฐ˜๋ณต๊ธฐ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค. ์ด ๋ฐ˜๋ณต์ž๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜ ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ฏธ๋ฆฌ ์ค‘์ง€ํ•  ์ˆ˜ ์—†์„ ๋•Œ๊นŒ์ง€ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฆ๊ฐ€๋ฉ๋‹ˆ๋‹ค. expired_expired ํ•จ์ˆ˜๋Š” ํŠœํ”Œ์˜ ์ˆ˜๋ช…์„ ํ™•์ธํ•˜๊ณ ,expirationd_delete๋Š” ํŠœํ”Œ์„ ์‚ญ์ œํ•˜๊ณ ,expirationd_breakable์€ ๊ณ„์† ์ง„ํ–‰ํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

Expirationd_iterate ํ•จ์ˆ˜ ์ฝ”๋“œ:

static bool
expirationd_iterate(struct expirationd_task *task, box_iterator_t **iterp)
{
  box_iterator_t *iter = *iterp;
  box_txn_begin();
  for (uint32_t i = 0; i < task->scan_size; ++i) {
    box_tuple_t *tuple = NULL;
    if (box_iterator_next(iter, &tuple) < 0) {
      box_iterator_free(iter);
      *iterp = NULL;
      box_txn_rollback();
      return false;
    }
    if (!tuple) {
      box_iterator_free(iter);
      *iterp = NULL;
      box_txn_commit();
      return true;
    }
    if (expirationd_expired(task, tuple))
      expirationd_delete(task, tuple);
    else if (expirationd_breakable(task))
      break;
  }
  box_txn_commit();
  return true;
}

ํ•จ์ˆ˜ ์ฝ”๋“œ ๋งŒ๋ฃŒ_๋งŒ๋ฃŒ:

static bool
expirationd_expired(struct expirationd_task *task, box_tuple_t *tuple)
{
  const char *buf = box_tuple_field(tuple, task->field_no - 1);
  if (!buf || mp_typeof(*buf) != MP_UINT)
    return false;
  uint64_t val = mp_decode_uint(&buf);
  if (val > fiber_time64() / 1000000)
    return false;
  return true;
}

Expirationd_delete ํ•จ์ˆ˜ ์ฝ”๋“œ:

static void
expirationd_delete(struct expirationd_task *task, box_tuple_t *tuple)
{
  uint32_t len;
  const char *str = box_tuple_extract_key(tuple, task->space_id, task->rm_index_id, &len);
  box_delete(task->space_id, task->rm_index_id, str, str + len, NULL);
}

ํ•จ์ˆ˜ ์ฝ”๋“œ ๋งŒ๋ฃŒ_ํ•ด์ œ ๊ฐ€๋Šฅ:

static bool
expirationd_breakable(struct expirationd_task *task)
{
  return task->it_index_id != task->rm_index_id && task->it_index_type == ITER_GT;
}

์‹ ์ฒญ

๋‹ค์Œ์—์„œ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—!

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€