Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Design review on redis/rediscluster store

Open
#116 9 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
18/100
Issue type
Feature
Clarity
Needs clarification
Activity status
Stale
Tech stack
go, redis

Research direction

Start with the original feature requirements in issue #9 and the store interface in store/store.go. Review the proposed Redis operations for List, DeleteTree, locking, watching, and atomic methods, then clarify which behaviors and atomicity guarantees are required. Done means an agreed design and concrete scope for the Redis/RedisCluster store; this issue does not yet define an implementation task.

Written by the indexing model from the issue text.

Description

kind/feature kind/proposal store/meta

This is a following up discussion on the design review of redis driver.
the original feature requirements are discussed here: https://github.com/docker/libkv/issues/9
For store interface, please refer to here: https://github.com/docker/libkv/blob/master/store/store.go#L63

Redis is an in-memory key/value storage, a single thread server which supports rich data structures and lua script. It also can grant ttl(time-to-live) for each key and evict the expired keys automatically. This feature enables us to impl such functions straightforward.

Put(key string, value []byte, options *WriteOptions) error
Get(key string) (*KVPair, error)
Delete(key string) error
Exists(key string) (bool, error)

Redis also provided a scan feature which lookups all keyspace with a pattern given. It can be used to impl List and DeleteTree methods with the following file hierarchy:

set /foo bar
set /dir1/foo bar
set /dir1/dir2/foo bar

so if we call List("/"), we need to scan all keyspace and return those keys matched "/".
if we call List("/dir1/dir2"), we need to use pattern "/dir1/dir2/
" instead.
In this case, DeleteTree will be performed in two steps: 1. list the tree 2. batch delete all keys in the tree.
But that really depends how atomic we want here. If we need this operation atomaitcally, we need to move these two functions into a lua script (which will be discussed later)

For Lock implementation, redis did provide such features called "set if not exist" and "set if exist" http://redis.io/commands/set
so the one who create the key owns the lock. Release the lock actually means delete the key.
The impl can be trivial as well (for handling ttl, we just need a goroutine to refresh it's expiration time through calling set)

redisclient.Do("set", $key, $value, "NX", "EX", $ttl_in_second)
// once we hold the key, we can have a dedlicated goroutine to handle ttl
ticker := time.NewTick( ttl / 3)
for range ticker.T {
    redisclient.Do("set", $key, $value, "XX", "EX", $ttl_in_second) // update ttl only when key exist.
}

Watch API basically allows client to receive events regarding to the changes of a key (or a directory). In redis, we can borrow a keyspace notification feature(http://redis.io/topics/notifications). Since keyspace notification will deliver any events of the whole entire keyspace, client need to filter out thoese irrelevants.

func (r *Redis) WatchXXX(key string, stopCh <-chan struct{}) (<-chan *KVPair, error){
    psc := redislib.PubSubConn{client: r.client}
    psc.PSubscribe("__keyevent*__:*") // doing a pattern subscribe for all keyevent notification
    respChan :=make(chan *KVPair)
    go func(){
        for {
            // watch stopChan
            select{
                case <-stopCh:
                    // doing unsubscribe and close respChan..
                default:
            }
            switch n := psc.Receive().(type) {
                    case redis.PMessage:
                        // filter the key part and enque to respChan if found any of interest

            }
        }
    }()
    return respChan, nil
}

Script allows multiple non-blocking commands to be run without being interrupted by any coming client requests.
Here is a simple script example from stackoverflow
So that is really useful to impl DeleteTree, AtomicPut and AtomicDelete.

Feel free to modify this issue and please let me know how you think about this. thanks

Dominant language
Go
Stars
847
Forks
204
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from docker/libkv

All issues in docker/libkv

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.