slowpokeã¯ãgolangæšæºã©ã€ãã©ãªã§èšè¿°ãããããŒ/ããªã¥ãŒããŒã¿ãŠã§ã¢ããŠã¹ã§ãã Slowpokeã«ã¯æå°éã®äŸ¿å©ãªAPIããããããªãå¹ åºãã¿ã¹ã¯ã解決ããã®ã«é©ããŠããŸãã
Setã³ãã³ãã䜿çšããŠãslowpokeã«å€ãæžã蟌ãããšãã§ããŸãã
slowpoke.Set("db/some.db", []byte("foo"), []byte("bar"))
slowpokeã®ããŒã¿ã¹ãã¬ãŒãžã®åäœã¯ãã¡ã€ã«ã§ãã ãã®äŸã§ã¯ããã¡ã€ã«ãsome.dbããšãšãã«ãdbããã£ã¬ã¯ããªãäœæãããããã«3ãã€ãïŒãbarãïŒãé 眮ãããŸãã
å³å¯ã«èšãã°ãslowpokeã®ãã¹ãŠã®ãã¡ã€ã«ã¯ç¬ç«ããããŒã¿ããŒã¹ã§ãã åããŒã¿ããŒã¹ã¯åå¥ã®ãŽã«ãŒãã³ã§ç®¡çãããŸãã ãã¡ã€ã«ã®ãªãŒãã³/èªã¿åãã¯èªåçã«è¡ãããŸãã ã€ãŸã ãã®ããŒã¿ããŒã¹ãååšããå ŽåãéããŠèªã¿åãããŸãã ããã§ãªãå Žåã¯ãäœæãããŸãã ãã®æ©èœã䜿çšãããšãããŒã¿ããŒã¹ã®æäœæã«ããŒã¿ããŒã¹ã®ç¶æ ãèæ ®ããã«äœ¿çšã§ããŸããããšãã°ãhttpèŠæ±ãã³ãã©ãŒãä»ã®ãŽã«ãŒãã³ã§äœ¿çšã§ããŸãã
ããŒãšå€ãšããŠãslowpokeã¯ãã€ãã®é åãåããŸãã äžèšã®äŸã§ã¯ãããŒãšå€ã¯åºæ¬çã«æååã§ãã slowpokeã§æ°åãæžããŸãã
for i := 0; i < 40; i++ { id := make([]byte, 4) binary.BigEndian.PutUint32(id, uint32(i)) slowpoke.Set("numeric.db", id, nil) }
æ°å€ãBigEndian圢åŒã«å€æããŸãããããã«ãããä»åŸã®äœæ¥ã§ããŒã®äžŠã¹æ¿ããæ£ããèæ ®ããããšãã§ããŸãã ãã®äŸã®å€ã¯æå®ãããŠããããããŒã®é åã®ã¿ãäœæãããŸãïŒãnumeric.dbãã®ãµã€ãºã¯0ãã€ãã«ãªããŸãïŒã ããŒãšããã°ãslowpokeã®ããŒã¯ã¡ã¢ãªã«ä¿åãããŸããããã£ã¹ã¯ã«ä¿åãããŸãã
ããã«ãããäžæ¹ã§ããŒã䜿çšããŠãã°ããæäœããä»æ¹ã§ååãªRAMããªãå Žåã¯ããŒãã«ãéããããšãã§ããŸãã ãã®ããã倧ããªããŒã¯ãå§ãããŸããã 1ã€ã®ããŒãã«ã®ãã¹ãŠã®ããŒã®æé©ãªåèšãµã€ãºã¯10ã¡ã¬ãã€ãã§ãããšæ³å®ããŠããŸãã ãã®ãµã€ãºãè¶ ããå Žåã¯ãããŒã¿ããŒã¹ãè€æ°ã®ããŒãã«ã«åå²ããããšããå§ãããŸãã å€ã¯ã¡ã¢ãªã«ä¿åããããä»»æã®ãµã€ãºïŒç»åããã£ã«ã ïŒã«ããããšãã§ããŸãã å€ããŒãã«ã®åèšãµã€ãºã¯uint32ãè¶ ããããšã¯ã§ããŸããã ãã®ã¢ãããŒãã®ããã€ãã®å©ç¹ïŒããŒãšå€ã®åå¥ã®ã¹ãã¬ãŒãžïŒã¯ãèšäºwww.usenix.org/system/files/conference/fast16/fast16-papers-lu.pdfã§èª¬æãããŠããŸãïŒãã®èšäºã§ã¯ãssd LsmããªãŒãã£ã¹ã¯ããã³ãã®ä»ã®ã¢ãŒããã¯ãã£ãŒã«çŠç¹ãåœãŠãŠããŸãïŒ slowpokeã§ã¯äœ¿çšãããŸããïŒ
slowpokeã«æ»ããŸãã æ°å€ãè¡ããã¡ã€ã«ãªã©ã«å ããŠãããããã®ã¡ãœããã§ãªããžã§ã¯ããã·ãªã¢ã«åããããšã§ãªããžã§ã¯ããä¿åã§ããŸãã JSONã§ã®ã·ãªã¢ã«åã®äŸïŒ
binary, _ := json.Marshal(post) slowpoke.Set("json",key,binary)
ãŸãã¯ãgolangã«çµã¿èŸŒãŸããŠããgobããã±ãŒãžã䜿çšããŸãïŒ golang.org/pkg/encoding/gob
slowpokeã®ãã¹ãŠã®æžã蟌ã¿ã³ãã³ãã¯ã¢ãããã¯ã§ãããsyncã³ãã³ãïŒããŒã¿åæïŒã§çµãããŸãã å®éãææ°ã®ãã¡ã€ã«ã·ã¹ãã ã¯ããã¡ã€ã«ã«æžã蟌ãŸãããšãæ¬è³ªçã«ãããã¡ã«æžã蟌ãŸããŸãã ãŸãããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãã¯ã©ãã·ã¥ãããšããããã¡ã倱ãããŸãã ã»ãšãã©ã®ããŒã¿ããŒã¹ã«ã¯nosyncã¢ãŒãããããŸãïŒå¥ã®ååã§åŒã³åºãããšãã§ããŸãããæçµçã«ã¯åææäœãéåžžã«é ããšããããšã§ããããã¯ç¹ã«å€ãããŒããã©ã€ãã§é¡èã§
slowpokeã«ã¯ãnosyncãã¢ãŒãã¯ãããŸããããããã£ãŠã
slowpokeã«è€æ°ã®ã¬ã³ãŒããæ¿å ¥ããã«ã¯ãSetsã³ãã³ãã䜿çšããŸãã
ãã®ã³ãã³ãã¯ãããŒ/å€ããã±ãŒãžãäœæããããã«ãå§ãããŸãã ãã®å ŽåãããŒã¿ã¯ãã¡ã€ã«ãããã¡ã«æžã蟌ãŸããèšé²ã®æåŸã«1åã ãåæãããŸãã èšé²é床ãåçã«åäžãããããšã«ãããããŒã¿ã®äžè¬çãªå®å šæ§ãç ç²ã«ããããšã¯ã§ããŸããã Setsã³ãã³ãã®äœ¿çšäŸïŒ
var pairs [][]byte for i := 0; i < 40; i++ { id := make([]byte, 4) binary.BigEndian.PutUint32(id, uint32(i)) post := &Post{Id: i, Content: "Content:" + strconv.Itoa(i), Category: "Category:" + strconv.Itoa(i/10)} b, _ := json.Marshal(post) pairs = append(pairs, id) pairs = append(pairs, b) } //store posts fast slowpoke.Sets(posts, pairs)
äžèšã®äŸã§ã¯ãæåã«ããŒ/å€ã®ãã¢ã®é åã圢æããã次ã«èšé²ãããŸãã
setã³ãã³ããšsetã³ãã³ãã䜿çšããŠãslowpokeã§ããŒã¿ãä¿åããæ¹æ³ãåŠã³ãŸããã ãã ããã³ãã³ããèªã¿å§ããåã«ãslowpokeããããŒãååŸããã³ãã³ããæ€èšããŠãã ããã
slowpokeã§ããŒãæäœããããã«ãKeysã³ãã³ããçµã¿èŸŒãŸããŠããŸãã
ããŒã¯ãslowpokeããæœåºã§ããŸãã
- çŽæ¥æ³šæ
- éé
- ãªãã»ãã
- ããå€ãã
- éžæãããã¬ãã£ãã¯ã¹
ã³ãã³ãäŸïŒ
//get last 2 post key with offset 2 limit := uint32(2) offset := uint32(2) order := false //descending keys, _ := slowpoke.Keys(posts, nil, limit, offset, order)
ããŒããŒã ã«ã¯ããã€ãã®ã«ãŒã«ããããŸãã
å¶éãèšå®ãããŠããªãå Žåããã¹ãŠã®ããŒãè¿ãããŸãã
fromãã£ãŒã«ããæå®ãããŠããïŒnilãšçãããªãïŒå ŽåãããŒã¯ãã®å€ã®åŸã«è¿ãããŸãïŒå€èªäœã¯å«ãŸããŸããïŒã
äžèŽããããŒããªãå Žåã空ã®é åãè¿ãããŸãã
å éšã®ããŒã¯ããã€ãã®é åãšããŠè¡šãããŸãã ãããã£ãŠãããšãã°ãæ£ãããœãŒããããæ°å€ãååŸããã«ã¯ãããããBigEndianã«å€æããå¿ èŠããããŸãã
Keysã³ãã³ãã¯ã¡ã¢ãªå ã®ããŒã¿ãæäœãããã£ã¹ã¯ã«ã¯ã¢ã¯ã»ã¹ããŸããã å éšã§ã¯ãslowpokeã§ãããŒã¯é åïŒã¹ã©ã€ã¹ïŒã«è€è£œãããåã¹ã©ã€ã¹ã¯ããŒãã«ã®äžã«äœæãããKeysåŒã³åºãæã«ãœãŒããããŸãïŒå¿ èŠãªå ŽåïŒã ãã¬ãã£ãã¯ã¹/å€ã§éžæããå Žåããã€ããªæ€çŽ¢ã䜿çšãããŸãïŒå¯èœãªå ŽåïŒã Keysã³ãã³ãã¯ãäžèšã®çç±ããGet / Getsãããåªå ãããŸãã
ããŒãžããŒã·ã§ã³ã®å¯èœæ§ã次ã®å€ã®éžæã«å ããŠãKeysã³ãã³ãã䜿çšãããšãç¹å®ã®ãã¬ãã£ãã¯ã¹ã§ããŒãéžæã§ããŸãã ããšãã°ãtagsïŒidãŸãã¯emailïŒusernameããŒã¯ããŒã¿ããŒã¹ã«ä¿åã§ããŸãã ãã®å Žåã[]ãã€ãïŒ "sexïŒ*"ïŒãªã©ãæ«å°Ÿã«*æåãå«ãå€ãfromãã£ãŒã«ãã«è»¢éããå¿ èŠããããŸãã ãŸããå€ãæããªãããŒãäœæããå¯èœæ§ã«ã€ããŠãæãåºããŸããããã¯ãã€ã³ããã¯ã¹ãã¡ã¢ãªã«æ ŒçŽããã®ã«äŸ¿å©ã§ãïŒå€ã®ãªãããŒããã£ã¹ã¯ã«æ ŒçŽãããå Žåã§ããé害ãŸãã¯ããŒãã«ãéããå Žåã®å埩ã®å¯èœæ§ã®ããïŒã
Keysã³ãã³ããšçµã¿åãããŠå€ãéžæããã«ã¯ãGetsã³ãã³ãã䜿çšãããšäŸ¿å©ã§ãã
Getsã³ãã³ãã¯ãããŒã®é åïŒã€ãŸããKeysã³ãã³ãã®çµæïŒãåãåããŸãã äŸïŒ
keys, _ := slowpoke.Keys(posts, nil, limit, offset, order) //get key/ values res := slowpoke.Gets(posts, keys)
Getsã³ãã³ãã®çµæã¯ãããŒãšå€ã®ãã¢ã®é åã§ãã 泚ïŒ
-ãšã©ãŒãè¿ããªãå¯äžã®ã³ãã³ã
-ããŒã®1ã€ãæ¬ èœããŠããå Žåãã¹ããããããŸã
-ããŒããªãå Žåã空ã®é åãè¿ãããŸã
ãŸããSetsã³ãã³ãã¯ãããŒ/å€ã®ãã¢ãå ¥åãšããŠåãå ¥ããŸãã ããšãã°ãå¥ã®ããŒãã«ã«ããŒã¿ãä¿åããããã«äœ¿çšã§ãããã®ã
ããŒ-ããŒã®é åãè¿ããŸã
Gets-ããŒã®é åãåãåãããã¢ã®é åãè¿ããŸã
ã»ãã-ãã¢ã®é åãåãå ¥ããŸã
å€ã®ã°ã«ãŒããæäœããé¢æ°ã¯ãåäžã®å€ãæäœããé¢æ°ãããé«éã§ãããšèšãå¿ èŠã¯ãããããªãã§ãããã
åäžã®å€ãéžæããã«ã¯ãGetã³ãã³ãã䜿çšããŸãã
res, err := slowpoke.Get(file, key)
å€ããªãå ŽåãGetã¯nilãè¿ããããŒãšã©ãŒã¯èŠã€ãããŸããã§ããã
CloseAllïŒïŒã³ãã³ã -ãã¹ãŠã®ã¢ã¯ãã£ããªããŒã¿ããŒã¹ãéããŸããäœæ¥ã®æåŸã«åŒã³åºãå¿ èŠããããŸããäŸïŒ
sigchan := make(chan os.Signal, 10) signal.Notify(sigchan, os.Interrupt) <-sigchan // slowpoke.CloseAll()
ãã®ããã«ïŒdefpoke slowpoke.CloseAllïŒïŒ
åºæ¬çãªslowpokeã³ãã³ãã«ã€ããŠèª¬æããŸããããããã«é«åºŠãªã³ãã³ãããããŸãã
Openã³ãã³ã-ããŒã¿ããŒã¹ãéããããŒãã¡ã¢ãªã«èªã¿èŸŒã¿ãŸãã
éããã³ãã³ã-ããŒã¿ããŒã¹ãéããã¡ã¢ãªããããŒãã¢ã³ããŒãããŸãã
RAMã®ãµã€ãºã§éããŠããããŒã¿ããŒã¹ã®ãã¹ãŠã®ããŒãä¿åã§ããå Žåããããã®ã³ãã³ããæåã§åŒã³åºãå¿ èŠã¯ãããŸããã ãããã®ã³ãã³ãã¯ã次ã®å Žåã«åœ¹ç«ã¡ãŸãã
äŸ1ïŒãã°ãä¿åãã
æéééã®ãã°ã¯ãã¢ã®é åã§åéãããSetsã³ãã³ãã䜿çšããŠæ¿å ¥ãããŸã
ãããŠãããšãã°ããlogs / 20170101.dbããªã©ããã°ã®æ¥ä»ã«å¯Ÿå¿ãããã¡ã€ã«ã«èšé²ãããŸã
ãã®ééã§ã®äœæ¥ã®çµããã«ãããŒã¿ããŒã¹ãlogs / 20170101.dbããéããŠãloseã³ãã³ãã䜿çšããŠã¡ã¢ãªããã¢ã³ããŒãã§ããŸãã ãã®ããŒã¿ããŒã¹ãžã®èŠæ±ãããã°ãèªåçã«éãããèªã¿åãããŸãã
äŸ2ïŒãããã¯ãã§ãŒã³ãã©ã³ã¶ã¯ã·ã§ã³ãã§ãŒã³
åãã©ã³ã¶ã¯ã·ã§ã³ã«çªå·ããããšããŸãã 1000.dbãªã©ã®åãã©ã³ã¶ã¯ã·ã§ã³ããŒã«ãåå¥ã®ãã¡ã€ã«ã«ä¿åããã®ãé©åãªå ŽåããããŸãã1ã1000ã®ãã©ã³ã¶ã¯ã·ã§ã³ã«å¯Ÿå¿ãããã®ãããã¯ãžã®ã¢ã¯ã»ã¹ãæ¯èŒçãŸããªå Žåã¯ãèšé²ã®æåŸã«ã¡ã¢ãªããã¢ã³ããŒãããŸãã
äŸ3ïŒãŠã§ããµã€ãã®ãã¹ãã£ã³ã°
åãµã€ãã®ããŒã¿ã¯ãsites / mysite.com.dbãªã©ã®åå¥ã®ãã©ã«ããŒã«ä¿åã§ããŸãã
ãããããã®èªã¿åããæ¯èŒçãŸããªå Žåã¯ãæŽæ°åŸã«ã¢ã³ããŒãããŸãã slowpokeã®ããŒã¯å€ãšã¯å¥ã«ä¿åãããããããã¡ã€ã«ããã¢ã³ããŒããããããŒãã¡ã¢ãªã«èªã¿èŸŒãã®ã¯ç°¡åãªæäœã§ãã
ããŒã¿ããŒã¹DeleteFileïŒïŒãåé€ããã³ãã³ãããããŸã
建ç¯
slowpokeã¯golangæšæºã©ã€ãã©ãªã§æžãããŠããŸãã ããŒã®ä¿åã«ã¯ãããããšã¹ã©ã€ã¹ã䜿çšãããŸãã ã¹ã±ãŒãªã³ã°ã¯ãåããŒã¿ããŒã¹ãåå¥ã®ãŽã«ãŒãã³ã§å®è¡ããããšã«ããå®çŸãããŸãã
å€ã¯ãã®ãŸãŸããªãŒããŒããããªãã§ãã£ã¹ã¯äžã«ã®ã¿ä¿åãããå€ã®ã¢ãã¬ã¹ãžã®ãªã³ã¯ã¯ã¡ã¢ãªã«ä¿åãããŸãã ãããžã§ã¯ãã§ã¯BTreeãLSM Treeã䜿çšãããŠããŸããã ãŸããmmapãã¯ãããžãŒã¯äœ¿çšãããŸããïŒèšç»ãããŠããŸããïŒã å®è·µã瀺ãããã«ãããŒã¿ããŒã¹ã®ã¢ãŒããã¯ãã£ãè€éã«ãªãã»ã©ãããŒã¿ããŒã¹ã®æé·ã«äŒŽãåé¡ãå€ããªããŸãã ç¡æã§ã¯äœãèµ·ãããªãã®ã§ã
ã¢ãŒããã¯ãã£ã®ã·ã³ãã«ãã®è£åŽã¯ããããã®å Žåã§ãæšæºçãªæž¬å®ã§ãåžå Žã®ãªãŒããŒãšæ¯èŒããŠé ãspokepokeããã©ãŒãã³ã¹ã§ãïŒ
//macbook 2017 slowpoke vs boltdb //The 100 Set took 19.440075ms to run./19.272079ms //The 100 Sets took 1.139579ms to run./? //The 100 Get took 671.343µs to run./211.878µs //The 100 Gets took 206.775µs to run./? //The 100 Keys took 36.214µs to run./? //The second 100 Keys took 5.632µs to run./?
ããšãã°ãLSMããªãŒïŒrocksdbãleveldbãcassandraãbadgerïŒã䜿çšããããŒã¿ããŒã¹ã§ã¯ãæžã蟌ã¿ãé«éã«ãªããŸãã
mmapã䜿çšããããŒã¿ããŒã¹-ïŒLMDBãBoltdbãSophiaDbïŒå€ã®èªã¿åããé«éã«ãªããŸãïŒslowpokeã¯å€ããã£ãã·ã¥ããŸããïŒ
ãã ããäžè¬çã«ãããŒã¿ããŒã¹ã®ååã瀺ãããã«ãã¢ãŒããã¯ãã£ã®åçŽãã®ç¹ã§ããªãã®é©ãããããæ倱ã¯æå°éã§ãããslowpokeã¯ããæŽç·Žããã競åä»ç€Ÿãããããã©ãŒãã³ã¹ãåªããŠããŸããã å€æ°ã®ãã³ãããŒã¯ããããžã§ã¯ãããã³åå¥ã®ãªããžããªã«ãããŸãã
golang以å€ã®ããã°ã©ãã³ã°èšèªã§slowpokeã䜿çšããã«ã¯ãå°ããªããŒã¿ããŒã¹ãµãŒããŒã®äŸãhttpã«èšè¿°ããŸãã ãŸãããã£ãããšãã®ãšã³ãžã³ã§ãã倧ããªãããžã§ã¯ããèŠãŸããã
REST APIãšããŠããã¯ãã¢ãåããGRPCãµãŒããŒ
çŸæç¹ã§ã¯ãslowpokesã¯è¥ããŠæ®åããŠããããsnatchnews.comã®APIïŒrest APIãä»ããã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ïŒãšããŠãå人ã®ããããããžã§ã¯ãïŒãã¬ã°ã©ã ããããtggram.comãµã€ããªã©ïŒã§å人ãäž»ã«äœ¿çšããŠããŸãã çè«çã«ã¯ã倧éã®ããŒã¿ã®ä¿åã䌎ããããžã§ã¯ã-ipdb.ioãŸãã¯leveldb / badgerãªã©ã®ããè€éãªããŒã¿ããŒã¹ã®ä»£æ¿ãšããŠã®ã€ãŒãµãªã¢ã ã«é©ããŠããŸãã
ãªã¯ãšã¹ããããŒã«ããããšãã§ããŠããããã§ãã