Skip to content

Commit

Permalink
Merge pull request #10 from golang-acexy/future
Browse files Browse the repository at this point in the history
New Future
  • Loading branch information
acexy authored Jun 27, 2024
2 parents 16b2e2e + c4ce730 commit 46de374
Show file tree
Hide file tree
Showing 18 changed files with 348 additions and 234 deletions.
95 changes: 94 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,95 @@
# starter-redis
go framework redis module

基于`github.com/redis/go-redis`封装的集中式缓存组件

---

#### 功能说明

规范了Redis操作方法调用风格,统一RedisKey类型,统一过期时间设置,避免了全局写rediskey的问题,所有Redis操作方法只允许使用RedisKey类型作为key参数,方便集中定义

```go
type RedisKey struct {

// 最终key值的格式化格式 将使用 fmt.Sprintf(key.KeyFormat, keyAppend) 进行处理
KeyFormat string
Expire time.Duration
}
```

> 提供常用的操作方法并分类`cmdhash` `cmdkey` `cmdset` `cmdstring` `cmdothers`
```go
func TestSet(t *testing.T) {
stringType := redisstarter.StringCmd()

key1 := redisstarter.RedisKey{
KeyFormat: "string:%d:%s",
Expire: time.Second,
}
_ = stringType.Set(context.Background(), key1, "你好", 1, "2")
fmt.Println(stringType.Get(context.Background(), key1, 1, "2"))
time.Sleep(time.Second * 2)
fmt.Println(stringType.Get(context.Background(), key1, 1, "2"))
}

func TestSAdd(t *testing.T) {
key := redisstarter.RedisKey{
KeyFormat: "key-set",
}
err := setCmd.SAdd(context.Background(), key, []string{"", ""})
if err != nil {
t.Error(err)
}
fmt.Println(setCmd.SMembers(context.Background(), key))
}
```

> 依赖Redis简单的分布式锁操作
```go
func TestTryLock(t *testing.T) {
number := 0
key := random.RandString(5)
for i := 0; i < 100; i++ {
go tryLock(key, &number)
}
time.Sleep(time.Second * 5)
fmt.Println(number)
}

func tryLock(k string, i *int) {
err := redisstarter.TryLock(k, time.Minute, func() {
*i = *i + 1
fmt.Println(*i)
})
if err != nil {
fmt.Printf("%+v %s \n", err, k)
return
}
}

func lock(ctx context.Context, key string, i *int) {
err := redisstarter.LockWithDeadline(ctx, key, time.Minute, time.Now().Add(time.Minute), 200, func() {
*i = *i + 1
time.Sleep(time.Duration(random.RandRangeInt(100, 300)) * time.Millisecond)
fmt.Println(*i)
})
if err != nil {
fmt.Printf("%+v %s \n", err, key)
return
}
}
func TestLockWithDeadline(t *testing.T) {
ctx := context.Background()
deadline, cancel := context.WithDeadline(ctx, time.Now().Add(10*time.Second))
number := 0
key := random.RandString(5)
for i := 0; i < 100; i++ {
go lock(deadline, key, &number)
}
time.Sleep(time.Second * 5)
cancel()
fmt.Println(number)
}
```
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ module github.com/golang-acexy/starter-redis
go 1.20

require (
github.com/acexy/golang-toolkit v0.0.10
github.com/acexy/golang-toolkit v0.0.11
github.com/bsm/redislock v0.9.4
github.com/golang-acexy/starter-parent v0.0.6
github.com/golang-acexy/starter-parent v0.1.1
github.com/redis/go-redis/v9 v9.5.3
)

Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/acexy/golang-toolkit v0.0.10 h1:XwToFSGz0zQr6DNBWuVJlv91YihQZ5SyFa/AdKwC9mo=
github.com/acexy/golang-toolkit v0.0.10/go.mod h1:2xhHYl8xxybJx4q6/ZzcqVbRZtl0MW9ytxUdkjxJp7A=
github.com/acexy/golang-toolkit v0.0.11 h1:RxZ6rY9GSvH7JqfbSNoUd2IEBGJjJ7XWdcovFDxSmj0=
github.com/acexy/golang-toolkit v0.0.11/go.mod h1:lZn+XmM/H0Y3AQ3G4BiDwkiKbBXCgGVeTCz02ILhc0s=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/redislock v0.9.4 h1:X/Wse1DPpiQgHbVYRE9zv6m070UcKoOGekgvpNhiSvw=
Expand All @@ -11,8 +11,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/golang-acexy/starter-parent v0.0.6 h1:NtnCykpaQj1MxbIyk0FwuTrSZ1W7qWXvOJ2lNxprg60=
github.com/golang-acexy/starter-parent v0.0.6/go.mod h1:ogG+h4P2lt/opG3laeNg6Q75KFryvct0g/k9JZGPODU=
github.com/golang-acexy/starter-parent v0.1.1 h1:KSf57ItnJfXhP9WZ6Yq9nRLzVsoWr8gOA4qS4CC3wiU=
github.com/golang-acexy/starter-parent v0.1.1/go.mod h1:lp09SvT0Rsd27M0Zpd+pzKIHjspvKnczAH0TxFfmFLA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU=
Expand Down
90 changes: 0 additions & 90 deletions redismodule/redisloader.go

This file was deleted.

2 changes: 1 addition & 1 deletion redismodule/cmdhash.go → redisstarter/cmdhash.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package redismodule
package redisstarter

import (
"context"
Expand Down
2 changes: 1 addition & 1 deletion redismodule/cmdkey.go → redisstarter/cmdkey.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package redismodule
package redisstarter

import (
"context"
Expand Down
2 changes: 1 addition & 1 deletion redismodule/cmdothers.go → redisstarter/cmdothers.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package redismodule
package redisstarter

import (
"context"
Expand Down
2 changes: 1 addition & 1 deletion redismodule/cmdset.go → redisstarter/cmdset.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package redismodule
package redisstarter

import (
"context"
Expand Down
2 changes: 1 addition & 1 deletion redismodule/cmdstring.go → redisstarter/cmdstring.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package redismodule
package redisstarter

import (
"context"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package redismodule
package redisstarter

import (
"context"
Expand Down
106 changes: 106 additions & 0 deletions redisstarter/redisloader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package redisstarter

import (
"context"
"github.com/bsm/redislock"
"github.com/golang-acexy/starter-parent/parent"
"github.com/redis/go-redis/v9"
"time"
)

var redisClient redis.UniversalClient
var redisLockerClient *redislock.Client

type RedisKey struct {

// 最终key值的格式化格式 将使用 fmt.Sprintf(key.KeyFormat, keyAppend) 进行处理
KeyFormat string
Expire time.Duration
}

type RedisStarter struct {
RedisConfig redis.UniversalOptions
LazyRedisConfig func() redis.UniversalOptions

RedisSetting *parent.Setting
InitFunc func(instance redis.UniversalClient)
}

func (r *RedisStarter) Setting() *parent.Setting {
if r.RedisSetting != nil {
return r.RedisSetting
}
return parent.NewSetting("Redis-Starter", 19, true, time.Second*10, func(instance interface{}) {
if r.InitFunc != nil {
r.InitFunc(instance.(redis.UniversalClient))
}
})
}

func (r *RedisStarter) ping() error {
if redisClient == nil {
return nil
}
return redisClient.Ping(context.Background()).Err()
}
func (r *RedisStarter) closedAllConn() bool {
if redisClient == nil {
return true
}
stats := redisClient.PoolStats()
if stats.IdleConns == 0 && stats.TotalConns == 0 {
return true
}
return false
}

func (r *RedisStarter) Start() (interface{}, error) {
if r.LazyRedisConfig != nil {
r.RedisConfig = r.LazyRedisConfig()
}
redisClient = redis.NewUniversalClient(&r.RedisConfig)
if err := r.ping(); err != nil {
return nil, err
}
redisLockerClient = redislock.New(redisClient)
return redisClient, nil
}

func (r *RedisStarter) Stop(maxWaitTime time.Duration) (gracefully, stopped bool, err error) {
err = redisClient.Close()
if err != nil {
if pingErr := r.ping(); pingErr != nil {
stopped = true
}
return
}
ctx, cancelFunc := context.WithCancel(context.Background())
go func() {
for {
if r.closedAllConn() {
cancelFunc()
return
}
time.Sleep(500 * time.Millisecond)
}
}()
select {
case <-ctx.Done():
gracefully = true
stopped = r.ping() != nil
case <-time.After(maxWaitTime):
gracefully = false
stopped = r.ping() != nil
}
return
}

// RawRedisClient 获取原始RedisClient进行操作
func RawRedisClient() redis.UniversalClient {
return redisClient
}

// RawLockerClient 获取原始RedisLockerClient进行操作
func RawLockerClient() *redislock.Client {
return redisLockerClient
}
Loading

0 comments on commit 46de374

Please sign in to comment.