1,安装go-redis
liuhongdi@ku:~$ go get -u github.com/go-redis/redis
说明:刘宏缔的go森林是一个专注golang的博客,
地址:https://blog.csdn.net/weixin_43881017
说明:作者:刘宏缔 邮箱: [email protected]
1,项目地址:
https://github.com/liuhongdi/digv08
2,项目功能说明:
用go-redis缓存数据,提高响应速度,减少数据库压力
3,项目结构:如图:
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
)