一,安装go-redis
1,从命令行执行:
liuhongdi@ku:~$ go get -u github.com/go-redis/redis/v8
说明:安装命令及版本等信息可以从github站直接得到
说明:刘宏缔的go森林是一个专注golang的博客,
地址:https://blog.csdn.net/weixin_43881017
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,演示项目的相关信息
1,地址:
https://github.com/liuhongdi/digv17
2,功能:演示通过go-redis库+lua实现一个顺序自增的id发号器
通常用在文件存储的目录计算等方面
3,项目结构:如图:
三,go代码说明
1,global/redisDb.go
-
package global
-
-
import (
-
"context"
-
"github.com/go-redis/redis/v8"
-
)
-
-
var (
-
RedisDb *redis.Client
-
)
-
-
//创建redis链接
-
func SetupRedisDb() (error) {
-
var ctx = context.Background()
-
RedisDb = redis.NewClient(&redis.Options{
-
Addr: RedisSetting.Addr,
-
Password: RedisSetting.Password, // no password set
-
DB: 0, // use default DB
-
})
-
-
_, err := RedisDb.Ping(ctx).Result()
-
if err != nil {
-
return err
-
}
-
return nil
-
-
}
2,controller/idController.go
-
package controller
-
-
import (
-
"fmt"
-
"github.com/gin-gonic/gin"
-
"github.com/liuhongdi/digv17/pkg/result"
-
"github.com/liuhongdi/digv17/service"
-
)
-
-
type IdController struct{}
-
-
func NewIdController() IdController {
-
return IdController{}
-
}
-
//得到一个id
-
func (a *IdController) GetOne(c *gin.Context) {
-
resultRes := result.NewResult(c)
-
idType := "logId"
-
idOne,err := service.GetOneId(idType);
-
if err != nil {
-
resultRes.Error(404,"数据查询错误")
-
} else {
-
fmt.Println(idOne)
-
resultRes.Success(&idOne);
-
}
-
return
-
}
3,service/id.go
-
package service
-
-
import (
-
"github.com/liuhongdi/digv17/cache"
-
)
-
-
//得到一个id
-
func GetOneId(idType string) (int64, error) {
-
//get from cache
-
id,err := cache.GetOneId(idType);
-
return id,err
-
}
4,cache/id.go
-
package cache
-
-
import (
-
"context"
-
"github.com/liuhongdi/digv17/global"
-
"strconv"
-
"github.com/go-redis/redis/v8"
-
)
-
-
//得到cache的名字
-
func getIdCacheName(idType string) (string) {
-
return "id_"+idType
-
}
-
-
//得到一个id
-
func GetOneId(idType string) (int64,error) {
-
key := getIdCacheName(idType);
-
luaId := redis.NewScript(`
-
local id_key = KEYS[1]
-
local current = redis.call('get',id_key)
-
if current == false then
-
redis.call('set',id_key,1)
-
return '1'
-
end
-
--redis.log(redis.LOG_NOTICE,' current:'..current..':')
-
local result = tonumber(current)+1
-
--redis.log(redis.LOG_NOTICE,' result:'..result..':')
-
redis.call('set',id_key,result)
-
return tostring(result)
-
`)
-
var ctx = context.Background()
-
n, err := luaId.Run(ctx, global.RedisDb, []string{key}, 2).Result()
-
-
if (err != nil) {
-
return -1,err
-
} else {
-
var ret string = n.(string)
-
retint,err := strconv.ParseInt(ret, 10, 64)
-
if (err == nil) {
-
return retint,err
-
} else {
-
return -1,err
-
}
-
}
-
}
lua代码的说明:
id_key变量作为存储的kv对的key
如果变量不存在,设置id_key值为1并返回
如果变量存在,值加1后返回
注意转为字符串形式后返回,方便java代码接收
5,其他相关代码可以访问github查看
四,测试效果
1,从redis控制台把原key删除
-
liuhongdi@ku:~$ /usr/local/soft/redis6/bin/redis-cli
-
127.0.0.1:6379> keys *
-
1) "id_logId"
-
2) "article_2"
-
3) "article_3"
-
127.0.0.1:6379> del id_logId
-
(integer) 1
-
127.0.0.1:6379> get id_logId
-
(nil)
-
127.0.0.1:6379> exit
2,通过ab发起100个并发连接:
liuhongdi@ku:~$ ab -c 100 -n 100 http://127.0.0.1:8000/id/getone
通过控制台查看效果:
-
1
-
2
-
3
-
4
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
19
-
20
-
21
-
22
-
23
-
5
-
61
-
6
-
16
-
...
-
38
-
58
-
100
说明:可以看到并发时也没出现重复的id
五,查看库的版本:
-
module github.com/liuhongdi/digv17
-
-
go 1.15
-
-
require (
-
github.com/gin-gonic/gin v1.6.3
-
github.com/go-playground/universal-translator v0.17.0
-
github.com/go-playground/validator/v10 v10.2.0
-
github.com/go-redis/redis/v8 v8.3.3
-
github.com/jinzhu/gorm v1.9.16 // indirect
-
github.com/magiconair/properties v1.8.4 // indirect
-
github.com/mitchellh/mapstructure v1.3.3 // indirect
-
github.com/pelletier/go-toml v1.8.1 // indirect
-
github.com/spf13/afero v1.4.1 // indirect
-
github.com/spf13/cast v1.3.1 // indirect
-
github.com/spf13/jwalterweatherman v1.1.0 // indirect
-
github.com/spf13/pflag v1.0.5 // indirect
-
github.com/spf13/viper v1.7.1
-
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
-
golang.org/x/text v0.3.4 // indirect
-
gopkg.in/ini.v1 v1.62.0 // indirect
-
gopkg.in/yaml.v2 v2.3.0 // indirect
-
)