-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from golang-acexy/future
New Future
- Loading branch information
Showing
18 changed files
with
348 additions
and
234 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package redismodule | ||
package redisstarter | ||
|
||
import ( | ||
"context" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package redismodule | ||
package redisstarter | ||
|
||
import ( | ||
"context" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package redismodule | ||
package redisstarter | ||
|
||
import ( | ||
"context" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package redismodule | ||
package redisstarter | ||
|
||
import ( | ||
"context" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package redismodule | ||
package redisstarter | ||
|
||
import ( | ||
"context" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package redismodule | ||
package redisstarter | ||
|
||
import ( | ||
"context" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.