{"id":16980973,"url":"https://github.com/guzba/respite","last_synced_at":"2025-03-23T17:31:05.511Z","repository":{"id":235212508,"uuid":"789248693","full_name":"guzba/respite","owner":"guzba","description":"Redis protocol backed by SQLite.","archived":false,"fork":false,"pushed_at":"2024-04-22T16:45:52.000Z","size":86,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-18T22:23:40.155Z","etag":null,"topics":["database","nim","redis","redis-server","sql","sqlite"],"latest_commit_sha":null,"homepage":"","language":"Nim","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/guzba.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,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-04-20T03:09:16.000Z","updated_at":"2025-01-24T23:05:56.000Z","dependencies_parsed_at":"2024-04-26T05:31:21.836Z","dependency_job_id":null,"html_url":"https://github.com/guzba/respite","commit_stats":null,"previous_names":["guzba/respite"],"tags_count":1,"template":false,"template_full_name":"treeform/nimtemplate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guzba%2Frespite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guzba%2Frespite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guzba%2Frespite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guzba%2Frespite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/guzba","download_url":"https://codeload.github.com/guzba/respite/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245140875,"owners_count":20567461,"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","nim","redis","redis-server","sql","sqlite"],"created_at":"2024-10-14T02:04:16.685Z","updated_at":"2025-03-23T17:31:04.893Z","avatar_url":"https://github.com/guzba.png","language":"Nim","readme":"# Respite\n\n**NOTE: Respite is in active development. It is not yet production-ready.**\n\nRespite is an implementation of the Redis server API on SQLite.\n\nSaid another way, Respite is an epoll TCP server that speaks the Redis protocol and uses SQLite for its backing store.\n\nJust like Redis, Respite can easily handle a huge number of clients sending commands at the same time.\n\n## Supported commands\n\nBelow are the currently supported commands. Adding support for more commands is ongoing.\n\n#### Transactions\n\n`MULTI`\n`EXEC`\n`DISCARD`\n\n#### Strings\n\n`GET`\n`SET`\n`DEL`\n`EXPIRE`\n`EXPIREAT`\n`TTL`\n`EXPIRETIME`\n`EXISTS`\n`PERSIST`\n`TYPE`\n`DECR`\n`DECRBY`\n`INCR`\n`INCRBY`\n`GETDEL`\n\n#### Hashes\n\n`HSET`\n`HSETNX`\n`HGET`\n`HINCRBY`\n`HDEL`\n`HEXISTS`\n`HGETALL`\n`HLEN`\n`HKEYS`\n\n#### Sets\n\n`SADD`\n`SCARD`\n`SISMEMBER`\n`SMEMBERS`\n`SREM`\n`SPOP`\n\n#### Sorted sets\n\n`ZADD`\n`ZREM`\n`ZCARD`\n`ZSCORE`\n`ZCOUNT`\n`ZREMRANGEBYSCORE`\n\n#### Connections\n\n`AUTH`\n`PING`\n`ECHO`\n\n## Compatibility\n\nRespite is intended to be compatibile with existing Redis clients, libraries and tools including `redis-cli` and `redis-benchmark`. This means Respite can be thought of as a drop-in alternative to Redis for many projects.\n\nWhile Respite may be a drop-in replacement, the use of SQLite does have implications that can either help or hurt depending on the specific use-case.\n\nFor use-cases where data persistence is desired (not just an in-memory cache), Respite is an excellent option:\n* Stores as much data as you have disk space for with no memory capacity limit.\n* Excellent write durability provided by SQLite.\n* Turns `MULTI`, `EXEC` into a real database transaction.\n\nFor use-cases that are essentially just an in-memory cache, Respite can still work well:\n* Good: use SQLite's in-memory database, avoiding all disk writes and clearing on restart.\n* Bad: missing support for key eviction policies and memory usage cap, etc.\n\n## Configuration\n\nCommand line configuration compatibility with Redis is a goal, within reason. So far, the following configuration options are supported:\n\n* `-h hostname`\n* `-p port`\n* `--dir my/path`\n* `--dbfilename respite.sqlite`\n* `--save \"\"` (for in-memory only)\n* `--requirepass password`\n\n## Networking\n\nBoth Respite and Redis use the same approach for networking and speak [RESP2](https://redis.io/docs/latest/develop/reference/protocol-spec/). This means you can carry over same expectations about connections and use the same clients as you would with Redis.\n\nClient connections are easy to open, can either be long-lived or transient, and you can have a lot or a little of them at any time. Concerns around connections that may be highly relevant for something like Postgres are a non-issue for Respite (and Redis itself).\n\n## Performance\n\nAs one would expect, Redis generally is able to handle more requests per second than Respite. In exchange, Respite has no memory storage limit and a better data persistence story. While more requests per second sounds great, it is not the only concern to think about.\n\nCommand: `redis-benchmark -q -c 10 -n 1000000 -r 100000 -d 64 -t get,set`\n\n### Google Cloud n2d-standard-2 VM, 2 vCPU + 8GB + balanced disk, $60/mo\n\nSeparate client and server in the same zone on same VPC.\n\nRespite in-memory only `respite-server --save \"\"`\n\n```\nSET: 31436.65 requests per second, p50=0.279 msec\nGET: 32840.72 requests per second, p50=0.263 msec\n```\n\nRedis in-memory only `redis-server --save \"\"`\n\n```\nSET: 43731.14 requests per second, p50=0.175 msec\nGET: 46834.02 requests per second, p50=0.159 msec\n```\n\nRespite `respite-server`\n\n```\nSET: 22706.63 requests per second, p50=0.359 msec\nGET: 30275.51 requests per second, p50=0.295 msec\n```\n\nRedis `redis-server --save \"\" --appendonly yes`\n\n```\nSET: 3342.47 requests per second, p50=2.919 msec      --appendfsync always\nSET: 41684.04 requests per second, p50=0.183 msec     --appendfsync everysec\nGET: 45167.12 requests per second, p50=0.167 msec\n```\n\nVery interesting results! It appears is that Redis with `--appendfsync everysec` is running face-first into the IOPS limit of GCP balanced disks, whereas SQLite appears not to. If you can sacrifice durability with `--appendfsync everysec` you avoid this sharp edge.\n\nPerformance can be hard to predict. It appears Respite using SQLite would perform far better for write-heavy workloads where risking data-loss is unacceptable.\n\n### M1 MacBook Pro (local client and server, LOW VALUE METRIC!)\n\nRespite in-memory only `respite-server --save \"\"`\n\n```\nSET: 72332.73 requests per second, p50=0.119 msec\nGET: 77447.34 requests per second, p50=0.111 msec\n```\n\nRedis in-memory only `redis-server --save \"\"`\n\n```\nSET: 121212.12 requests per second, p50=0.063 msec\nGET: 131943.53 requests per second, p50=0.055 msec\n```\n\nRespite `respite-server`\n\n```\nSET: 48206.71 requests per second, p50=0.175 msec\nGET: 56773.02 requests per second, p50=0.167 msec\n```\n\nRedis `redis-server --save \"\" --appendonly yes`\n\n```\nSET: 110399.65 requests per second, p50=0.071 msec\nGET: 125659.71 requests per second, p50=0.063 msec\n```\n\n## Building\n\nTo build Respite locally, clone the repo and run the following command from the repo base directory.\n\n`nim c -r -d:release -d:useMalloc -o:respite-server src/respite.nim`\n\nNote that this does require having [Nim](https://nim-lang.org/) installed and in your path.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguzba%2Frespite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fguzba%2Frespite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguzba%2Frespite/lists"}