Design review on redis/rediscluster store
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 18/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Da chiarire
- Stato di attività
- Ferma
- Stack tecnologico
- go, redis
- Ambito
- backend, databases, distributed-systems
Direzione di ricerca
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.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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
- Lingua principale
- Go
- Stelle
- 848
- Fork
- 204
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di docker/libkv
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 15/100
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 25/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 45/100
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 28/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 45/100
Tutte le issue di docker/libkv
Issue simili
-
Difficoltà 1/5 1-3 ore Idoneità per principianti 90/100
FootprintAI/Containarium#2338 ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug]: core doesn't build standalone on dev since a17068054 (go-mp3 require dropped, go.sum pruned)Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
SagerNet/sing-openvpn#11 ·
-
priority: P3 type: devops
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
jiegui2025/hwspec#57 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
columnar-tech/dbc#513 ·
I maintainer di solito rispondono entro 1 giorno