#### gin-session
* gin-session 一个为gin框架开发的session中间件, 使用redis储存数据, 并且底层维护了一个cache, 大量减小了对redis的读操作 。
* gin-session 保证请求前和请求后, session数据的一致性和完整性, 不保证请求执行过程中数据实时同步。
##### 安装
```shell
go get github.com/loop-xxx/gin-session
```
##### 架构
![00.jpg](https://static.studygolang.com/200309/7bf99dfcdeee15f48aebd3772394c6bc.jpg)
![01.jpg](https://static.studygolang.com/200309/5d7523befbd26ae332b4cb9ef3da7b5a.jpg)
##### 流程
```go
//1 获取请求携带的session
if token, err := ctx.Cookie("gin-session-id"); err == nil{
//2 到pool中查找有没有对应的ball
if cacheBall, exist := pool.SearchCacheBall(token); exist {
ball = cacheBall
}else{
//3 如果未找到则创建新的ball, 并将其交给pool拓展
//该token对应cache ball已经被lru算法移除,
//为该token创建新的cache bool并托管到cache pool
ball = cache_pool.MakeCacheBall(
fmt.Sprintf("gin-session:%s", token),
keeper,
expiration)
pool.AppendCacheBall(token, ball)
}
//4 获取数据前, 先于redis同步以下数据
if ball.Sync(){
//5 同步成功后获取一个cache-ball保存的数据副本
data = ball.Get()
}else{
//同步失败的原因:
//keeper (redis)中的key-value不存在或已过期
//keeper 底层错误(redis-server连接错误)
//keeper 的实现代码有bug
data = make(map[string]string, sessionInitSize)
}
}
```
```go
//执行请求
ctx.Next()
//请求结束后判断副本数据是否被修改过, 若修改过提交到cache-ball, cache-ball也会主动同步到redis
if ginSession.Check(){
ball.Commit(ginSession.Dump())
}
```
##### 参数介绍
```go
GinSessionManager(
keeper, //底层为一个redis客户端
domain, //web服务器的域名
expiration, //session的超时时间默认 30 分钟
poolMaxSize, //cache-pool的最大容积
sessionMapInitSize, //一个空的session被初始化时的最初打下
)
```
##### 简单使用
```go
type User struct{
FirstName string
SecondName string
}
func main() {
if keeper, err := dao.DefaultRedis("192.168.20.130:6379", "toor", 0); err == nil {
engine := gin.Default()
engine.Use(session.DefaultGinSessionManager(keeper, "localhost"))
engine.GET("/login", func(ctx *gin.Context){
if s, exist := session.GetSession(ctx); exist {
s.Set("name", "loop")
_= s.SetStruct("user", User{"li", "loop"})
}
ctx.String(http.StatusOK, "ok")
})
engine.GET("/show", func(ctx *gin.Context){
if s, ok := session.GetSession(ctx); ok {
if name , ok := s.Get("name"); ok{
var u User
if err := s.GetStruct("user",&u); err == nil{
ctx.JSON(http.StatusOK, gin.H{"name": name, "user":u})
}
}
}
})
_ = engine.Run(":2333")
}
}
```
如果你的cache本身就有version,那我个人觉得这个操作在session这个场景中并没有多大意义。
因为本身session一般数据都不长,每次都发起一次一起取版本信息和每次都取完整信息的差别并不大。
我自己也有带版本的本地缓存组件,都是一定长度下直接取远程数据的。
回到正题,是我没有理解你这个cache的意义,对一开始的误解十分抱歉。
#7
更多评论
看着描述就不能支持啊……
方向错了吧?
redis本来就是个cache,然后给redis加个cache是什么操作……
至少我做session组件的时候,session就分两种,基于cache的session和储存在client的session.
用redis就是为了跨进程/服务器共享session使用的,不然直接用个syncmap/gocache/freecache等不香么……
#2