modulepackage
0.0.0-20240416020153-0fa6226974d9
Repository: https://github.com/goclub/redis.git
Documentation: pkg.go.dev
# README
permalink: / sidebarBasedOnContent: true
goclub/redis
易用性
go 社区有很多 redis 库, 但是大多数库在 redis 返回 nil 时候用 error 表示.例如使用GET方法:
cmd := client.Get(ctx, "name")
err = cmd.Err()
isNil := false
if err != nil {
if errors.Is(err, redis.Nil) {
isNil = true
} else {
return err
}
}
if isNil {
// do some
} else {
log.Print(cmd.String())
}
代码写的复杂,心很累.
goclub/redis 的接口风格是
value, isNil, err := red.GET{Key:key}.Do(ctx, client) ; if err != nil {
return
}
if isNil {
// do some
} else {
log.Print(value)
}
自由
redis 的核心是 RESP 协议. goclub/redis 提供以下接口对应 RESP.
// Connecter RESP
type Connecter interface {
DoStringReply(ctx context.Context, args []string) (reply string, isNil bool, err error)
DoStringReplyWithoutNil(ctx context.Context, args []string) (reply string, err error)
DoIntegerReply(ctx context.Context, args []string) (reply int64, isNil bool, err error)
DoIntegerReplyWithoutNil(ctx context.Context, args []string) (reply int64, err error)
DoArrayIntegerReply(ctx context.Context, args []string) (reply []OptionInt64, err error)
DoArrayStringReply(ctx context.Context, args []string) (reply []OptionString, err error)
Eval(ctx context.Context, script Script) (reply Reply, isNil bool, err error)
EvalWithoutNil(ctx context.Context, script Script) (reply Reply, err error)
}
你可以自由的使用任何命令.
replyInt64, err = client.DoIntegerReplyWithoutNil(
ctx,
[]string{
"HSET", key, "name", "goclub", "age", "18",
})
if err != nil {
return
}
你也可以查看 red.API
查看 goclub/redis 对哪些方法进行了封装
像是 RESP Simple Strings
这类操作你可以根据 redis 是否会返回 nil 去调用 DoStringReply
或 DoStringReplyWithoutNil
脚本则使用 Eval
或者EvalWithoutNil
script := `
if redis.call("GET", KEYS[1]) == ARGV[1]
then
return redis.call("DEL", KEYS[1])
else
return 0
end
`
reply, err := client.EvalWithoutNil(ctx, Script{
KEYS: []string{key},
ARGV: []string{value},
Script: script,
}) ; if err != nil {
return
}
/*
你可以根据 script 内容调用一下 reply 方法
reply.Int64()
reply.Uint64()
reply.String()
reply.Int64Slice()
reply.StringSlice()
*/
包容
你可以将 goclub/redis 理解为是一个驱动库,是一个"壳". goclub/redis 能通过接口适配 go 社区的说有 redis 库.
直接来吧
实用方法
goclub/redis 还基于redis实现了了一些实用的方法,帮助开发人员提高开发效率.防止重复造轮子.
Trigger
触发器
// Trigger 触发器
// 每5分钟出现3次则触发,但是10分钟内只触发一次
func exmaple () {
triggered, err := red.Trigger{
Namespace: "pay_fail_alarm",
Interval: time.Minute*5,
Threshold: 3,
Frequency: time.Minute*5,
}.Do(ctx, client) ; if err != nil {
return
}
if triggered {
// do some
}
}
Mutex
互斥锁
mutex := red.Mutex{
Key: key,
// Expire 控制锁定时间
Expire: time.Millisecond*100,
// Retry 当锁被占用时进入循环重试(此时会堵塞)
// Retry.Times 重试上锁多少次
// Retry.Interval 重试上锁间隔
Retry: red.Retry{
Times: 3,
Interval:time.Millisecond*100,
},
}
lockSuccess, unlock, err := mutex.Lock(context.TODO(), client) ; if err != nil {
// 锁失败
return
}
if lockSuccess == false {
// 锁被占用
return
}
// 处理某些业务
err = unlock(context.TODO()) ; if err != nil {
*mutexCount--
// 解锁失败
log.Printf("%+v", err)
return
}
// 解锁成功
IncrLimiter
递增限制器
alarm_1 := IncrLimiter{
Namespace: "incr_limiter_alarm_1",
Expire: time.Second * 10,
Maximum: 3,
}
/* 第1次 */
limited, err := alarm_1.Do(ctx, client) ; if err != nil {
return
} // limited = false
/* 第2次 */
limited, err := alarm_1.Do(ctx, client) ; if err != nil {
return
} // limited = false
/* 第3次 */
limited, err := alarm_1.Do(ctx, client) ; if err != nil {
return
} // limited = false
/* 第4次 */
limited, err := alarm_1.Do(ctx, client) ; if err != nil {
return
} // limited = true
SetLimiter
设值限制器
使用场景: 限制用户每天只能试读3个章节(如果不允许一天内反复试读相同章节则可以使用 IncrLimiter )
注意:
如果 Key = free_trial:{userID} Expire = 24h 是限制24小时
如果 Key = free_trial:2022-01-01:{userID} Expire = 24h 是限制每天
/* 第1次 用户1访问了章节1 */
limited, err := SetLimiter{
Key: "free_trial:2022-05-25:userID:1",
Member: "1"
Expire: time.Hour * 24,
Maximum: 3,
}.Do(ctx, client) ; if err != nil {
return
} // limited = false
/* 第2次 用户1重复访问了章节1 */
limited, err := SetLimiter{
Key: "free_trial:2022-05-25:userID:1",
Member: "1"
Expire: time.Hour * 24,
Maximum: 3,
}.Do(ctx, client) ; if err != nil {
return
} // limited = false
/* 第3次 用户1访问了章节2 */
limited, err := SetLimiter{
Key: "free_trial:2022-05-25:userID:1",
Member: "2"
Expire: time.Hour * 24,
Maximum: 3,
}.Do(ctx, client) ; if err != nil {
return
} // limited = false
/* 第4次 用户1访问了章节3 */
limited, err := SetLimiter{
Key: "free_trial:2022-05-25:userID:1",
Member: "3"
Expire: time.Hour * 24,
Maximum: 3,
}.Do(ctx, client) ; if err != nil {
return
} // limited = false
/* 第5次 用户1访问了章节4 */
limited, err := SetLimiter{
Key: "free_trial:2022-05-25:userID:1",
Member: "4"
Expire: time.Hour * 24,
Maximum: 3,
}.Do(ctx, client) ; if err != nil {
return
} // limited = true
# Packages
No description provided by the author
# Functions
No description provided by the author
No description provided by the author
MakeKey MakeKey("user", today, "count") // "user:2022-01-01:count".
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
# Variables
No description provided by the author
# Structs
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
bit operation.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
IncrLimiter 递增限制器 eg:消息队列:重新入队:消息ID作为key在1分钟内只能递增3次.三次内返回的Limited为false,超过三次为true.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
SetLimiter 集合限制器 使用场景: 限制用户每天只能试读3个章节(如果不允许一天内反复试读相同章节则可以使用 IncrLimiter ).
No description provided by the author
No description provided by the author
Trigger 触发器 每5分钟出现3次则触发,但是10分钟内只触发一次 func exmaple () { triggered, err := Trigger{ Namespace: "pay_fail_alarm", Interval: time.Minute*5, Threshold: 3, Frequency: time.Minute*5, }.Do(ctx, client) ; if err != nil { return } if triggered { // do some } }.
No description provided by the author
# Interfaces
Connecter RESP.