
ã·ã¹ãã ã¯è€éã«æããŸãã ãã·ã¢ã®ã«ãŒãã«ãé¢ããããæåã¯ãã·ã¢èªã®ããã¥ã¡ã³ããããããŸããã§ããã ãã®åŒ·åãªããŒã«ã¯ãããã°ã©ããåå¿è ã®éçºè ãªã©ãæ®éã®äººãã©ã®ããã«å©ããããšãã§ããŸããïŒ æ®ãã¯ããã«çµæãèŠãããšãã§ããŸãã
倧ããªè² è·ã«èããããšãã§ããç°¡åãªåš¯æ¥œãµãŒãã¹ãæžããŠã¿ãŸãããã ãããŠãSQLãªãïŒ
ç§ãã¡ã®ç®æš
åŠç¿ããã»ã¹ãžã®é¢å¿ãé«ããããã«ãWebéçºã§Tarantulaã䜿çšããç°¡åã§èå³æ·±ãäŸãèŠãŠã¿ãŸãããã åçã®ãã¢æ祚ã衚瀺ãããŠã§ããµã€ããç«ã¡äžããŸãã Mark Zuckerbergã®ãããªå€§åŠçã®åçã¯ã¢ããããŒãããŸãããã Telegramã¡ãã»ã³ãžã£ãŒã®ã¹ããã«ãŒã®éžæã«é¢ããæ祚ãæé ããŸãã æ祚ã«ããã¢ã«ãŽãªãºã ã¯ãæé«ã®ã¹ããã«ãŒã®ããããéžæããŸãããå®éã«ã¯ãã³ã¬ã¯ã·ã§ã³ã®ã¡ã€ã³ããªãŒã¯-Mr. The UglyãèŠã€ããããšãã¿ã¹ã¯ã§ãã ããæ°ãããã®ã§ãä»ã¯éå±ãªããšãããæã§ãã
èšçœ®
ãŽã©ããã®ã©ããã§ãç¥ã¯ããŒãºãéããŸããã 1ã€ã®ããã»ããµã³ã¢ãš1 GBã®RAMãåããæ§ãããªä»®æ³ãµãŒããŒãååŸããŸãããããã¯ãæè²æ°Žæºã®é«ããã€ãã®å®¶æã®äžã§æãè¥ãåå«ã§ãã ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã¯Debianãªã®ã§ãTarantulaã¯å ¬åŒãªããžããªtarantool.org/download.htmlããã€ã³ã¹ããŒã«ã§ããŸãã
ããã¥ã¢ã«ã«ã¯ãã³ããŒã¢ã³ãããŒã¹ãããšæžãããŠããŸãããããã¯éåžžã«ç±å¿ã§ãã
curl http://download.tarantool.org/tarantool/1.7/gpgkey | sudo apt-key add - release=`lsb_release -c -s` # install https download transport for APT sudo apt-get -y install apt-transport-https # append two lines to a list of source repositories sudo rm -f /etc/apt/sources.list.d/*tarantool*.list sudo tee /etc/apt/sources.list.d/tarantool_1_7.list <<- EOF deb http://download.tarantool.org/tarantool/1.7/debian/ $release main deb-src http://download.tarantool.org/tarantool/1.7/debian/ $release main EOF # install sudo apt-get update sudo apt-get -y install tarantool
éçºè ããã®ã¡ãã£ãšããé©ãïŒi386ã¢ãŒããã¯ãã£ã¯å ¬åŒãªããžããªã§ã¯ãµããŒããããŠããŸããããããã±ãŒãžãã¹ãã£ã³ã°ãµãŒãã¹ã¯ã¡ã€ã³ãã¡ã€ã«ä»¥å€ã®ãã¹ãŠã®ãã¡ã€ã«ãå®æçã«æäŸããŸãã ãã©ãã«ãé¿ããããã«ãAMD64ã·ã¹ãã ã«ããã±ãŒãžãã€ã³ã¹ããŒã«ããŠãã ããã
ã¯ããã«
ã€ã³ã¹ããŒã«åŸã次ã®ãããªãã¹ãæ§æexample.luaã§tarantoolããã»ã¹ãèµ·åãããŸãã
ps xauf | grep taran root 2735 0.0 0.2 13972 2132 pts/0 S+ 22:05 0:00 \_ grep taran taranto+ 568 0.0 0.8 812304 8632 ? Ssl 17:03 0:03 tarantool example.lua <running>
Tarantoolã䜿çšããã«ã¯ã Luaã¹ã¯ãªããèšèªã䜿çšããŸãããã®èšèªã§ã¯ããµãŒããŒç®¡çã³ãã³ããèšè¿°ãããã¹ãã¢ãããã·ãŒãžã£ãšããªã¬ãŒãèšè¿°ãããŸãã æ¢è£œã®ãœãããŠã§ã¢ã¢ãžã¥ãŒã«ãããŒãããããç¬èªã®ã¢ãžã¥ãŒã«ãäœæã§ããŸãã
tarantoolctlãŠãŒãã£ãªãã£ãå®è¡ããæåã®ããã°ã©ã ãå°å·ããŠããã¹ãŠãæ©èœããããšã確èªããŸãã
tarantoolctl connect '3301' connected to localhost:3301 localhost:3301> print ('The good!') --- ... localhost:3301>
ããã§ãé åžãããã«ä»å±ãããã¹ãæ§æã«ãªããŸããã Debianã®ã€ããªãã®ãŒã«ããã°ãèšå®ã¯/etc/tarantool/instances.available/*ãã£ã¬ã¯ããªãŒã«ãããèµ·åãããããã°ã©ã æ§æã¯/etc/tarantool/instances.enabled/*ãã£ã¬ã¯ããªãŒã®ã·ã³ããªãã¯ãªã³ã¯ã䜿çšããŠäœæãããŸãã æ°ãããšã¹ããŒãã®äžã«ãµã³ãã«ãã¡ã€ã«ãã³ããŒãããããžã§ã¯ããäœæããŸãã
ç§ãã¡ã®ãããžã§ã¯ãã¯ãçãgbuã§ã¯ãè¯ããæªããandãããšåŒã°ããŠããŸãã ãããžã§ã¯ãã®ãã«ããŒã ã®ç¥èªãæåã®æåã«äœ¿çšãããšãååã¯åžžã«ããªãã®ä»äºãå°éããæããã§ãããïŒ
次ã«ãgbu.cfgãå°ãä¿®æ£ããŠããµãŒãã¹ãéå§ããŸãã Luaæ§æã¯ãã³ã¡ã³ãã2ã€ã®ãã€ãã³ã§å§ãŸãæ§æã«äœ¿çšãããããšãæãåºãããŠãã ããã
box.cfg { -- listen = 3311; -- slab_alloc_arena = 0.2; -- } local function bootstrap() local space = box.schema.create_space('example') space:create_index('primary') -- -- box.schema.user.grant('guest', 'read,write,execute', 'universe') -- box.schema.user.create('good', { password = 'secret' }) box.schema.user.grant('good', 'read,write,execute', 'universe') end -- box.once('example-2.0', bootstrap)
tarantoolctl start gbuã³ãã³ãã§æ°ããã€ã³ã¹ã¿ã³ã¹ãèµ·åãããã¹ãŠãæ£åžžã«æ©èœããããšã確èªããŸãã
tarantoolctl connect "good:secret@0:3311" connected to 0:3311 0:3311>
ç§ãã¡ã¯ããžãã¹ãããŠããŸãïŒ
ããŒã¿ããŒã¹
- Tarantoolã®ã¬ã³ãŒãã¯ã¹ããŒã¹ã«ä¿åãããŸããããã¯ããªã¬ãŒã·ã§ãã«SQLããŒã¿ããŒã¹ã®ããŒãã«ã«äŒŒãŠããŸãã å¿ èŠãªã ãäœæã§ããŸã-æ倧65,000
- ã¹ããŒã¹å ã«ã¯ã¿ãã«ããããŸããã¿ãã«ã¯ãSQLããŒãã«ã®è¡ãšJSONããŒã¿é åã«äŒŒãŠããŸãã ã¿ãã«ã®æ倧ãµã€ãºã¯ãããã©ã«ãèšå®ã§æ倧1 MBã§ãã ãã®ãã©ã¡ãŒã¿ãŒã¯å€æŽã§ããŸãã
- ããŒã¿ããŒã¹ã掻çšããã«ã¯ãSQLãšåæ§ã«ã€ã³ããã¯ã¹ãäœæããå¿ èŠããããŸãã ãããã®ãããã§ããã¹ãŠã®èŠçŽ ã®å®å šãªãªã¹ããå埩åŠçãã代ããã«ãããé«éãªã¢ã«ãŽãªãºã ã䜿çšããŠæ€çŽ¢ãå®è¡ãããŸãã 䞊ã¹æ¿ããå¯èœã§ãã ã€ã³ããã¯ã¹ã®éžæã¯ãããŒã¿ã®ã¿ã€ãã«ãã£ãŠç°ãªããŸãã
HASHã€ã³ããã¯ã¹ ïŒå€ã¯äžæã§ããå¿ èŠããããä»»æã®å€ã«ããããšãã§ããŸãã ããã¯ãããç¥ãããŠããããŒ/å€ã¹ãã¢ã®æ§ææ¹æ³ã§ãããããããšãåŒã°ããŸãã è¯ãäŸã¯ãMD5ããã·ã¥ãã¡ã€ã«ã®ãã§ãã¯ãµã ã§ãã
TREEã€ã³ããã¯ã¹ ïŒå€ã¯äžæã§ã¯ãªãå ŽåããããŸããã䞊ã¹æ¿ãããããªã¹ããæŽçããã«ã¯ãå¯ãã§ãªããã°ãªããŸããã äžè¶³ããŠããèŠçŽ ãããå¯èœæ§ã®ããé åïŒArrayïŒãå€æããŸãã è¯ãäŸã¯ã1ãã€å¢å ãã泚æçªå·ã§ãã
äžæã®å€ãå¿ èŠãªå Žåã¯ãHASHãŸãã¯TREEã䜿çšã§ããŸãããHASHã¯ã¹ããŒã¹ããŒã¿ã§ã¯ããé«éã«ãªããŸãã ãœãŒãã«äžæã§ãªããã£ãŒã«ããå¿ èŠãªå Žåã¯ãTREEã€ã³ããã¯ã¹ã®ã¿ã䜿çšã§ããŸãã
ãŸãã2次å å¹³é¢ã§ã®æ€çŽ¢çšã®RTREEã€ã³ããã¯ã¹ãšããããããŒã¿ã®æäœçšã®BITSETããããŸããããããã¯å¿ èŠãããŸããã 詳现ã«ã€ããŠã¯ã ããã¥ã¡ã³ããåç §ããŠãã ãã ã
ã¿ã©ã³ãã¥ã©ãç¿åŸããŠãããšãã²ããŒã»ã·ã£ããªã³ã®èšäºã®ç»åã ã¡ãªã¿ã«ãæåã®ç¥äººã®ããã®è¯ãã¬ã€ãã

ãããžã§ã¯ãããŒã¿ã¢ãã«
ã¢ããªã±ãŒã·ã§ã³ã®ããŒã¿ã¢ãã«ã§ã¯ããã¡ã€ã«ã«é¢ããæ å ±ãä¿åããããã®ã¹ãã£ãã«ãŒã¹ããŒã¹ãäœæããŸãã Luaæ§æã䜿çšãããããããã£ãŒã«ãçªå·ã¯1ããå§ãŸãããšã«æ³šæããŠãã ããã ã¿ãã«ã«ã¯æ¬¡ã®ãã£ãŒã«ããå«ãŸããŸãã
- 眲åãªãID-äžæã®ã¹ããã«ãŒçªå·
- æŽæ°è©äŸ¡-ã¹ããã«ãŒè©äŸ¡
- æååããã¯-ã¹ããã«ãŒããã¯ã®åå
- æååå-ã¹ããã«ãŒãã¡ã€ã«å
- ïŒæååïŒãã¹-ã¹ããã«ãŒURL
- ïŒnumberïŒup-ã¹ããã«ãŒããšã®æ祚æ°
- ïŒnumberïŒdown-ã¹ããã«ãŒã«å¯Ÿããæ祚æ°ã
ããã¯ã¹ããŒã¹ã«ãã¹ããã«ãŒããã¯ã®ãªã¹ããä¿åããŸãã
- æååããã¯-ã¹ããã«ãŒããã¯ã®åå
- æŽæ°ã®è©äŸ¡-ã¹ããã«ãŒããã¯ã®è©äŸ¡
- ïŒæååïŒãã¹-説æããŒãžãžã®ãªã³ã¯
ã·ãŒã¯ã¬ããã¹ããŒã¹ã«ã¯ãäžæ£è¡çºã«å¯Ÿããæãç°¡åãªä¿è·ãå®è£ ããããã«ãç»åãžã®ãªã³ã¯ãæå·åããããŒã¯ã³ãæ ŒçŽããŸãã
- æååããŒã¯ã³-ã¹ããã«ãŒã®ã©ã³ãã ããŒã¯ã³
- æŽæ°æé-ããŒã¯ã³äœææéïŒå€ããã®ãåé€ããã®ã«äŸ¿å©ïŒ
- ïŒæŽæ°ïŒid-äžæã®ã¹ããã«ãŒçªå·ïŒã¹ããã«ãŒã¹ããŒã¹ããŒïŒ
- ïŒæååïŒurl-ã¹ããã«ãŒURL
ã»ãã·ã§ã³ã¹ããŒã¹ã§ã¯ã蚪åè ãèšé²ããçµ±èšãåéããŸãã
- string uuid-蚪åè ã®äžæã®ã·ã³ããªãã¯èå¥å
- æŽæ°uuid_time-ã»ãã·ã§ã³äœææéïŒå€ãã»ãã·ã§ã³ã®åé€ã«äŸ¿å©ïŒ
- ïŒæ°ïŒuser_votes-蚪åè ãæ祚ããåæ°
- ïŒæååïŒip-蚪åè ã®IPã¢ãã¬ã¹
- ïŒæååïŒãšãŒãžã§ã³ã-蚪åè ã®ãã©ãŠã¶ã¿ã€ã
ãµãŒããŒç©ºéã§ã¯ãåã«ãµã€ãã®çµ±èšãåéããŸãã
- æŽæ°IDã¯åãªãããŒã§ã
- ïŒnumberïŒvisitors-ãŠããŒã¯ãŠãŒã¶ãŒã®æ°
- ïŒæ°ïŒç¥š-æãããã祚ã®ç·æ°
- ïŒæ°ïŒã¯ãªãã¯-æ祚ã§ã®ã¯ãªãã¯ã®ç·æ°
ã€ã³ããã¯ã¹ãå²ãåœãŠãã«ã¯ããã£ãŒã«ãã®ã¿ã€ããæ瀺çã«æå®ããå¿ èŠãããããšã«æ³šæããŠãã ããã ãã®ã¿ã€ãã¯ã å¯èœãª Tarantula ãªãã·ã§ã³ã®ãªã¹ãããéžæããå¿ èŠããããŸã ã
æ®ãã®ãã£ãŒã«ãã¯ä»»æã®ã¿ã€ãã§ãçµã¿èŸŒã¿ã®Luaã€ã³ã¿ãŒããªã¿ãŒã«ãã£ãŠãµããŒããããŠããŸãã ãã®ããŒã¿åã®äºå æ§ã¯ãTarantulaã®æ©èœã§ããã ããã¥ã¡ã³ãã«èšèŒãããŠããŸã ã 䟿å®äžãã¢ãã«ã説æãããšãã«ãæ¬åŒ§å ã«LuaããŒã¿åã瀺ããŸããã
ã¢ããªã³ã°ã®éèŠãªéšåã¯ãã€ã³ããã¯ã¹ã®ã³ã³ãã€ã«ã§ãã Tarantulaã®å€§ããªå©ç¹ã¯ãè€éãªè€åã€ã³ããã¯ã¹ãäœæã§ããããšã§ãã ãã®ãããã·ã¹ãã ã®é床ãäœäžãããããšãªããã¿ãã«ã®ããŸããŸãªãã£ãŒã«ãã«åºã¥ããé«éãªåæã¯ãšãªãäœæã§ããŸãã idãã£ãŒã«ãã«ã¿ã€ãTREEã®ãã©ã€ããªã€ã³ããã¯ã¹ãè¿œå ããŠãæ祚ããã¢ã€ãã ãã©ã³ãã ã«éžæããŸãã 2çªç®ã®ã€ã³ããã¯ã¹ã¯ãã¬ã€ãã£ã³ã°ãã£ãŒã«ãã®ããªãŒã¿ã€ãã§ããããã¡ããè©äŸ¡ã衚瀺ããŸãïŒ HASHåã®Pack + Emojãã£ãŒã«ãã®è€åã€ã³ããã¯ã¹ãè¿œå ããŸããããã¯äžæã§ããå¿ èŠããããŸãã ã¹ããã«ãŒããã¯ã®äººæ°ãåæããããã«äœ¿çšã§ããŸãã
ããŒã¿ããŒã¹äœæã³ãŒããåæåæé ã®gbu.luaãã¡ã€ã«ã«é 眮ããŸã
é¢æ°ããŒãã¹ãã©ããïŒïŒ
local function bootstrap() box.schema.user.create('good', { password = 'secret' }) box.schema.user.grant('good', 'read,write,execute', 'universe') ----------------------------------- -- local stickers = box.schema.create_space('stickers') -- stickers:create_index('primary', { type = 'TREE', parts = {1, 'unsigned'} }) -- stickers:create_index('secondary', { type = 'TREE', unique = false, parts = {2, 'integer'} }) -- stickers:create_index('ternary', { type ='HASH', parts = {3, 'string', 4, 'string'} }) ----------------------------------- -- - local packs = box.schema.create_space('packs') -- - packs:create_index('primary', { type = 'HASH', parts = {1, 'string'} }) -- packs:create_index('secondary', { type = 'TREE', unique = false, parts = {2, 'integer'} }) ----------------------------------- -- local secret = box.schema.create_space('secret') -- secret:create_index('primary', { type = 'HASH', parts = {1, 'string'} }) -- secret:create_index('secondary', { type = 'TREE', unique = false, parts = {2, 'integer'} }) ----------------------------------- -- local sessions = box.schema.create_space('sessions') -- sessions:create_index('primary', { type = 'HASH', parts = {1, 'string'} }) -- sessions:create_index('secondary', { type = 'TREE', unique = false, parts = {2, 'integer'} }) ----------------------------------- -- local server = box.schema.create_space('server') -- server:create_index('primary', { type = 'TREE', parts = {1, 'unsigned'} }) -- server:insert{1, 0, 0, 0} end
èšå®ã§ãµãŒããŒãåèµ·åããåã«ãã³ã³ãœãŒã«ã®ã³ãã³ãã䜿çšããŠãã€ã¢ã°ã©ã ãäœæããŠãã ããã äœãåé¡ãçºçããå Žåã¯ã
box.space.stickers:drop()
ã³ãã³ãã§ã¹ããŒã¹å šäœãåé€ã§ããŸãã
ãŸãã¯å¥ã®ã€ã³ããã¯ã¹ïŒ
box.space.stickers.index.ternary:drop()
TABããŒããããèªç±ã«äœ¿çšããŠãã ããã ã³ã³ãœãŒã«ã§ã®äœæ¥ã®äŸ¿å®ã®ããã«ãäœæããåè·¯èŠçŽ ã®ååãå°æåã§æžããŸãã ã³ã³ãœãŒã«ã§äœæ¥ããããã®ã³ãã³ãã¯ãããã¥ã¡ã³ããå°ãèŠããšçŽæçã«ãªããŸãã
ã¯ãªã¢ã¹ããŒã¹ïŒ
box.space.stickers:truncate()
ã¹ããŒã¹ã®åé€ïŒ
box.space.stickers:drop()
ã€ã³ã¡ã¢ãªããŒã¿ããŒã¹ã®å Žåã«ããã§ããããã«ããã¹ãŠãå³åº§ã«è¡ãããŸãïŒ
ã³ã³ããŒãã³ãã®ã€ã³ã¹ããŒã«

åªããææ°ã®ããã°ã©ãã³ã°èšèªã«ã¯éçã§å³å¯ãªåä»ããå¿ èŠã§ãããã¢ã€ã³ãã·ãã£ã¯ãã³ãŒããããŒã¿ãšããŠæäœããOOPãCã©ã€ãã©ãªãžã®FFIããµããŒããããžã§ããªãã¯ã競åããã°ã©ãã³ã°ããã¡ãŒã¹ãã¯ã©ã¹ã®åžæ°ãšããŠã®æ©èœãã©ã ãããµããŒãããããããã£ã§ãã
ãã¡ãããããã¯PHPã«ã¯ååšããŸããïŒ ãããã£ãŠããµã³ãã«ã³ãŒããèšè¿°ããŸãã
ãŸããå®çžŸã®ããããŒã«-NginxãŠã§ããµãŒããŒãšPHPã€ã³ã¿ãŒããªã¿ãŒãã€ã³ã¹ããŒã«ããŸã-php - fpm ïŒ wiki.debian.org/en/nginx/nginx+php-fpm
nginxèšå®ã®ã«ãŒããã¹ã«ããªã¯ãšã¹ããæžãæããã«ãŒã«ãè¿œå ããŸãã
location / { try_files $uri $uri/ /index.php?q=$uri&$args; }
ãããã£ãŠãPHPã¹ã¯ãªããã®
$_REQUEST['q']
é åãã/ goodã¿ã€ãã®çŸãããªã³ã¯ãååŸããHTTPèŠæ±ã®ã«ãŒãã£ã³ã°ãå®è£ ããŸãã
CGIãªã¯ãšã¹ããå®è¡ããããã®ããŒã«ã©ã€ãºããããŸãã
location ~* \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; expires -1; }
expires -1;
ã³ãã³ã
expires -1;
ãªã¯ãšã¹ãã®ãã£ãã·ã¥ãç¡å¹ã«ããŸããæ祚ããŒãžãããããã£ãŒãã«ã¯å¿ èŠãããŸããã æ®ãã®å Žæã¯ãã¢ããã¹ããªãŒã HTTPèšå®ãã24æéãŸãã¯30æ¥éããŒã¿ããã£ãã·ã¥ããŸãã ãããã誰ããç¬èªã®æ¢è£œã®Nginxãªãã·ã§ã³ã®ã³ã¬ã¯ã·ã§ã³ãæã£ãŠããã§ãããã
次ã«ãTarantulaã䜿çšããããã®ã¢ãžã¥ãŒã«ãã€ã³ã¹ããŒã«ããå¿ èŠããããŸãã
sudo apt-get install php5-cli php5-dev php-pear pecl channel-discover tarantool.github.io/tarantool-php/pecl pecl install Tarantool-PHP/Tarantool-beta
ã€ã³ã¹ããŒã©ãŒã®åºåã«æžãããŠããå 容ãèªã¿ãŸãã ç§ã®å Žåãã¡ãã»ãŒãžããããŸããïŒ
Build process completed successfully Installing '/usr/lib/php5/20131226/tarantool.so' install ok: channel://tarantool.github.io/tarantool-php/pecl/Tarantool-0.0.13 configuration option "php_ini" is not set to php.ini location You should add "extension=tarantool.so" to php.ini
ãã¡ã€ã«/etc/php5/fpm/php.iniããã³/etc/php5/cli/php.iniã®æ§æãã¡ã€ã«ã«æå®ãããè¡ãè¿œå ããŸãã æ®å¿µãªãããPHPã®èµ·åæã«ãšã©ãŒãçºçããŸãïŒ WebãµãŒããŒã®ãããã°ã«æ©ãŸãããªãããã«ãæ°ããã©ã€ãã©ãªãcliæ§æã«è¿œå ãããããã³ãã³ãã©ã€ã³ããæäœæ§ã確èªã§ããŸãã
php -v PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php5/20131226/tarantool.so' - /usr/lib/php5/20131226/tarantool.so: undefined symbol: tarantool_schema_destroy in Unknown on line 0 PHP 5.6.29-0+deb8u1 (cli) (built: Dec 13 2016 16:02:08)
å·çæç¹ã§ã¯ãPEARãªããžããªã®ã¢ãžã¥ãŒã«ã«ãšã©ãŒãå«ãŸããŠãããããJediã®ãã¹ã®ã¿ãæ®ããŸã-ãœãŒã¹ã³ãŒããããã©ã€ããŒããã«ãããŸãã
pecl uninstall Tarantool-PHP/Tarantool-beta cd ~ git clone https://github.com/tarantool/tarantool-php.git cd tarantool-php phpize ./configure make make install
ããŒã¿ã®èªã¿èŸŒã¿
æåã®ãã¡ã€ã«ãäœæããŠtest.phpãåŒã³åºããŠãããŒã¿ããŒã¹ã®åäœã確èªããŸãã
<?php $tarantool = new Tarantool('localhost', 3311, 'good', 'secret'); try { $tarantool->ping(); } catch (Exception $e) { echo "Exception: ", $e->getMessage(), "\n"; } ?>
ã³ãã³ãã©ã€ã³ãã
php config.php
ãå®è¡ããåäœã確èªããŸãã æ£ããæ§æããªããšããšã©ãŒã¡ãã»ãŒãžã衚瀺ãããŸãã ããããã§ãã¯ããŠãã ããïŒ
ããã§ãå¿ èŠãªãµã€ãããããŒã¿ãåéããããŒãµãŒãäœæã§ããŸãã tlgrm.ru/stickersãæ¢çŽ¢ããŸã ã ãŸãã ããã¯ããŒãã«ãèªã¿èŸŒã¿ãŸãããã®ããŒãã«ã«ã¯ãã¹ããã«ãŒããã¯ã®äººå£èª¿æ»ããããŸãã ããã¯ãtarantoolã³ãã³ãã©ã€ã³ã§ã®insertã³ãã³ãã®å€èŠ³ã§ãã
box.space.packs:upsert({'key1',0}, {{'=',2,0}})
ãã®ã³ãã³ãã¯ãæ°ããããŒãkey1ãïŒãã£ãŒã«ã1ïŒãšå€0ïŒãã£ãŒã«ã2ïŒãè¿œå ããŸãã ã¬ã³ãŒããååšããå Žåããã£ãŒã«ã0ã®åãã¬ã³ãŒãïŒ=èšå·ïŒã«å¯ŸããŠå€0ã§æŽæ°ãããŸããæãåºãããã«ããã£ãŒã«ã2ã®è©äŸ¡ã¯æåã«0ã«èšå®ãããŠããŸããupsertã³ãã³ã㯠ããããã°äžã«ããŒãµãŒãç¹°ãè¿ãå®è¡ããã®ã«äŸ¿å©ã§ãæ¯åå ¥åããããŒã¿ãåé€ããªãã§ãã ããã ã³ãã³ãã®PHPããŒãžã§ã³ã¯æ¬¡ã®ããã«ãªããŸãã
$tarantool->upsert('packs', array ($pack,0), array ( array( "field" => 1, "op" => "=", "arg" => 0 ) ));
ããããïŒ PHPã§ã¯ããã£ãŒã«ãã®çªå·ä»ãã¯0ãããLuaã§ã¯1ããã§ãããããã£ãŠãPHPé åã®
"field" => 1
ã¯ãLua
{'=',2,0}
ãšæžãããšã«å¯Ÿå¿ããŸãã ã¢ã¬ã€ããŒãããå§ãŸãå Žåã¯åžžã«ãçŸåšã®ã³ãã¯ã¿ã¯åãããã«æ©èœããŸãã ãã®åäœã¯ããŒãžã§ã³1.6以éã«å€æŽãããŠããŸãã ã€ã³ã¿ãŒãããã§äŸãèªããšãã¯ãã¿ã©ã³ãã¥ã©ã®ããŒãžã§ã³ã«æ³šæããŠãã ããïŒ ãã®èšäºã¯ããŒãžã§ã³1.7ã§æžãããŠãããéçºè ã¯ããŒãžã§ã³1.5ã«ã€ããŠãŸã£ããèŠããŠããªãããã«æ±ããããŠããŸãã
çµã¿èŸŒã¿ã®auto_incrementããã·ãŒãžã£ã䜿çšããŠã¹ããã«ãŒã®ãšã³ããªãäœæããŸããããã«ããããã©ã€ããªã€ã³ããã¯ã¹ãèªåçã«å¢å ããŸãã ã¿ã©ã³ãã¥ã©ããŒã ïŒ
box.space.stickers:auto_increment({0,'pack2','sticker2'})
PHPïŒ
$tarantool->call('box.space.stickers:auto_increment', array( array(0,$pack, $i . '.png', $url, 0, 0) ));
ãã®ãããã¹ã¯ãªãããäœæãããŸãã èµ·åããŸã-声ã«åºããŠãéæ³ïŒ ããã§ã16,000ã¬ã³ãŒãã®ããŒã¿ããŒã¹ãã§ããŸããïŒ
ããã°ã©ã ãæžã
ãŸããPHPã§éåžžè¡ãããŠããããã«ãåçŽãªã¯ãšãªã«ãŒã¿ãŒãäœæããŸãã
# Get routes from request $route = isset($_REQUEST['q']) ? $_REQUEST['q'] : '/'; $vote_plus = isset($_REQUEST['vote_plus']) ? $_REQUEST['vote_plus'] : ''; $vote_minus = isset($_REQUEST['vote_minus']) ? $_REQUEST['vote_minus'] : ''; switch ($route) { case '/good': action_good(); break; case '/bad': action_bad(); break; case '/ugly': action_ugly(); break; case '/about': action_about(); break; default: if (!empty($vote_plus) && !empty($vote_minus)) { sleep (1); do_post($vote_plus, $vote_minus); } action_main(); }
2ã€ã®å€æ°$ vote_plusããã³$ vote_minusã®ååšã«æ³šæããŠãã ããããããã¯ã1ã€ãŸãã¯å¥ã®åçã«æ祚ãããšãã«POSTãªã¯ãšã¹ãã§éä¿¡ãããŸãã å®éããã¡ã€ã«ã®ååãšãã¹ãç¥ã£ãŠããã°ããããã§æ祚ããã®ã¯éåžžã«ç°¡åã§ãããããã¯å¿ èŠãããŸããã ãããã£ãŠãæ祚ããŒãžçšã«ãåç»åã«1ã€ãã€ãäžæã®ããŒã¯ã³ã®ãã¢ãçæããŸãã æ祚åŸãããŒã¯ã³ã¯åé€ãããæ祚ãåå©çšã§ããªããªããŸãã
ããŒãžã§ã³7.0ã®ãªãªãŒã¹åã®PHPã§ã¯ãæå·åã»ãŒãæ©èœã䜿çšããããšã¯æ²ããã®ã§ãæå·åãæäœããããã®Tarantulaã®è±å¯ãªæ©èœã倧ãã«æ¯æŽããŸãã
ãŸããaction_mainé¢æ°ã§ãæå·åãããä¹±æ°ãžã§ãã¬ãŒã¿ãŒïŒã€ãŸããæ¬åœã«ã©ã³ãã ãªïŒã·ãŒããéå§ããŸãã
$r = $tarantool->evaluate( "digest = require('digest') return (digest.urandom(4))" ); $seed = unpack('L', $r[0])[1]; srand($seed);
$ tarantool-> evaluateïŒïŒé¢æ°ã¯ãã¹ãã¢ãããã·ãŒãžã£ãäœæããæéããããã«çŽæ¥Luaã³ãŒããå®è¡ããããã«äœ¿çšãããŸãã 次ã«ã create_random_voteïŒïŒé¢æ°ã2ååŒã³åºããŸããããã«ããã空éå ã®ã©ã³ãã ãªèŠçŽ ãéžæãããç»åãšããŒã¯ã³ã®URLãäœæãããŸãã
é¢æ°create_random_voteïŒïŒ
function create_random_vote() { # Get random sticker id global $tarantool; $tuple = $tarantool->call("box.space.stickers.index.primary:random", array(rand())); $id = $tuple[0][0]; $url = $tuple[0][4]; # Create random sticker token $token = $tarantool->evaluate( "digest = require('digest') return ( digest.md5_hex(digest.urandom(32)))" )[0]; $time = time(); # Set secure token to protect post action ################################################################## # # box.space.secret:insert({key', 0, 456, 'bla-bla'}) # ################################################################## $tarantool->insert('secret', array ($token, $time, $id, $url)); return array ( $url, $token ); }
ããã§ããã«2ã€ã®é¢æ°ã䜿çšãããŸããã $ tarantool-> callïŒïŒçµã¿èŸŒã¿ããã·ãŒãžã£ãåŒã³åºãã $ tarantol-> insertïŒïŒã§æ°ããã¬ã³ãŒããæ¿å ¥ããŸãã
ã¬ã³ãŒãè©äŸ¡ãæŽæ°ããæ祚æŽæ°æé ã®äŸã次ã«ç€ºããŸãã
é¢æ°update_votesïŒ$ idã$ plusã$ minusïŒ
function update_votes($id, $plus, $minus) { global $tarantool; ########################################################### # # box.space.stickers:update(1, {{'+', 6, 1}, {'+', 7, -1}}) # ########################################################### $tarantool->update("stickers", $id, array ( array( "field" => 5, "op" => "+", "arg" => $plus ), array( "field" => 6, "op" => "+", "arg" => $minus ) ) ); }
Tarantoolã¯ã©ã¹ã®ã¡ãœããã®å®å šãªãªã¹ãã«ã€ããŠã¯ã tarantool-phpã®ããã¥ã¡ã³ããåç §ããŠãã ããã
ãã©ã¡ãŒã¿ãŒ "
op" => "="
ã«æ³šæããŠãã ãããããã¯ããã£ãŒã«ããæ¢åã®ã¿ãã«ã§çœ®ãæããããããšãæå³ããŸãã ãŸãããã©ã¡ãŒã¿ãŒ+ã-ãããã³ãã®ä»ã®æäœããããŸãã 圌ãã¯éåžžã«éèŠãªã¿ã¹ã¯ãå®è¡ããŸãã éåžžãããŒã¿ããŒã¹å ã®å€ã眮ãæããã«ã¯ããŸãããã€ãã®ãã£ãŒã«ããèªã¿åã£ãŠããå€æŽããŸãã ããŒã¿ã®äžè²«æ§ãç¶æããã«ã¯ãããŒãã«ãžã®ã¢ã¯ã»ã¹ããããã¯ãããã©ã³ã¶ã¯ã·ã§ã³ã䜿çšããå¿ èŠããããŸãã Tarantulaã§ã¯ããã®ã¢ãŒããã¯ãã£ã®ãããã§ã updateããã³upsertã³ãã³ãã¯ããŒã¿ããŒã¹ãããã¯ããã«ãµãŒããŒããã»ã¹å ã§ã¢ãããã¯ã«åäœããŸãã ããã«ãããéåžžã«é«éãªã·ã¹ãã ãæ§ç¯ã§ããŸãïŒ
å·çæç¹ã§ã®index.phpãã¡ã€ã«ã®ã³ãŒãã¯ãã¿ãã¬ã§ãã
index.php
<?php # Init database $tarantool = new Tarantool('localhost', 3301, 'good', 'bad'); try { $tarantool->ping(); } catch (Exception $e) { echo "Exception: ", $e->getMessage(), "\n"; } const MIN_VOTES = 20; // Number of votes to show the ugly const UPDATE_PLUS = 1; // Increment for positive update const UPDATE_MINUS = -1; // Increment for negative update const NO_UPDATE = 0; const COOKIE = 'uuid'; // Cookie name const HIDDEN = '/img/Question.svg';// Picture for hidden element # Get routes from request $route = isset($_REQUEST['q']) ? $_REQUEST['q'] : '/'; $vote_plus = isset($_REQUEST['vote_plus']) ? $_REQUEST['vote_plus'] : ''; $vote_minus = isset($_REQUEST['vote_minus']) ? $_REQUEST['vote_minus'] : ''; # Get cookie from request or create new value $cookie = isset($_COOKIE[COOKIE]) ? $_COOKIE[COOKIE] : update_user(''); switch ($route) { case '/good': action_good(); break; case '/bad': action_bad(); break; case '/ugly': action_ugly($cookie); break; case '/about': action_about(); break; default: # This is post request: if (!empty($vote_plus) && !empty($vote_minus)) { sleep (1); $cookie = update_user($cookie); do_post($vote_plus, $vote_minus); } setcookie(COOKIE, $cookie, time() + (86400 * 30), "/"); action_main(); } exit(); function action_main() { global $tarantool; # Get crypto safe random seed from Tarantool LUA module # https://tarantool.org/doc/reference/reference_lua/digest.html $r = $tarantool->evaluate( "digest = require('digest') return (digest.urandom(4))" ); $seed = unpack('L', $r[0])[1]; srand($seed); list ($left_url, $left_token_plus) = create_random_vote(); list ($right_url, $right_token_plus) = create_random_vote(); $left_token_minus = $right_token_plus; $right_token_minus = $left_token_plus; update_stats(UPDATE_PLUS, NO_UPDATE); $title = ' Telegram'; include_once('main.html'); } function action_good() { $title = ' Telegram'; $top = get_top(10,Tarantool::ITERATOR_LE); $active_good ='class="active"'; $active_bad =''; include_once('top.html'); } function action_bad () { $title = ' Telegram'; $active_bad ='class="active"'; $active_good =''; $top = get_top(10,Tarantool::ITERATOR_GE); # Hide the ugly $top[0][4] = HIDDEN; include_once('top.html'); } function action_ugly($user) { $title = ' Telegram'; $top = get_top(1,Tarantool::ITERATOR_GE); $votes = get_session($user); # Hide the ugly until getting enough votes if ($votes < MIN_VOTES) { $ugly_message = " " . MIN_VOTES . " <br>"; $ugly_message .= " " . (MIN_VOTES - $votes) . " "; $ugly_img = HIDDEN; } else { $ugly_img = $top[0][4]; } include_once('ugly.html'); } function action_about() { $title = ' ?'; list($stickers, $shows, $votes, $visitors) = get_server_stats(); include_once('about.html'); } function do_post($vote_plus, $vote_minus) { global $tarantool; $tuple_plus = $tarantool->select("secret", $vote_plus); $tuple_minus = $tarantool->select("secret", $vote_minus); $id_plus = $tuple_plus[0][2]; $id_minus = $tuple_minus[0][2]; # Clean up used tokens if (!empty($vote_plus) && !empty($vote_minus)) { $tarantool->delete("secret", $vote_plus); $tarantool->delete("secret", $vote_minus); } # Get actual tuple data if (!empty($id_plus) && !empty($id_minus)) { $raiting = +1; update_rating($id_plus, $raiting); $raiting = -1; update_rating($id_minus, $raiting); update_votes($id_plus, UPDATE_PLUS, NO_UPDATE); update_votes($id_minus, NO_UPDATE, UPDATE_MINUS); update_stats(NO_UPDATE, UPDATE_PLUS); } } function create_random_vote() { # Get random sticker id global $tarantool; $tuple = $tarantool->call("box.space.stickers.index.primary:random", array(rand())); $id = $tuple[0][0]; $url = $tuple[0][4]; # Create random sticker token $token = $tarantool->evaluate( "digest = require('digest') return ( digest.md5_hex(digest.urandom(32)))" )[0]; $time = time(); # Set secure token to protect post action ################################################################## # # box.space.secret:insert({key', 0, 456, 'bla-bla'}) # ################################################################## $tarantool->insert('secret', array ($token, $time, $id, $url)); return array ( $url, $token ); } function update_rating($id, $update) { global $tarantool; ################################################# # # box.space.stickers:update(7856, {{'+', 2, 10}}) # ################################################# $tarantool->update("stickers", $id, array ( array( "field" => 1, "op" => "+", "arg" => $update ) )); } function update_votes($id, $plus, $minus) { global $tarantool; ########################################################### # # box.space.stickers:update(1, {{'+', 6, 1}, {'+', 7, -1}}) # ########################################################### $tarantool->update("stickers", $id, array ( array( "field" => 5, "op" => "+", "arg" => $plus ), array( "field" => 6, "op" => "+", "arg" => $minus ) ) ); } function update_user($cookie) { global $tarantool; # Create uuid if first time user if (empty($cookie)) { ################################## # # uuid = require('uuid') # uuid() # ################################## $uuid = $tarantool->evaluate( "uuid = require('uuid') return (uuid.str())" )[0]; } else { $uuid = $cookie; } $time = time(); $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''; $agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; # Create session or update user stat inside ########################################################### # # box.space.sessions:upsert({'111222333', 123456, 0, 'ip', 'agent'}, # {{'=', 2, 1}, {'+', 3, 1}, {'=', 4, 'ip'}, {'=', 5, 'agent'}}) # ########################################################### # Please check https://github.com/tarantool/tarantool-php/issues/111 $tarantool->upsert("sessions", array($uuid, $time, 0, $ip, $agent), array ( array( "field" => 1 "op" => "=", "arg" => $time ), array( "field" => 2 "op" => "+", "arg" => 1 ), array( "field" => 3 "op" => "=", "arg" => $ip ), array( "field" => 4, "op" => "=", "arg" => $agent ) ) ); return($uuid); } function update_stats($vote, $click) { global $tarantool; ######################################################## # # box.space.server:update(1, {{'+', 3, 1}, {'+', 4, 1}}) # ######################################################## $tarantool->update("server",1, array ( array( "field" => 2, "op" => "+", "arg" => $vote ), array( "field" => 3, "op" => "+", "arg" => $click ) ) ); } function get_session($sid) { global $tarantool; ########################################## # # box.space.sessions:select('id') # ######################################### if (strlen($sid) > 16) { return $tarantool->select("sessions", $sid)[0][2]; } else { return 0; } } function get_top($limit, $iterator) { global $tarantool; ###################################################################################### # # box.space.stickers.index.secondary:select({primary}, {iterator = box.index.GE, offset=0, limit=10}) # ###################################################################################### $result = $tarantool->select("stickers", null, 'secondary', $limit, 0, $iterator); return $result; } function get_server_stats() { global $tarantool; $time = time() - 30*86400; // one month before $stickers = $tarantool->call('box.space.stickers:count')[0][0]; $tuple = $tarantool->select('server',1); $shows = $tuple[0][2]; $votes = $tuple[0][3]; $visitors = $tarantool->call('box.space.sessions.index.secondary:count', array($time, array('iterator' => Tarantool::ITERATOR_GE)) )[0][0]; # $shows, $votes, $visitors) = get_server_stats(); return array($stickers, $shows, $votes, $visitors); } ?>
ãµã€ãããã³æ祚ããŒãžã§ã®æ祚çšã«åçä»ãã®ããŒã¿ã衚瀺ããHTMLãã³ãã¬ãŒããäœæããããšã¯æ®ã£ãŠããŸãã
æ祚åçã®ãµã³ãã«ã³ãŒã
<!-- --> <div class="voting container"> <div class="voting-zone"> <!-- --> <div class="sticker" onclick="myFunction()"> <form name="voteFormLeft" id="idForm" method ="POST" action="/" > <input class= "pic1" id="left_url" type="image" src="<?php echo $left_url?>" alt="Vote left" > <input type="hidden" name="vote_plus" value="<?php echo $left_token_plus?>"> <input type="hidden" name="vote_minus" value="<?php echo $left_token_minus?>"> </form> </div> <!-- --> <div class="sticker" onclick="myFunction()"> <form name="voteFormRight" id="idForm" method ="POST" action="/"> <input class= "pic2" id="right_url" type="image" src="<?php echo $right_url?>" alt="Vote right" > <input type="hidden" name="vote_plus" value="<?php echo $right_token_plus?>" > <input type="hidden" name="vote_minus" value="<?php echo $right_token_minus?>" > </form> </div> </div> </div> <!-- -->
çæ³çã«ã¯HTMLã³ãŒãããã©ãŒãããããã¬ã€ã¢ãŠããã¶ã€ããŒã®ç掻ã®äžã§èª°ããåºäŒã£ãããšããããŸããïŒ

èšäºã®çµããã«éããèªè ã¯ãèè ã®ãããŒãªã³ã°ã«èŠãã¿ã圌ã®æããããäœåºŠãç ®è©°ãŸã£ããåœç¶ã®å ±é ¬ãæ³å®ãããŠããŸããããªããçªããšã¯ãªãã¯ããããšãã§ããå®éã®äœæ¥äŸãããèå³æ·±ããã®ã¯äœã§ããïŒugly.begetan.meã® Telegramã¹ããã«ãŒã«æ祚ããŠãã©ããæãuããã®ããèŠã€ããŠãã ãããNGNIXãPHP-FPMãTarantoolããçµã¿ç«ãŠããããã·ã¢ã®é«è² è·ã®åšãã§ããŠã¹ãçªãããŸããçµ±èšçã«ä¿¡é Œã§ããæ祚ã®ç»åãååŸããã«ã¯å€æ°ã®æ祚ãå¿ èŠãªã®ã§ãã¬ãŒã«ãã¬ã³ããžã®ãªã³ã¯ã衚瀺ããããšãå¿ããªãã§ãã ããã