Skip to content

Commit

Permalink
feat: Add KeepTTL option
Browse files Browse the repository at this point in the history
  • Loading branch information
diiyw committed May 16, 2024
1 parent 17d95c9 commit 90fcf47
Show file tree
Hide file tree
Showing 15 changed files with 325 additions and 220 deletions.
65 changes: 41 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Nodis

![GitHub top language](https://img.shields.io/github/languages/top/diiyw/nodis) ![GitHub Release](https://img.shields.io/github/v/release/diiyw/nodis)

<div class="column" align="left">
<a href="https://godoc.org/github.com/diiyw/nodis"><img src="https://godoc.org/github.com/diiyw/nodis?status.svg" /></a>
<a href="https://goreportcard.com/report/github.com/diiyw/nodis"><img src="https://goreportcard.com/badge/github.com/diiyw/nodis" /></a>
<a href="https://codecov.io/gh/diiyw/nodis"><img src="https://codecov.io/gh/diiyw/nodis/branch/main/graph/badge.svg?token=CupujOXpbe"/></a>
</div>


English | [简体中文](https://github.com/diiyw/nodis/blob/main/README_zh-cn.md)

Nodis is a Redis implementation using the Golang programming language. This implementation provides a simple way to embed Redis functionality directly into your application or run it as a standalone server. The supported commands are compatible with the original Redis protocol, allowing you to use existing Redis clients like goredis for testing and integration.
Expand All @@ -21,6 +22,7 @@ Nodis is a Redis implementation using the Golang programming language. This impl
- Sorted Set

## Key Features

- **Fast and Embeddable**: The Golang-based implementation is designed to be fast and easily embeddable within your applications.
- **Low Memory Usage**: The system only stores hot data in memory, minimizing the overall memory footprint.
- **Snapshot and WAL for Data Storage**: This Redis implementation supports snapshot and write-ahead logging (WAL) mechanisms for reliable data storage.
Expand All @@ -30,33 +32,39 @@ Nodis is a Redis implementation using the Golang programming language. This impl
- **Redis Protocol Compatibility**: As of version 1.5.0, this Redis implementation fully supports the original Redis protocol, ensuring seamless integration with existing Redis clients.

## Supported Commands

| **Client Handling** | **Configuration** | **Key Commands** | **String Commands** | **Set Commands** | **Hash Commands** | **List Commands** | **Sorted Set Commands** |
|---------------------|-----------------|-----------------|---------------------|-----------------|-----------------|------------------|----------------|
| CLIENT | FLUSHALL | DEL | GET | SADD | HSET | LPUSH | ZADD |
| PING | FLUSHDB | EXISTS | SET | SSCAN | HGET | RPUSH | ZCARD |
| QUIT | SAVE | EXPIRE | INCR | SCARD | HDEL | LPOP | ZRANK |
| ECHO | INFO | EXPIREAT | DECR | SPOP | HLEN | RPOP | ZREVRANK |
| DBSIZE | | KEYS | SETBIT | SDIFF | HKEYS | LLEN | ZSCORE |
| MULTI | | TTL | GETBIT | SINTER | HEXISTS | LINDEX | ZINCRBY |
| DISCARD | | RENAME | INCR | SISMEMBER | HGETALL | LINSERT | ZRANGE |
| EXEC | | TYPE | DESR | SMEMBERS | HINCRBY | LPUSHX | ZREVRANGE |
| | | SCAN | SETEX | SREM | HICRBYFLOAT | RPUSHX | ZRANGEBYSCORE |
| | | RANDOMKEY | INCRBY | SMOVE | HSETNX | LREM | ZREVRANGEBYSCORE |
| | | RENAMEEX | DECRBY | SRANDMEMBER | HMGET | LSET | ZREM |
| | | PERSIST | SETNX | SINTERSTORE | HMSET | LRANGE | ZREMRANGEBYRANK |
| | | | INCRBYFLOAT | SUNIONSTORE | HCLEAR | LPOPRPUSH | ZREMRANGEBYSCORE |
| | | | APPEND | | HSCAN | RPOPLPUSH | ZCLEAR |
| | | | GETRANGE | | HVALS | BLPOP | ZEXISTS |
| | | | STRLEN | | HSTRLEN | BRPOP | ZUNIONSTORE |
| | | | SETRANGE | | | | ZINTERSTORE |
| ------------------- | ----------------- | ---------------- | ------------------- | ---------------- | ----------------- | ----------------- | ----------------------- |
| CLIENT | FLUSHALL | DEL | GET | SADD | HSET | LPUSH | ZADD |
| PING | FLUSHDB | EXISTS | SET | SSCAN | HGET | RPUSH | ZCARD |
| QUIT | SAVE | EXPIRE | INCR | SCARD | HDEL | LPOP | ZRANK |
| ECHO | INFO | EXPIREAT | DECR | SPOP | HLEN | RPOP | ZREVRANK |
| DBSIZE | | KEYS | SETBIT | SDIFF | HKEYS | LLEN | ZSCORE |
| MULTI | | TTL | GETBIT | SINTER | HEXISTS | LINDEX | ZINCRBY |
| DISCARD | | RENAME | INCR | SISMEMBER | HGETALL | LINSERT | ZRANGE |
| EXEC | | TYPE | DESR | SMEMBERS | HINCRBY | LPUSHX | ZREVRANGE |
| | | SCAN | SETEX | SREM | HICRBYFLOAT | RPUSHX | ZRANGEBYSCORE |
| | | RANDOMKEY | INCRBY | SMOVE | HSETNX | LREM | ZREVRANGEBYSCORE |
| | | RENAMEEX | DECRBY | SRANDMEMBER | HMGET | LSET | ZREM |
| | | PERSIST | SETNX | SINTERSTORE | HMSET | LRANGE | ZREMRANGEBYRANK |
| | | PTTL | INCRBYFLOAT | SUNIONSTORE | HCLEAR | LPOPRPUSH | ZREMRANGEBYSCORE |
| | | | APPEND | | HSCAN | RPOPLPUSH | ZCLEAR |
| | | | GETRANGE | | HVALS | BLPOP | ZEXISTS |
| | | | STRLEN | | HSTRLEN | BRPOP | ZUNIONSTORE |
| | | | SETRANGE | | | | ZINTERSTORE |

## Get Started

```bash
go get github.com/diiyw/nodis@latest
```

Or use test version

```bash
go get github.com/diiyw/nodis@main
```

```go
package main

Expand All @@ -68,16 +76,18 @@ func main() {
n := nodis.Open(opt)
defer n.Close()
// Set a key-value pair
n.Set("key", []byte("value"))
n.Set("key", []byte("value"),false)
n.LPush("list", []byte("value1"))
}
```

## Examples

<details>
<summary> Watch changes</summary>

Server:
Server:

```go
package main

Expand Down Expand Up @@ -108,11 +118,13 @@ func main() {
}
}
```

- Browser client built with WebAssembly

```bash
GOOS=js GOARCH=wasm go build -o test.wasm
```

```go
package main

Expand All @@ -139,11 +151,12 @@ func main() {
select {}
}
```

</details>
<details>
<summary> Simple Redis Server</summary>

```go
```go
package main

import (
Expand All @@ -161,6 +174,7 @@ func main() {
}
}
```

You can use redis-cli to connect to the server.

```bash
Expand All @@ -171,6 +185,7 @@ redis-cli -p 6380
</details>

## Benchmark

<details>
<summary>Embed benchmark</summary>

Expand All @@ -197,7 +212,7 @@ Linux VM: 4C/8GB
```bash
goos: linux
goarch: amd64
pkg: github.com/diiyw/nodis/bench
pkg: github.com/diiyw/nodis/bench
BenchmarkSet-4 806912 1658 ns/op 543 B/op 7 allocs/op
BenchmarkGet-4 5941904 190.6 ns/op 7 B/op 0 allocs/op
BenchmarkLPush-4 852932 1757 ns/op 615 B/op 9 allocs/op
Expand All @@ -215,7 +230,7 @@ BenchmarkHGet-4 4442625 243.4 ns/op 7 B/op 0 allocs
<summary>Redis benchmark tool</summary>

```bash
redis-benchmark -p 6380 -t set,get,lpush,lpop,sadd,smembers,zadd,zrank,hset,hget -n 100000 -q
redis-benchmark -p 6380 -t set,get,lpush,lpop,sadd,smembers,zadd,zrank,hset,hget -n 100000 -q
```

```
Expand All @@ -226,7 +241,9 @@ LPOP: 92165.90 requests per second
SADD: 91911.76 requests per second
HSET: 93023.25 requests per second
```

</details>

## Note

If you want to persist data, please make sure to call the `Close()` method when your application exits.
64 changes: 40 additions & 24 deletions README_zh-cn.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,70 @@
# Nodis

![GitHub top language](https://img.shields.io/github/languages/top/diiyw/nodis) ![GitHub Release](https://img.shields.io/github/v/release/diiyw/nodis)

<div class="column" align="left">
<a href="https://godoc.org/github.com/diiyw/nodis"><img src="https://godoc.org/github.com/diiyw/nodis?status.svg" /></a>
<a href="https://goreportcard.com/report/github.com/diiyw/nodis"><img src="https://goreportcard.com/badge/github.com/diiyw/nodis" /></a>
<a href="https://codecov.io/gh/diiyw/nodis"><img src="https://codecov.io/gh/diiyw/nodis/branch/main/graph/badge.svg?token=CupujOXpbe"/></a>
</div>


English | [简体中文](https://github.com/diiyw/nodis/blob/main/README_zh-cn.md)

Nodis 是一个使用 Golang 编程语言实现的 Redis。这个实现提供了一种将 Redis 功能直接嵌入到应用程序中或作为独立服务器运行的简单方法。支持的命令与原始 Redis 协议兼容,允许您使用现有的 Redis 客户端(如 goredis)进行测试和集成。

## 支持的数据类型

Bitmap
String
List
Hash
Set
Sorted Set

## 主要特性

- **快速和可嵌入**: Golang 实现的设计目标是快速和易于嵌入到您的应用程序中。
- **低内存使用**: 该系统只在内存中存储热数据,将整体内存占用降到最低。
- **快照和 WAL 用于数据存储**: 这个 Redis 实现支持快照和预写日志(WAL)机制,用于可靠的数据存储。
- **自定义数据存储后端**: 您可以集成自定义的数据存储后端,如 Amazon S3、浏览器存储等。
使用 WebAssembly 支持浏览器: 从 1.2.0 版本开始,这个 Redis 实现可以直接在浏览器中使用 WebAssembly 运行。
使用 WebAssembly 支持浏览器: 从 1.2.0 版本开始,这个 Redis 实现可以直接在浏览器中使用 WebAssembly 运行。
- **远程变更监控**: 从 1.2.0 版本开始,该系统支持监视来自远程源的变更。
- **Redis 协议兼容性**: 从 1.5.0 版本开始,这个 Redis 实现完全支持原始的 Redis 协议,确保与现有的 Redis 客户端无缝集成。

## 支持的Redis命令
## 支持的 Redis 命令

| **Client Handling** | **Configuration** | **Key Commands** | **String Commands** | **Set Commands** | **Hash Commands** | **List Commands** | **Sorted Set Commands** |
|---------------------|-----------------|-----------------|---------------------|-----------------|-----------------|------------------|----------------|
| CLIENT | FLUSHALL | DEL | GET | SADD | HSET | LPUSH | ZADD |
| PING | FLUSHDB | EXISTS | SET | SSCAN | HGET | RPUSH | ZCARD |
| QUIT | SAVE | EXPIRE | INCR | SCARD | HDEL | LPOP | ZRANK |
| ECHO | INFO | EXPIREAT | DECR | SPOP | HLEN | RPOP | ZREVRANK |
| DBSIZE | | KEYS | SETBIT | SDIFF | HKEYS | LLEN | ZSCORE |
| MULTI | | TTL | GETBIT | SINTER | HEXISTS | LINDEX | ZINCRBY |
| DISCARD | | RENAME | INCR | SISMEMBER | HGETALL | LINSERT | ZRANGE |
| EXEC | | TYPE | DESR | SMEMBERS | HINCRBY | LPUSHX | ZREVRANGE |
| | | SCAN | SETEX | SREM | HICRBYFLOAT | RPUSHX | ZRANGEBYSCORE |
| | | RANDOMKEY | INCRBY | SMOVE | HSETNX | LREM | ZREVRANGEBYSCORE |
| | | RENAMEEX | DECRBY | SRANDMEMBER | HMGET | LSET | ZREM |
| | | PERSIST | SETNX | SINTERSTORE | HMSET | LRANGE | ZREMRANGEBYRANK |
| | | | INCRBYFLOAT | SUNIONSTORE | HCLEAR | LPOPRPUSH | ZREMRANGEBYSCORE |
| | | | APPEND | | HSCAN | RPOPLPUSH | ZCLEAR |
| | | | GETRANGE | | HVALS | BLPOP | ZEXISTS |
| | | | STRLEN | | HSTRLEN | BRPOP | ZUNIONSTORE |
| | | | SETRANGE | | | | ZINTERSTORE |
| ------------------- | ----------------- | ---------------- | ------------------- | ---------------- | ----------------- | ----------------- | ----------------------- |
| CLIENT | FLUSHALL | DEL | GET | SADD | HSET | LPUSH | ZADD |
| PING | FLUSHDB | EXISTS | SET | SSCAN | HGET | RPUSH | ZCARD |
| QUIT | SAVE | EXPIRE | INCR | SCARD | HDEL | LPOP | ZRANK |
| ECHO | INFO | EXPIREAT | DECR | SPOP | HLEN | RPOP | ZREVRANK |
| DBSIZE | | KEYS | SETBIT | SDIFF | HKEYS | LLEN | ZSCORE |
| MULTI | | TTL | GETBIT | SINTER | HEXISTS | LINDEX | ZINCRBY |
| DISCARD | | RENAME | INCR | SISMEMBER | HGETALL | LINSERT | ZRANGE |
| EXEC | | TYPE | DESR | SMEMBERS | HINCRBY | LPUSHX | ZREVRANGE |
| | | SCAN | SETEX | SREM | HICRBYFLOAT | RPUSHX | ZRANGEBYSCORE |
| | | RANDOMKEY | INCRBY | SMOVE | HSETNX | LREM | ZREVRANGEBYSCORE |
| | | RENAMEEX | DECRBY | SRANDMEMBER | HMGET | LSET | ZREM |
| | | PERSIST | SETNX | SINTERSTORE | HMSET | LRANGE | ZREMRANGEBYRANK |
| | | | INCRBYFLOAT | SUNIONSTORE | HCLEAR | LPOPRPUSH | ZREMRANGEBYSCORE |
| | | | APPEND | | HSCAN | RPOPLPUSH | ZCLEAR |
| | | | GETRANGE | | HVALS | BLPOP | ZEXISTS |
| | | | STRLEN | | HSTRLEN | BRPOP | ZUNIONSTORE |
| | | | SETRANGE | | | | ZINTERSTORE |

## Get Started

```bash
go get github.com/diiyw/[email protected]
```

Or use test version

```bash
go get github.com/diiyw/nodis@main
```

```go
package main

Expand All @@ -66,16 +76,18 @@ func main() {
n := nodis.Open(opt)
defer n.Close()
// Set a key-value pair
n.Set("key", []byte("value"))
n.Set("key", []byte("value"), false)
n.LPush("list", []byte("value1"))
}
```

## Examples

<details>
<summary> Watch changes</summary>

Server:
Server:

```go
package main

Expand Down Expand Up @@ -106,11 +118,13 @@ func main() {
}
}
```

- Browser client built with WebAssembly

```bash
GOOS=js GOARCH=wasm go build -o test.wasm
```

```go
package main

Expand All @@ -137,9 +151,11 @@ func main() {
select {}
}
```

</details>

## Benchmark

<details>
<summary>Embed benchmark</summary>
Windows 11: 12C/32G
Expand All @@ -165,7 +181,7 @@ Linux VM: 4C/8GB
```bash
goos: linux
goarch: amd64
pkg: github.com/diiyw/nodis/bench
pkg: github.com/diiyw/nodis/bench
BenchmarkSet-4 806912 1658 ns/op 543 B/op 7 allocs/op
BenchmarkGet-4 5941904 190.6 ns/op 7 B/op 0 allocs/op
BenchmarkLPush-4 852932 1757 ns/op 615 B/op 9 allocs/op
Expand Down
4 changes: 2 additions & 2 deletions bench/nodis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func BenchmarkSet(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
id := strconv.Itoa(i)
n.Set(id, []byte("value"+id))
n.Set(id, []byte("value"+id), false)
}
}

Expand All @@ -27,7 +27,7 @@ func BenchmarkGet(b *testing.B) {
})
for i := 0; i < 100000; i++ {
id := strconv.Itoa(i)
n.Set(id, []byte("value"+id))
n.Set(id, []byte("value"+id), false)
}
b.ResetTimer()
b.ReportAllocs()
Expand Down
2 changes: 1 addition & 1 deletion examples/hello/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ func main() {
n := nodis.Open(opt)
defer n.Close()
// Set a key-value pair
n.Set("echo", []byte("hello world"))
n.Set("echo", []byte("hello world"), false)
fmt.Println("Set key-value pair: ", string(n.Get("echo")))
}
Loading

0 comments on commit 90fcf47

Please sign in to comment.