feat(backend): redis key scan service - cursor pagination + cluster + CLI fix
Modeled on opsxdb's redis scan design:
- opaque base64 scan cursor {pattern,db,type,nodes,index,cursor}; server
validates search conditions match, rejects stale cursors (400)
- soft page cap 200 keys (whole scan batches returned, no key loss),
max 20 SCAN calls per page; next_cursor until all shards exhausted
- pattern rule: no glob chars -> *kw* contains match; non-glob input
also probed with TYPE for exact hit (returned as exact, slot-routed
so cluster/NAT safe)
- pipeline batch TYPE/TTL replaces per-key serial N+1; type filter now
effective server-side
- cluster: per-master direct SCAN merged across shards (MasterAddrs on
wrapper), DB0-only, MOVED errors hint at switching deploy mode;
SlowLog/ClientList aggregate across masters (were cluster-broken)
- GET /redis/:id/dbs (0-15, cluster -> [0])
- POST /redis/:id/keys/:key/field: hash row-level HSET/HDEL (no whole-
key rewrite)
- RedisExecuteCommand fixed (was always-403): accepts {db, command}
full-string, quote-aware tokenizer, whitelist on first word, expanded
read-only set
- RedisUpdateKey preserves previous TTL unless explicitly set/cleared
(was silently dropping TTL); string type skips the DEL
Verified live against local redis: 200/page no overlap across pages,
cursor 400 on condition change, exact hit, type filter, hash field
edit round-trip, CLI DBSIZE/HGET ok, SET rejected
This commit is contained in:
1 parent
6945c53879
commit
6604fdf48e
3 files changed
+521
-129
No files matched your search
@@ -93,7 +93,9 @@ func Setup(r *gin.Engine) {
|
||||
// Redis
|
||||
auth.GET("/redis/:id/info", handler.RedisInfo)
|
||||
auth.GET("/redis/:id/dbsize", handler.RedisDbsize)
|
||||
auth.GET("/redis/:id/keys", handler.RedisScanKeys)
|
||||
auth.GET("/redis/:id/dbs", handler.RedisDbs)
|
||||
auth.GET("/redis/:id/keys", handler.RedisScanKeysPaged)
|
||||
auth.POST("/redis/:id/keys/:key/field", handler.RedisUpdateKeyField)
|
||||
auth.GET("/redis/:id/keys/:key", handler.RedisGetKeyDetail)
|
||||
auth.GET("/redis/:id/slowlog", handler.RedisSlowlog)
|
||||
auth.GET("/redis/:id/clients", handler.RedisClients)
|
||||
|
||||
Reference in new issue
Block a user