mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
Merge pull request #2676 from banjiaojuhao/add_filer_store-redis_lua
FilerStore: add redis_lua
This commit is contained in:
commit
aa7fc299b8
|
@ -195,6 +195,40 @@ routeByLatency = false
|
||||||
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
|
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
|
||||||
superLargeDirectories = []
|
superLargeDirectories = []
|
||||||
|
|
||||||
|
[redis_lua]
|
||||||
|
enabled = false
|
||||||
|
address = "localhost:6379"
|
||||||
|
password = ""
|
||||||
|
database = 0
|
||||||
|
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
|
||||||
|
superLargeDirectories = []
|
||||||
|
|
||||||
|
[redis_lua_sentinel]
|
||||||
|
enabled = false
|
||||||
|
addresses = ["172.22.12.7:26379","172.22.12.8:26379","172.22.12.9:26379"]
|
||||||
|
masterName = "master"
|
||||||
|
username = ""
|
||||||
|
password = ""
|
||||||
|
database = 0
|
||||||
|
|
||||||
|
[redis_lua_cluster]
|
||||||
|
enabled = false
|
||||||
|
addresses = [
|
||||||
|
"localhost:30001",
|
||||||
|
"localhost:30002",
|
||||||
|
"localhost:30003",
|
||||||
|
"localhost:30004",
|
||||||
|
"localhost:30005",
|
||||||
|
"localhost:30006",
|
||||||
|
]
|
||||||
|
password = ""
|
||||||
|
# allows reads from slave servers or the master, but all writes still go to the master
|
||||||
|
readOnly = false
|
||||||
|
# automatically use the closest Redis server for reads
|
||||||
|
routeByLatency = false
|
||||||
|
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
|
||||||
|
superLargeDirectories = []
|
||||||
|
|
||||||
[redis3] # beta
|
[redis3] # beta
|
||||||
enabled = false
|
enabled = false
|
||||||
address = "localhost:6379"
|
address = "localhost:6379"
|
||||||
|
|
44
weed/filer/redis_lua/redis_cluster_store.go
Normal file
44
weed/filer/redis_lua/redis_cluster_store.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package redis_lua
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/filer"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/util"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
filer.Stores = append(filer.Stores, &RedisLuaClusterStore{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisLuaClusterStore struct {
|
||||||
|
UniversalRedisLuaStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *RedisLuaClusterStore) GetName() string {
|
||||||
|
return "redis_lua_cluster"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *RedisLuaClusterStore) Initialize(configuration util.Configuration, prefix string) (err error) {
|
||||||
|
|
||||||
|
configuration.SetDefault(prefix+"useReadOnly", false)
|
||||||
|
configuration.SetDefault(prefix+"routeByLatency", false)
|
||||||
|
|
||||||
|
return store.initialize(
|
||||||
|
configuration.GetStringSlice(prefix+"addresses"),
|
||||||
|
configuration.GetString(prefix+"password"),
|
||||||
|
configuration.GetBool(prefix+"useReadOnly"),
|
||||||
|
configuration.GetBool(prefix+"routeByLatency"),
|
||||||
|
configuration.GetStringSlice(prefix+"superLargeDirectories"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *RedisLuaClusterStore) initialize(addresses []string, password string, readOnly, routeByLatency bool, superLargeDirectories []string) (err error) {
|
||||||
|
store.Client = redis.NewClusterClient(&redis.ClusterOptions{
|
||||||
|
Addrs: addresses,
|
||||||
|
Password: password,
|
||||||
|
ReadOnly: readOnly,
|
||||||
|
RouteByLatency: routeByLatency,
|
||||||
|
})
|
||||||
|
store.loadSuperLargeDirectories(superLargeDirectories)
|
||||||
|
return
|
||||||
|
}
|
45
weed/filer/redis_lua/redis_sentinel_store.go
Normal file
45
weed/filer/redis_lua/redis_sentinel_store.go
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
package redis_lua
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/filer"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/util"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
filer.Stores = append(filer.Stores, &RedisLuaSentinelStore{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisLuaSentinelStore struct {
|
||||||
|
UniversalRedisLuaStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *RedisLuaSentinelStore) GetName() string {
|
||||||
|
return "redis_lua_sentinel"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *RedisLuaSentinelStore) Initialize(configuration util.Configuration, prefix string) (err error) {
|
||||||
|
return store.initialize(
|
||||||
|
configuration.GetStringSlice(prefix+"addresses"),
|
||||||
|
configuration.GetString(prefix+"masterName"),
|
||||||
|
configuration.GetString(prefix+"username"),
|
||||||
|
configuration.GetString(prefix+"password"),
|
||||||
|
configuration.GetInt(prefix+"database"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *RedisLuaSentinelStore) initialize(addresses []string, masterName string, username string, password string, database int) (err error) {
|
||||||
|
store.Client = redis.NewFailoverClient(&redis.FailoverOptions{
|
||||||
|
MasterName: masterName,
|
||||||
|
SentinelAddrs: addresses,
|
||||||
|
Username: username,
|
||||||
|
Password: password,
|
||||||
|
DB: database,
|
||||||
|
MinRetryBackoff: time.Millisecond * 100,
|
||||||
|
MaxRetryBackoff: time.Minute * 1,
|
||||||
|
ReadTimeout: time.Second * 30,
|
||||||
|
WriteTimeout: time.Second * 5,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
38
weed/filer/redis_lua/redis_store.go
Normal file
38
weed/filer/redis_lua/redis_store.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package redis_lua
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/filer"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/util"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
filer.Stores = append(filer.Stores, &RedisLuaStore{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisLuaStore struct {
|
||||||
|
UniversalRedisLuaStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *RedisLuaStore) GetName() string {
|
||||||
|
return "redis_lua"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *RedisLuaStore) Initialize(configuration util.Configuration, prefix string) (err error) {
|
||||||
|
return store.initialize(
|
||||||
|
configuration.GetString(prefix+"address"),
|
||||||
|
configuration.GetString(prefix+"password"),
|
||||||
|
configuration.GetInt(prefix+"database"),
|
||||||
|
configuration.GetStringSlice(prefix+"superLargeDirectories"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *RedisLuaStore) initialize(hostPort string, password string, database int, superLargeDirectories []string) (err error) {
|
||||||
|
store.Client = redis.NewClient(&redis.Options{
|
||||||
|
Addr: hostPort,
|
||||||
|
Password: password,
|
||||||
|
DB: database,
|
||||||
|
})
|
||||||
|
store.loadSuperLargeDirectories(superLargeDirectories)
|
||||||
|
return
|
||||||
|
}
|
19
weed/filer/redis_lua/stored_procedure/delete_entry.lua
Normal file
19
weed/filer/redis_lua/stored_procedure/delete_entry.lua
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
-- KEYS[1]: full path of entry
|
||||||
|
local fullpath = KEYS[1]
|
||||||
|
-- KEYS[2]: full path of entry
|
||||||
|
local fullpath_list_key = KEYS[2]
|
||||||
|
-- KEYS[3]: dir of the entry
|
||||||
|
local dir_list_key = KEYS[3]
|
||||||
|
|
||||||
|
-- ARGV[1]: isSuperLargeDirectory
|
||||||
|
local isSuperLargeDirectory = ARGV[1] == "1"
|
||||||
|
-- ARGV[2]: name of the entry
|
||||||
|
local name = ARGV[2]
|
||||||
|
|
||||||
|
redis.call("DEL", fullpath, fullpath_list_key)
|
||||||
|
|
||||||
|
if not isSuperLargeDirectory and name ~= "" then
|
||||||
|
redis.call("ZREM", dir_list_key, name)
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
|
@ -0,0 +1,15 @@
|
||||||
|
-- KEYS[1]: full path of entry
|
||||||
|
local fullpath = KEYS[1]
|
||||||
|
|
||||||
|
if fullpath ~= "" and string.sub(fullpath, -1) == "/" then
|
||||||
|
fullpath = string.sub(fullpath, 0, -2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local files = redis.call("ZRANGE", fullpath .. "\0", "0", "-1")
|
||||||
|
|
||||||
|
for _, name in ipairs(files) do
|
||||||
|
local file_path = fullpath .. "/" .. name
|
||||||
|
redis.call("DEL", file_path, file_path .. "\0")
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
24
weed/filer/redis_lua/stored_procedure/init.go
Normal file
24
weed/filer/redis_lua/stored_procedure/init.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package stored_procedure
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
InsertEntryScript = redis.NewScript(insertEntry)
|
||||||
|
DeleteEntryScript = redis.NewScript(deleteEntry)
|
||||||
|
DeleteFolderChildrenScript = redis.NewScript(deleteFolderChildren)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:embed insert_entry.lua
|
||||||
|
var insertEntry string
|
||||||
|
var InsertEntryScript *redis.Script
|
||||||
|
|
||||||
|
//go:embed delete_entry.lua
|
||||||
|
var deleteEntry string
|
||||||
|
var DeleteEntryScript *redis.Script
|
||||||
|
|
||||||
|
//go:embed delete_folder_children.lua
|
||||||
|
var deleteFolderChildren string
|
||||||
|
var DeleteFolderChildrenScript *redis.Script
|
27
weed/filer/redis_lua/stored_procedure/insert_entry.lua
Normal file
27
weed/filer/redis_lua/stored_procedure/insert_entry.lua
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
-- KEYS[1]: full path of entry
|
||||||
|
local full_path = KEYS[1]
|
||||||
|
-- KEYS[2]: dir of the entry
|
||||||
|
local dir_list_key = KEYS[2]
|
||||||
|
|
||||||
|
-- ARGV[1]: content of the entry
|
||||||
|
local entry = ARGV[1]
|
||||||
|
-- ARGV[2]: TTL of the entry
|
||||||
|
local ttlSec = tonumber(ARGV[2])
|
||||||
|
-- ARGV[3]: isSuperLargeDirectory
|
||||||
|
local isSuperLargeDirectory = ARGV[3] == "1"
|
||||||
|
-- ARGV[4]: zscore of the entry in zset
|
||||||
|
local zscore = tonumber(ARGV[4])
|
||||||
|
-- ARGV[5]: name of the entry
|
||||||
|
local name = ARGV[5]
|
||||||
|
|
||||||
|
if ttlSec > 0 then
|
||||||
|
redis.call("SET", full_path, entry, "EX", ttlSec)
|
||||||
|
else
|
||||||
|
redis.call("SET", full_path, entry)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not isSuperLargeDirectory and name ~= "" then
|
||||||
|
redis.call("ZADD", dir_list_key, "NX", zscore, name)
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
191
weed/filer/redis_lua/universal_redis_store.go
Normal file
191
weed/filer/redis_lua/universal_redis_store.go
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
package redis_lua
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/filer"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/filer/redis_lua/stored_procedure"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/glog"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DIR_LIST_MARKER = "\x00"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UniversalRedisLuaStore struct {
|
||||||
|
Client redis.UniversalClient
|
||||||
|
superLargeDirectoryHash map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) isSuperLargeDirectory(dir string) (isSuperLargeDirectory bool) {
|
||||||
|
_, isSuperLargeDirectory = store.superLargeDirectoryHash[dir]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) loadSuperLargeDirectories(superLargeDirectories []string) {
|
||||||
|
// set directory hash
|
||||||
|
store.superLargeDirectoryHash = make(map[string]bool)
|
||||||
|
for _, dir := range superLargeDirectories {
|
||||||
|
store.superLargeDirectoryHash[dir] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) BeginTransaction(ctx context.Context) (context.Context, error) {
|
||||||
|
return ctx, nil
|
||||||
|
}
|
||||||
|
func (store *UniversalRedisLuaStore) CommitTransaction(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (store *UniversalRedisLuaStore) RollbackTransaction(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) InsertEntry(ctx context.Context, entry *filer.Entry) (err error) {
|
||||||
|
|
||||||
|
value, err := entry.EncodeAttributesAndChunks()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("encoding %s %+v: %v", entry.FullPath, entry.Attr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(entry.Chunks) > 50 {
|
||||||
|
value = util.MaybeGzipData(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
dir, name := entry.FullPath.DirAndName()
|
||||||
|
|
||||||
|
err = stored_procedure.InsertEntryScript.Run(ctx, store.Client,
|
||||||
|
[]string{string(entry.FullPath), genDirectoryListKey(dir)},
|
||||||
|
value, entry.TtlSec,
|
||||||
|
store.isSuperLargeDirectory(dir), 0, name).Err()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("persisting %s : %v", entry.FullPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) UpdateEntry(ctx context.Context, entry *filer.Entry) (err error) {
|
||||||
|
|
||||||
|
return store.InsertEntry(ctx, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) FindEntry(ctx context.Context, fullpath util.FullPath) (entry *filer.Entry, err error) {
|
||||||
|
|
||||||
|
data, err := store.Client.Get(ctx, string(fullpath)).Result()
|
||||||
|
if err == redis.Nil {
|
||||||
|
return nil, filer_pb.ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get %s : %v", fullpath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = &filer.Entry{
|
||||||
|
FullPath: fullpath,
|
||||||
|
}
|
||||||
|
err = entry.DecodeAttributesAndChunks(util.MaybeDecompressData([]byte(data)))
|
||||||
|
if err != nil {
|
||||||
|
return entry, fmt.Errorf("decode %s : %v", entry.FullPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) DeleteEntry(ctx context.Context, fullpath util.FullPath) (err error) {
|
||||||
|
|
||||||
|
dir, name := fullpath.DirAndName()
|
||||||
|
|
||||||
|
err = stored_procedure.DeleteEntryScript.Run(ctx, store.Client,
|
||||||
|
[]string{string(fullpath), genDirectoryListKey(string(fullpath)), genDirectoryListKey(dir)},
|
||||||
|
store.isSuperLargeDirectory(dir), name).Err()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("DeleteEntry %s : %v", fullpath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) DeleteFolderChildren(ctx context.Context, fullpath util.FullPath) (err error) {
|
||||||
|
|
||||||
|
if store.isSuperLargeDirectory(string(fullpath)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = stored_procedure.DeleteFolderChildrenScript.Run(ctx, store.Client,
|
||||||
|
[]string{string(fullpath)}).Err()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("DeleteFolderChildren %s : %v", fullpath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) ListDirectoryPrefixedEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int64, prefix string, eachEntryFunc filer.ListEachEntryFunc) (lastFileName string, err error) {
|
||||||
|
return lastFileName, filer.ErrUnsupportedListDirectoryPrefixed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) ListDirectoryEntries(ctx context.Context, dirPath util.FullPath, startFileName string, includeStartFile bool, limit int64, eachEntryFunc filer.ListEachEntryFunc) (lastFileName string, err error) {
|
||||||
|
|
||||||
|
dirListKey := genDirectoryListKey(string(dirPath))
|
||||||
|
|
||||||
|
min := "-"
|
||||||
|
if startFileName != "" {
|
||||||
|
if includeStartFile {
|
||||||
|
min = "[" + startFileName
|
||||||
|
} else {
|
||||||
|
min = "(" + startFileName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
members, err := store.Client.ZRangeByLex(ctx, dirListKey, &redis.ZRangeBy{
|
||||||
|
Min: min,
|
||||||
|
Max: "+",
|
||||||
|
Offset: 0,
|
||||||
|
Count: limit,
|
||||||
|
}).Result()
|
||||||
|
if err != nil {
|
||||||
|
return lastFileName, fmt.Errorf("list %s : %v", dirPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch entry meta
|
||||||
|
for _, fileName := range members {
|
||||||
|
path := util.NewFullPath(string(dirPath), fileName)
|
||||||
|
entry, err := store.FindEntry(ctx, path)
|
||||||
|
lastFileName = fileName
|
||||||
|
if err != nil {
|
||||||
|
glog.V(0).Infof("list %s : %v", path, err)
|
||||||
|
if err == filer_pb.ErrNotFound {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if entry.TtlSec > 0 {
|
||||||
|
if entry.Attr.Crtime.Add(time.Duration(entry.TtlSec) * time.Second).Before(time.Now()) {
|
||||||
|
store.DeleteEntry(ctx, path)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !eachEntryFunc(entry) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastFileName, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func genDirectoryListKey(dir string) (dirList string) {
|
||||||
|
return dir + DIR_LIST_MARKER
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) Shutdown() {
|
||||||
|
store.Client.Close()
|
||||||
|
}
|
42
weed/filer/redis_lua/universal_redis_store_kv.go
Normal file
42
weed/filer/redis_lua/universal_redis_store_kv.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package redis_lua
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/filer"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) KvPut(ctx context.Context, key []byte, value []byte) (err error) {
|
||||||
|
|
||||||
|
_, err = store.Client.Set(ctx, string(key), value, 0).Result()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("kv put: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) KvGet(ctx context.Context, key []byte) (value []byte, err error) {
|
||||||
|
|
||||||
|
data, err := store.Client.Get(ctx, string(key)).Result()
|
||||||
|
|
||||||
|
if err == redis.Nil {
|
||||||
|
return nil, filer.ErrKvNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(data), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (store *UniversalRedisLuaStore) KvDelete(ctx context.Context, key []byte) (err error) {
|
||||||
|
|
||||||
|
_, err = store.Client.Del(ctx, string(key)).Result()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("kv delete: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue