Design review on redis/rediscluster store
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
- Domain
- backend, databases, distributed-systems
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
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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from docker/libkv
-
Difficulty 5/5 Over a week Newbie friendliness 15/100
-
Difficulty 3/5 1-2 days Newbie friendliness 25/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 45/100
-
Difficulty 4/5 3-5 days Newbie friendliness 28/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 45/100
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
-
Bob Shell support Openenhancement
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
santhosh-tekuri/jsonschema#276 ·