{"id":13763502,"url":"https://github.com/recoilme/slowpoke","last_synced_at":"2025-05-10T17:30:34.965Z","repository":{"id":57486886,"uuid":"122040719","full_name":"recoilme/slowpoke","owner":"recoilme","description":"Low-level key/value store in pure Go. ","archived":true,"fork":false,"pushed_at":"2019-09-30T09:10:54.000Z","size":2334,"stargazers_count":100,"open_issues_count":0,"forks_count":9,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-11-16T22:33:06.347Z","etag":null,"topics":["database","embedded","engine","golang","key-value","persistence"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/recoilme.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-02-19T09:22:37.000Z","updated_at":"2024-02-07T10:52:49.000Z","dependencies_parsed_at":"2022-09-01T23:01:17.186Z","dependency_job_id":null,"html_url":"https://github.com/recoilme/slowpoke","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recoilme%2Fslowpoke","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recoilme%2Fslowpoke/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recoilme%2Fslowpoke/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/recoilme%2Fslowpoke/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/recoilme","download_url":"https://codeload.github.com/recoilme/slowpoke/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253453148,"owners_count":21911049,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","embedded","engine","golang","key-value","persistence"],"created_at":"2024-08-03T15:00:49.207Z","updated_at":"2025-05-10T17:30:34.681Z","avatar_url":"https://github.com/recoilme.png","language":"Go","funding_links":[],"categories":["Database","数据库","数据库  `go语言实现的数据库`","Uncategorized"],"sub_categories":["Advanced Console UIs","标准 CLI"],"readme":"[![Build Status](https://travis-ci.org/recoilme/slowpoke.svg?branch=master)](https://travis-ci.org/recoilme/slowpoke) [![Go Report Card](https://goreportcard.com/badge/github.com/recoilme/slowpoke)](https://goreportcard.com/report/github.com/recoilme/slowpoke)\n[![Documentation](https://godoc.org/github.com/recoilme/slowpoke?status.svg)](https://godoc.org/github.com/recoilme/slowpoke)\n\n**Description**\n\nPackage slowpoke is a simple key/value store written using Go's standard library only. Keys are stored in memory (with persistence), values stored on disk.\n\nDescription on russian: https://habr.com/post/354224/\n\n![slowpoke](http://tggram.com/media/recoilme/photos/file_488344.jpg)\n\n**Motivation**\n\nReplace [Bolt](https://github.com/boltdb/bolt) with a simpler and more efficient engine.\n\nSlowpoke (from version 2.0) based on [pudge](https://github.com/recoilme/pudge)\n\n**How it works**\n\nKeys are stored in memory with persistence to disk. Values stored on disk only.\n\n**Slowpoke is parallel**\n\n\n![](https://habrastorage.org/webt/yp/ok/c3/ypokc33wp-p1jcewq4a221di1hu.png)\n\n\n**Server**\n\n\nGRPC Server example: [okdb](https://github.com/recoilme/okdb)\n\n**Complex examples**\n\n[typegram](https://github.com/recoilme/tgram)\n\nzen platform for authors and their subscribers with a minimalistic design and user-friendly interface.\n\n[golang-gin-realworld-example-app](https://github.com/recoilme/golang-gin-realworld-example-app)\n\nThis codebase was created to demonstrate a fully fledged fullstack application built with Golang/Gin/Slowpoke including CRUD operations, authentication, routing, pagination, and more.\n\n\n**Basic example**\n\n```golang\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/recoilme/slowpoke\"\n)\n\nfunc main() {\n\t// create database\n\tfile := \"test/example.db\"\n\t// close all opened database\n\tdefer slowpoke.CloseAll()\n\t// init key/val\n\tkey := []byte(\"foo\")\n\tval := []byte(\"bar\")\n\t//store\n\tslowpoke.Set(file, key, val)\n\t// get\n\tres, _ := slowpoke.Get(file, key)\n\t//result\n\tfmt.Println(string(res))\n}\n```\n\n**Lazy example**\n\n```golang\nfunc TestGob(t *testing.T) {\n\tfile := \"test/gob.db\"\n\tDeleteFile(file)\n\tdefer CloseAll()\n\ttype Post struct {\n\t\tId       int\n\t\tContent  string\n\t\tCategory string\n\t}\n\n\tfor i := 0; i \u003c 20; i++ {\n\t\tpost := \u0026Post{Id: i, Content: \"Content:\" + strconv.Itoa(i)}\n\t\terr := SetGob(file, post.Id, post)\n\t\tch(err, t)\n\t}\n\n\tfor i := 0; i \u003c 20; i++ {\n\t\tvar post = new(Post)\n\t\terr := GetGob(file, i, post)\n\t\tch(err, t)\n\t\tfmt.Println(\"i:\", i, \"Post:\", post)\n\t}\n}\n```\n\n**Advanced example**\n\n```golang\ntype Post struct {\n\tId       int\n\tContent  string\n\tCategory string\n}\n\nfunc main() {\n\tposts := \"test/posts\"\n\ttags := \"test/tags\"\n\tvar pairs [][]byte\n\tfor i := 0; i \u003c 40; i++ {\n\t\tid := make([]byte, 4)\n\t\tbinary.BigEndian.PutUint32(id, uint32(i))\n\t\tpost := \u0026Post{Id: i, Content: \"Content:\" + strconv.Itoa(i), Category: \"Category:\" + strconv.Itoa(i/10)}\n\t\tb, _ := json.Marshal(post)\n\t\tpairs = append(pairs, id)\n\t\tpairs = append(pairs, b)\n\t\ttag := fmt.Sprintf(\"%s:%08d\", strconv.Itoa(i/10), i)\n\t\t//store only tags keys\n\t\tslowpoke.Set(tags, []byte(tag), nil)\n\t}\n\t//store posts fast\n\tslowpoke.Sets(posts, pairs)\n\n\t//get last 2 post key with offset 2\n\tlimit := uint32(2)\n\toffset := uint32(2)\n\torder := false //desc\n\tkeys, _ := slowpoke.Keys(posts, nil, limit, offset, order)\n\tfmt.Println(keys) //[[0 0 0 37] [0 0 0 36]]\n\n\t//get key/ values\n\tres := slowpoke.Gets(posts, keys)\n\tfor k, v := range res {\n\t\tif k%2 == 0 {\n\t\t\tfmt.Print(binary.BigEndian.Uint32(v))\n\t\t} else {\n\t\t\tvar p Post\n\t\t\tjson.Unmarshal(v, \u0026p)\n\t\t\tfmt.Println(p)\n\t\t}\n\t}\n\t//37{37 Content:37 Category:3}\n\t//36{36 Content:36 Category:3}\n\n\t//free from memory\n\tslowpoke.Close(posts)\n\tslowpoke.Close(tags)\n\n\t//open Db and read tags by prefix 2:* in ascending order\n\ttagsKeys, _ := slowpoke.Keys(tags, []byte(\"2:*\"), 0, 0, true)\n\tfor _, v := range tagsKeys {\n\t\tfmt.Print(string(v) + \", \")\n\t}\n\t//2:00000020, 2:00000021, 2:00000022, 2:00000023, 2:00000024, 2:00000025, 2:00000026, 2:00000027, 2:00000028, 2:00000029,\n}\n```\n\n**Api**\n\nAll methods are thread-safe.\n\n\n- **Set/Sets/SetGob** \n\nStore val and key. If the file does not exist it will be created. \n\n\n- **Get/Gets/GetGob** \n\nReturn the value for the given key or nil and an error. `Get` will open the database if necessary.\n\n- **Keys** \n\nReturn keys in ascending/descending order. \n\nWith limit and offset.\n\nIf `from` is not nil, return keys lexicographically greater than the `from` value.\n\nIf `from` ends with asterix `*`, return keys with the prefix equal to `from` without the asterix.\n\n\n[Documentation](https://godoc.org/github.com/recoilme/slowpoke)\n\n\n**Status**\n\nUsed in production (master branch)\n\n\n**Benchmark**\n\n\n[All tests here](https://github.com/recoilme/pogreb-bench)\n\n\nSome tests, MacBook Pro (Retina, 13-inch, Early 2015)\n\n\n### Test 1\nNumber of keys: 1000000\nMinimum key size: 16, maximum key size: 64\nMinimum value size: 128, maximum value size: 512\nConcurrency: 2\n\n\n|                       | pogreb  | goleveldb | bolt   | badgerdb | pudge  | slowpoke | pudge(mem) |\n|-----------------------|---------|-----------|--------|----------|--------|----------|------------|\n| 1M (Put+Get), seconds | 187     | 38        | 126    | 34       | 23     | 23       | 2          |\n| 1M Put, ops/sec       | 5336    | 34743     | 8054   | 33539    | 47298  | 46789    | 439581     |\n| 1M Get, ops/sec       | 1782423 | 98406     | 499871 | 220597   | 499172 | 445783   | 1652069    |\n| FileSize,Mb           | 568     | 357       | 552    | 487      | 358    | 358      | 358        |","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frecoilme%2Fslowpoke","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frecoilme%2Fslowpoke","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frecoilme%2Fslowpoke/lists"}