go语言web开发系列之八:gin框架中用go-redis缓存数据

  • Post author:
  • Post category:其他


一,安装需要用到的库

1,安装go-redis

liuhongdi@ku:~$ go get -u github.com/go-redis/redis

说明:刘宏缔的go森林是一个专注golang的博客,

网站:

https://blog.imgtouch.com


原文:

go语言web开发系列之八:gin框架中用go-redis缓存数据 – 架构森林

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,演示项目的相关信息

1,项目地址:


GitHub – liuhongdi/digv08: gin框架中用go-redis缓存数据

2,项目功能说明:

用go-redis缓存数据,提高响应速度,减少数据库压力

3,项目结构:如图:

三,go代码说明

1,config/config.yaml

Database:
  DBType: mysql
  UserName: root
  Password: password
  Host: 127.0.0.1:3306
  DBName: dig
  Charset: utf8
  ParseTime: True
  MaxIdleConns: 10
  MaxOpenConns: 30
Server:
  RunMode: debug
  HttpPort: 8000
  ReadTimeout: 60
  WriteTimeout: 60
Redis:
  Addr: 127.0.0.1:6379
  Password:

2,cache/article.go

package cache

import (
	"encoding/json"
	"fmt"
	"github.com/go-redis/redis"
	"github.com/liuhongdi/digv08/global"
	"github.com/liuhongdi/digv08/model"
	"strconv"
	"time"
)
//token的过期时长
const ArticleDuration = time.Minute * 5

//cache的名字
func getArticleCacheName(articleId uint64) (string) {
	return "article_"+strconv.FormatUint(articleId,10)
}

//从cache得到一篇文章
func GetOneArticleCache(articleId uint64) (*model.Article,error) {
	key := getArticleCacheName(articleId);
	val, err := global.RedisDb.Get(key).Result()

	if (err == redis.Nil || err != nil) {
		return nil,err
	} else {
		article := model.Article{}
		if err := json.Unmarshal([]byte(val), &article); err != nil {
			//t.Error(target)
			return nil,err
		}
		return &article,nil
	}
}
//向cache保存一篇文章
func SetOneArticleCache(articleId uint64,article *model.Article) (error) {
	key := getArticleCacheName(articleId);
	content,err := json.Marshal(article)
	if (err != nil){
		fmt.Println(err)
		return err;
	}
	errSet := global.RedisDb.Set(key, content, ArticleDuration).Err()
	if (errSet != nil) {
		return errSet
	}
	return nil
}

3,global/setting.go

package global

import (
	"github.com/liuhongdi/digv08/pkg/setting"
	"time"
)
//服务器配置
type ServerSettingS struct {
	RunMode      string
	HttpPort     string
	ReadTimeout  time.Duration
	WriteTimeout time.Duration
}
//数据库配置
type DatabaseSettingS struct {
	DBType       string
	UserName     string
	Password     string
	Host         string
	DBName       string
	Charset      string
	ParseTime    bool
	MaxIdleConns int
	MaxOpenConns int
}
//redis配置
type RedisSettingS struct {
	Addr      string
	Password     string
}
//定义全局变量
var (
	ServerSetting   *ServerSettingS
	DatabaseSetting *DatabaseSettingS
	RedisSetting   *RedisSettingS
)

//读取配置到全局变量
func SetupSetting() error {
	s, err := setting.NewSetting()
	if err != nil {
		return err
	}
	err = s.ReadSection("Database", &DatabaseSetting)
	if err != nil {
		return err
	}

	err = s.ReadSection("Server", &ServerSetting)
	if err != nil {
		return err
	}

	err = s.ReadSection("Redis", &RedisSetting)
	if err != nil {
		return err
	}

	return nil
}

4,global/redisDb.go

package global

import (
	"github.com/go-redis/redis"
)
//保存redis连接
var (
	RedisDb *redis.Client
)

//创建到redis的连接
func SetupRedisDb() (error) {

	RedisDb = redis.NewClient(&redis.Options{
		Addr:     RedisSetting.Addr,
		Password: RedisSetting.Password, // no password set
		DB:       0,  // use default DB
	})

	_, err := RedisDb.Ping().Result()
	if err != nil {
		return err
	}
	return nil

}

5,service/article.go

package service

import (
	"github.com/go-redis/redis"
	"github.com/liuhongdi/digv08/cache"
	"github.com/liuhongdi/digv08/dao"
	"github.com/liuhongdi/digv08/model"
)
//得到一篇文章的详情
func GetOneArticle(articleId uint64) (*model.Article, error) {
	//get from cache
     article,err := cache.GetOneArticleCache(articleId);
     if (err == redis.Nil || err != nil) {
     	 //get from mysql
		 article,errSel := dao.SelectOneArticle(articleId);
		 if (errSel != nil) {
		 	return nil,errSel
		 } else {
		 	//set cache
		 	errSet := cache.SetOneArticleCache(articleId,article)
		 	if (errSet != nil){
		 		return nil,errSet
			} else {
				return article,errSel
			}
		 }
	 } else {
	 	return article,err
	 }
}

func GetArticleSum() (int, error) {
	return dao.SelectcountAll()
}

//得到多篇文章,按分页返回
func GetArticleList(page int ,pageSize int) ([]*model.Article,error) {
	articles, err := dao.SelectAllArticle(page,pageSize)
	if err != nil {
		return nil,err
	} else {
		return articles,nil
	}
}

6,main.go

package main

import (
	"github.com/gin-gonic/gin"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"github.com/liuhongdi/digv08/global"
	"github.com/liuhongdi/digv08/router"
	"log"
)

//init
func init() {
	err := global.SetupSetting()
	if err != nil {
		log.Fatalf("init.setupSetting err: %v", err)
	}

	err = global.SetupDBLink()
	if err != nil {
		log.Fatalf("init.setupDBEngine err: %v", err)
	}

	err = global.SetupRedisDb()
	if err != nil {
		log.Fatalf("init.SetupRedisDb err: %v", err)
	}
}

func main() {
	//设置运行模式
	gin.SetMode(global.ServerSetting.RunMode)
	//引入路由
	r := router.Router()
	//run
	r.Run(":"+global.ServerSetting.HttpPort)
}

7,其他相关代码可访问github

四,测试效果

1,访问一篇文章:例:

http://127.0.0.1:8000/article/getone/4

返回:

查看redis中的缓存:

root@ku:/data/liuhongdi/digv08# /usr/local/soft/redis6/bin/redis-cli 
127.0.0.1:6379> 
127.0.0.1:6379> get article_4
"{\"ArticleId\":4,\"Subject\":\"\xe6\x89\xab\xe5\x9c\xb0\xe6\x9c\xba\xe5\x99\xa8\xe4\xba\xba\xe8\xbf\x99\xe4\xb8\xaa\xe4\xb8\x9c\xe8\xa5\xbf...\x80\x82\",\"Url\":\"\",\"imgurl\":\"\",\"headurl\":\"\"}"

再刷新几次,注意看gin在控制台打印出的响应时间:

(/data/liuhongdi/digv08/dao/article.go:12) 
[2020-12-18 15:13:40]  [2.14ms]  SELECT articleId, subject, url FROM `article`  WHERE (articleId=4) LIMIT 1  
[1 rows affected or returned ] 
[GIN] 2020/12/18 - 15:13:40 | 200 |    4.584695ms |       127.0.0.1 | GET      "/article/getone/4"
[GIN] 2020/12/18 - 15:16:13 | 200 |     672.171µs |       127.0.0.1 | GET      "/article/getone/4"
[GIN] 2020/12/18 - 15:16:15 | 200 |     611.256µs |       127.0.0.1 | GET      "/article/getone/4"
[GIN] 2020/12/18 - 15:16:16 | 200 |     638.018µs |       127.0.0.1 | GET      "/article/getone/4"

可以看到当有数据库查询时,响应时间为4毫秒左右

当直接访问redis时,响应时间提升了7倍左右,600微秒左右

五,查看库的版本:

module github.com/liuhongdi/digv08

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/jinzhu/gorm v1.9.16
	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
	github.com/go-redis/redis v6.15.9+incompatible
	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
)



版权声明:本文为weixin_43881017原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。