mirror of
https://github.com/alibaba/higress.git
synced 2026-02-06 15:10:54 +08:00
5.7 KiB
5.7 KiB
Redis Client Reference
Initialization
type MyConfig struct {
redis wrapper.RedisClient
qpm int
}
func parseConfig(json gjson.Result, config *MyConfig) error {
serviceName := json.Get("serviceName").String()
servicePort := json.Get("servicePort").Int()
if servicePort == 0 {
servicePort = 6379
}
config.redis = wrapper.NewRedisClusterClient(wrapper.FQDNCluster{
FQDN: serviceName,
Port: servicePort,
})
return config.redis.Init(
json.Get("username").String(),
json.Get("password").String(),
json.Get("timeout").Int(), // milliseconds
// Optional settings:
// wrapper.WithDataBase(1),
// wrapper.WithBufferFlushTimeout(3*time.Millisecond),
// wrapper.WithMaxBufferSizeBeforeFlush(1024),
// wrapper.WithDisableBuffer(), // For latency-sensitive scenarios
)
}
Callback Signature
func(response resp.Value)
// Check for errors
if response.Error() != nil {
// Handle error
}
// Get values
response.Integer() // int
response.String() // string
response.Bool() // bool
response.Array() // []resp.Value
response.Bytes() // []byte
Available Commands
Key Operations
redis.Del(key, callback)
redis.Exists(key, callback)
redis.Expire(key, ttlSeconds, callback)
redis.Persist(key, callback)
String Operations
redis.Get(key, callback)
redis.Set(key, value, callback)
redis.SetEx(key, value, ttlSeconds, callback)
redis.SetNX(key, value, ttlSeconds, callback) // ttl=0 means no expiry
redis.MGet(keys, callback)
redis.MSet(kvMap, callback)
redis.Incr(key, callback)
redis.Decr(key, callback)
redis.IncrBy(key, delta, callback)
redis.DecrBy(key, delta, callback)
List Operations
redis.LLen(key, callback)
redis.RPush(key, values, callback)
redis.RPop(key, callback)
redis.LPush(key, values, callback)
redis.LPop(key, callback)
redis.LIndex(key, index, callback)
redis.LRange(key, start, stop, callback)
redis.LRem(key, count, value, callback)
redis.LInsertBefore(key, pivot, value, callback)
redis.LInsertAfter(key, pivot, value, callback)
Hash Operations
redis.HExists(key, field, callback)
redis.HDel(key, fields, callback)
redis.HLen(key, callback)
redis.HGet(key, field, callback)
redis.HSet(key, field, value, callback)
redis.HMGet(key, fields, callback)
redis.HMSet(key, kvMap, callback)
redis.HKeys(key, callback)
redis.HVals(key, callback)
redis.HGetAll(key, callback)
redis.HIncrBy(key, field, delta, callback)
redis.HIncrByFloat(key, field, delta, callback)
Set Operations
redis.SCard(key, callback)
redis.SAdd(key, values, callback)
redis.SRem(key, values, callback)
redis.SIsMember(key, value, callback)
redis.SMembers(key, callback)
redis.SDiff(key1, key2, callback)
redis.SDiffStore(dest, key1, key2, callback)
redis.SInter(key1, key2, callback)
redis.SInterStore(dest, key1, key2, callback)
redis.SUnion(key1, key2, callback)
redis.SUnionStore(dest, key1, key2, callback)
Sorted Set Operations
redis.ZCard(key, callback)
redis.ZAdd(key, memberScoreMap, callback)
redis.ZCount(key, min, max, callback)
redis.ZIncrBy(key, member, delta, callback)
redis.ZScore(key, member, callback)
redis.ZRank(key, member, callback)
redis.ZRevRank(key, member, callback)
redis.ZRem(key, members, callback)
redis.ZRange(key, start, stop, callback)
redis.ZRevRange(key, start, stop, callback)
Lua Script
redis.Eval(script, numkeys, keys, args, callback)
Raw Command
redis.Command([]interface{}{"SET", "key", "value"}, callback)
Rate Limiting Example
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
now := time.Now()
minuteAligned := now.Truncate(time.Minute)
timeStamp := strconv.FormatInt(minuteAligned.Unix(), 10)
err := config.redis.Incr(timeStamp, func(response resp.Value) {
if response.Error() != nil {
log.Errorf("redis error: %v", response.Error())
proxywasm.ResumeHttpRequest()
return
}
count := response.Integer()
ctx.SetContext("timeStamp", timeStamp)
ctx.SetContext("callTimeLeft", strconv.Itoa(config.qpm - count))
if count == 1 {
// First request in this minute, set expiry
config.redis.Expire(timeStamp, 60, func(response resp.Value) {
if response.Error() != nil {
log.Errorf("expire error: %v", response.Error())
}
proxywasm.ResumeHttpRequest()
})
} else if count > config.qpm {
proxywasm.SendHttpResponse(429, [][2]string{
{"timeStamp", timeStamp},
{"callTimeLeft", "0"},
}, []byte("Too many requests\n"), -1)
} else {
proxywasm.ResumeHttpRequest()
}
})
if err != nil {
log.Errorf("redis call failed: %v", err)
return types.HeaderContinue
}
return types.HeaderStopAllIterationAndWatermark
}
func onHttpResponseHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
if ts := ctx.GetContext("timeStamp"); ts != nil {
proxywasm.AddHttpResponseHeader("timeStamp", ts.(string))
}
if left := ctx.GetContext("callTimeLeft"); left != nil {
proxywasm.AddHttpResponseHeader("callTimeLeft", left.(string))
}
return types.HeaderContinue
}
Important Notes
- Check Ready() -
redis.Ready()returns false if init failed - Auto-reconnect - Client handles NOAUTH errors and re-authenticates automatically
- Buffering - Default 3ms flush timeout and 1024 byte buffer; use
WithDisableBuffer()for latency-sensitive scenarios - Error handling - Always check
response.Error()in callbacks