一.reids相关文章

Redis五种数据类型及其应用场景

REDIS中的缓存穿透,缓存击穿,缓存雪崩原因以及解决方案

redis实现用户签到,统计活跃用户,用户在线状态,用户留存率

[golang gin框架] 12.Gin 商城项目-base64Captcha生成图形验证码以及分布式架构中配置Captcha

[go学习笔记.第十七章.redis的使用] 1.redis的使用

linux下yum安装redis服务

二.golang中使用redis

redis介绍以及安装见: [go学习笔记.第十七章.redis的使用] 1.redis的使用

在这里使用go-redis插件来对接redis
模块: https://github.com/go-redis/redis
文档: https://redis.uptrace.dev/
安装go-redis:
下载go-redis,在main.go目录下,执行: go get github.com/redis/go-redis/v9,然后:
import (
"github.com/redis/go-redis/v9"
)
就可以使用go-redis了
下面看看redis相关代码:

1.redisCore.go

该文件中是 连接redis数据库核心代码

package models//redis官网: github.com/go-redis
//下载go-redis: go get github.com/redis/go-redis/v9
//连接redis数据库核心代码import ("context""github.com/redis/go-redis/v9"
)//Go1.7 加入了一个新的标准库 context,它定义了 Context 类型,专门用来简化 对于处理
单个请求的多个 goroutine 之间与请求域的数据、取消信号、截止时间等相关操作
var ctx = context.Background()
//全局使用,就需要把定义成公有的
var ctxRedis = context.Background()var (RedisDb *redis.Client
)//自动初始化数据库
func init() {RedisDb = redis.NewClient(&redis.Options{Addr:     "127.0.0.1:6379",Password: "", // no password setDB:       0,  // use default DB})//连接redis_, err := RedisDb.Ping(ctxRedis).Result()//判断连接是否成功if err != nil {println(err)}
}

2.redisOper.go

操作redis案例说明

package modelsimport ("context""fmt""time"
)var ctx = context.Background()type RedisOper struct {
}//RedisDb调用上面代码中的RedisDb//操作字符串:Set
func (r RedisOper) Set(key string, value string) error {err := RedisDb.Set(ctx, key, value, 0).Err()return err
}//操作字符串:Get
func (r RedisOper) Get(key string) string {val, err := RedisDb.Get(ctx, key).Result()if err != nil {fmt.Println(err)return ""}return val
}//操作列表(list)
func (r RedisOper) ListOper() {RedisDb.LPush(ctx, "hobby", "吃饭")RedisDb.LPush(ctx, "hobby", "睡觉")RedisDb.RPush(ctx, "hobby", "写代码")hobby, _ := RedisDb.LRange(ctx, "hobby", 0, -1).Result()fmt.Println(hobby)
}//操作集合(set)
func (r RedisOper) SetOper() {RedisDb.SAdd(ctx, "hobby", "吃饭", "睡觉", "吃饭")RedisDb.SAdd(ctx, "hobby", "写代码")hobby, _ := RedisDb.SMembers(ctx, "hobby").Result()fmt.Println(hobby)
}//操作哈希(hash)
func (r RedisOper) SetOper() {err := RedisDb.HMSet(ctx, "userinfo", map[string]interface{}{"username": "张三","age":      "20",}).Err()if err != nil {fmt.Println(err)}userinfo, _ := RedisDb.HGetAll(ctx, "userinfo").Result()fmt.Println(userinfo)fmt.Println(userinfo["username"])
}//设置过期时间
func (r RedisOper) SetExpire() {RedisDb.Set(ctx, "age", 20, time.Second*10)RedisDb.LPush(ctx, "hobby", "吃饭")RedisDb.Expire(ctx, "hobby", time.Second*10)
}//删除数据
func (r RedisOper) Del() {RedisDb.Set(ctx, "age", 20, 0)RedisDb.Del(ctx, "age")RedisDb.LPush(ctx, "hobby", "吃饭")RedisDb.FlushAll(ctx)
}

3.Redis 分布式架构订阅发布

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1
之间的关系:

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

案例演示:

redis_pub.go是一个发布的频道端,发布消息,redis_sub1.go,redis_sub2.go,redis_sub3.go是三个客户端,订阅redis_pub.go这个频道端对应频道发布的消息,当频道端发布消息时,三个订阅的客户端会各自订阅频道收到的消息.代码如下:

redis_pub.go

package mainimport ("context""fmt""github.com/go-redis/redis/v9"
)var ctx = context.Background()func main() {//连接redis数据库rdb := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "", // no password setDB:       0,  // use default DB})_, err := rdb.Ping(ctx).Result()if err != nil {fmt.Println("redis数据库连接失败")} else {fmt.Println("redis数据库连接成功...")}//发布消息:rdb.Publish(ctx, "ch", "我是ch的数据...")rdb.Publish(ctx, "ch2", "我是ch2的数据...")
}

假如redis_sub1.go订阅了ch这个频道,redis_sub2.go,redis_sub3.go订阅了ch,ch2这两个频道,对应的代码如下:

redis_sub1.go

package mainimport ("context""fmt""github.com/go-redis/redis/v9"
)var ctx = context.Background()func main() {//连接redis数据库rdb := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "", // no password setDB:       0,  // use default DB})_, err := rdb.Ping(ctx).Result()if err != nil {fmt.Println("redis数据库连接失败")} else {fmt.Println("redis数据库连接成功...")}//订阅消息pubsub := rdb.Subscribe(ctx, "ch")ch := pubsub.Channel()for msg := range ch {fmt.Println(msg.Channel, msg.Payload)}
}

redis_sub2.go,redis_sub3.go

package mainimport ("context""fmt""github.com/go-redis/redis/v9"
)var ctx = context.Background()func main() {//连接redis数据库rdb := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "", // no password setDB:       0,  // use default DB})_, err := rdb.Ping(ctx).Result()if err != nil {fmt.Println("redis数据库连接失败")} else {fmt.Println("redis数据库连接成功...")}//订阅消息pubsub := rdb.Subscribe(ctx, "ch")ch := pubsub.Channel()for msg := range ch {fmt.Println(msg.Channel, msg.Payload)}//订阅消息pubsub2 := rdb.Subscribe(ctx, "ch2")ch2 := pubsub2.Channel()for msg2 := range ch2 {fmt.Println(ms2g.Channel, msg2.Payload)}
}

三.项目中使用redis

  1. 修改redisCore.go核心代码

(1).redis配置修改

把redis配置放入conf/app.ini下,app.ini增加如下代码:

[redis]
ip          = localhost
port        = 6379
database    = 1
redisEnable = true

(2).完善redisCore.go

package models//redis官网: github.com/go-redis
//下载go-redis: go get github.com/redis/go-redis/v9
//连接redis数据库核心代码import ("context""fmt""github.com/redis/go-redis/v9""gopkg.in/ini.v1""os"
)//全局使用,就需要把定义成公有的
var ctxRedis = context.Background()var (RedisDb *redis.Client
)//是否开启redis
var redisEnable bool//自动初始化数据库
func init() {//加载配置文件config, iniErr := ini.Load("./conf/app.ini")if iniErr != nil {fmt.Printf("Fail to read file: %v", iniErr)os.Exit(1)}//获取redis配置ip := config.Section("redis").Key("ip").String()port := config.Section("redis").Key("port").String()redisEnable, _ = config.Section("redis").Key("redisEnable").Bool()//判断是否开启redisif redisEnable {RedisDb = redis.NewClient(&redis.Options{Addr:     ip + ":" + port,Password: "", // no password setDB:       0,  // use default DB})//连接redis_, err := RedisDb.Ping(ctxRedis).Result()//判断连接是否成功if err != nil {println(err)}}
}

2.创建redisCache.go

里面重构Set,Get方法

package modelsimport ("encoding/json""time"
)type RedisCache struct {
}//设置
func (r RedisCache) Set(key string, value interface{}, expiration int) {if redisEnable {  //判断是否开启redisv, err := json.Marshal(value)  //value是一个空接口类型,里面可以是字符串,切片,结构体,所以转成json保存if err == nil {//RedisDb:调用redisCore.go中的RedisDbRedisDb.Set(ctxRedis, key, string(v), time.Second*time.Duration(expiration))}}
}//获取
func (r RedisCache) Get(key string, obj interface{}) bool {if redisEnable { //判断是否开启redisvalueStr, err1 := RedisDb.Get(ctxRedis, key).Result()if err1 == nil && valueStr != "" {err2 := json.Unmarshal([]byte(valueStr), obj)return err2 == nil}}return false
}

3.商品首页控制器IndexController.go使用redis

package frontend//首页import ("github.com/gin-gonic/gin""gorm.io/gorm""goshop/models""net/http""strings"
)type IndexController struct {
}func (con IndexController) Index(c *gin.Context) {//实例化redisCache结构体redisCache := models.RedisCache{}//获取顶部导航列表topNavList := []models.Nav{}//判断redis中是否存在数据if hasTopNavList := redisCache.Get("topNavList", &topNavList); !hasTopNavList {  //不存在数据,则从数据中获取数据,并把数据保存到redismodels.DB.Where("status = 1 AND position = 1").Find(&topNavList)redisCache.Set("topNavList", topNavList, 3600)}//获取网站轮播图数据focusList := []models.Focus{}if hasFocusList := redisCache.Get("focusList", &focusList); !hasFocusList {models.DB.Where("status = 1 AND focus_type = 1").Find(&focusList)redisCache.Set("focusList", focusList, 3600)}//获取分类数据goodsCateList := []models.GoodsCate{}if hasGoodsCateList := redisCache.Get("goodsCateList", &goodsCateList); !hasGoodsCateList {//获取分类列表以及下级分类,并进行排序models.DB.Where("pid = ? AND status = ?", 0, 1).Order("sort DESC").Preload("GoodsCateItems", func(db *gorm.DB) *gorm.DB {return db.Where("goods_cate.status = 1").Order("goods_cate.sort DESC")} ).Find(&goodsCateList)redisCache.Set("goodsCateList", goodsCateList, 3600)}//获取中间导航middleNavList := []models.Nav{}if hasMiddleNavList := redisCache.Get("middleNavList", &middleNavList); !hasMiddleNavList {models.DB.Where("status = ? AND position = ? ", 1, 2).Find(&middleNavList)redisCache.Set("middleNavList", middleNavList, 3600)//循环,获取中间导航对应的商品数据for i:= 0; i < len(middleNavList);i++{//获取管理商品//替换字符串中的中文逗号strings.ReplaceAll()relation := strings.ReplaceAll(middleNavList[i].Relation, ",", ",")//把字符串转换成切片relationIds := strings.Split(relation, ",")//获取对应的商品信息goodsList := []models.Goods{}models.DB.Where("status = ?", 1).Where("id in ?", relationIds).Select("id, title, goods_img, price").Find(&goodsList)middleNavList[i].GoodsItems = goodsList}}//获取手机分类下面的商品phoneList := []models.Goods{}if hasPhoneList := redisCache.Get("phoneList", &phoneList); !hasPhoneList {phoneList := models.GetGoodsByCategory(23, "best", 10)redisCache.Set("phoneList", phoneList, 3600)}c.HTML(http.StatusOK, "frontend/index/index.html", gin.H{"topNavList": topNavList,"focusList": focusList,"goodsCateList": goodsCateList,"middleNavList": middleNavList,"phoneList": phoneList,})
}

[上一节][golang gin框架] 23.Gin 商城项目-前台templates模板分离,首页,顶部导航,轮播图 左侧分类数据渲染

[下一节][golang gin框架] 25.Gin 商城项目-配置清除缓存以及前台列表页面数据渲染公共数据

[golang gin框架] 24.Gin 商城项目-redis讲解以及操作相关推荐

  1. [golang gin框架] 27.Gin 商城项目-购物车

    1.先来看一个问题 购物车数据保持到哪里? 1.购物车数据保存在本地 (cookie或者 redis缓存中),下面统一保存到cookie中,保存到redis中和cookie中逻辑步骤其实都是一样的 2 ...

  2. [golang gin框架] 29.Gin 商城项目-用户登录,注册操作

    一.用户登录,注册界面展示说明 先看登录,注册界面以及相关流程,再根据流程写代码,一般网站的登录,注册功能都会在一个页面进行操作,还有的是在几个页面进行操作,这里讲解在几个页面进行注册的操作,步骤如下 ...

  3. [golang gin框架] 16.Gin 商城项目-商品模块数据表ER图关系分析

    1.数据表ER图 2.数据表相关 (1).商品分类表相关 1).数据表 -- ---------------------------- -- Table structure for goods_cat ...

  4. [golang gin框架] 6.Gin GORM简介以及安装

    介绍 GORM 是 Golang 的一个 orm 框架,简单说,ORM 就是通过实例对象的语法,完成关系型 数据库的操作的技术,是"对象-关系映射"(Object/Relation ...

  5. php商城项目开发视频_ThinkPHP框架开发大型商城项目实战视频教程下载

    ThinkPHP框架开发大型商城项目实战视频教程下载 教程介绍:ThinkPHP 为了简化企业级应用开发和敏捷WEB应用开发而诞生的一个免费开源的,快速.简单的面向对象的国产轻量级PHP开发框架.框架 ...

  6. django debug=false后静态文件丢失_python框架Django实战商城项目之工程搭建

    项目说明 该电商项目类似于京东商城,主要模块有验证.用户.第三方登录.首页广告.商品.购物车.订单.支付以及后台管理系统. 项目开发模式采用前后端不分离的模式,为了提高搜索引擎排名,页面整体刷新采用j ...

  7. python开发商城实战_python框架Django实战商城项目之工程搭建

    项目说明 该电商项目类似于京东商城,主要模块有验证.用户.第三方登录.首页广告.商品.购物车.订单.支付以及后台管理系统. 项目开发模式采用前后端不分离的模式,为了提高搜索引擎排名,页面整体刷新采用j ...

  8. 用python搭建微商城_python框架Django实战商城项目之工程搭建

    项目说明 该电商项目类似于京东商城,主要模块有验证.用户.第三方登录.首页广告.商品.购物车.订单.支付以及后台管理系统. 项目开发模式采用前后端不分离的模式,为了提高搜索引擎排名,页面整体刷新采用j ...

  9. 宝塔部署Yii框架多个商城项目,队列问题“服务测试失败,请检查服务是否正常运行”

    原因:队列起了相同的编号,导致运行队列冲突 Centos7.8 多个商城在同一个宝塔内,必须要设置\config\local.php,给不同队列起不同编号,那么多个商城运行队列不冲突 'queue' ...

最新文章

  1. CSS 选择器:BeautifulSoup4解析器
  2. 一个handle使用更新线程的实例
  3. BUU[SCTF2019]Strange apk
  4. pycharm Enable Live Templates的作用
  5. [笔记]路由器与交换机的区别
  6. IIS错误与解决方法
  7. Linux(三):VMware Tools安装
  8. 滴滴拼车更名“青菜拼车” 或将独立运营
  9. 拓端tecdat|R语言逻辑回归(Logistic Regression)、回归决策树、随机森林信用卡违约分析信贷数据集
  10. ICML2018论文公布!一文了解机器学习最新热议论文和研究热点
  11. c语言代码出来在哪里运行,C语言代码,怎么运行。
  12. redis内存碎片问题
  13. 小程序tabBar图标显示太大
  14. c语言的0xF9为什么表示1,0xc0(0xc0为什么表示0)
  15. Mode Collapse 和 Mode Dropping的定义与不同
  16. 啤酒肚真的是喝啤酒引起的吗?
  17. EasyUI上传图片,前台预览,后台读取
  18. layui请求加token_琴海森林 JFinal-layui 文档、资料、学习、API,token验证
  19. 基于 java 的批量下载压缩包的实现
  20. GitHub 上值得收藏的100个精选前端项目!你知道几个?

热门文章

  1. 日记侠:告诉你一个借助朋友圈吸粉裂变的套路
  2. HashMap?面试?我是谁?我在哪? 侵立删
  3. 2019李永乐考研数学 基础过关660题 数学一
  4. 计算机图形学--阴影1--PCSS算法
  5. 个人计算机属于微型计算机,个人计算机属于
  6. html wap 转换,html移动端wap页面、图片多少宽度最合适?【转载】
  7. Juniper 防火墙端口映射
  8. K8s 1.23.x版本nfs持久存储报错 persistentvolume-controller waiting for a volume to be created, either by ext
  9. 创业投资——风险投资周期及股市趋势技术分析
  10. mbedtls学习(10)数字证书X.509