golang云原生项目☞redis配置
配置redis适用与golang云原生架构。包括redis与数据库一致性等重要内容
1、编写redis配置文件、使用viper读取
- 配置文件
db.yml
redis:addr: 127.0.0.1port: 6379password: tiktokRedisdb: 0 # 数据库编号
- 读取配置文件
var (config = viper.Init("db")zapLogger = zap.InitLogger()redisOnce sync.OnceredisHelper *RedisHelperFavoriteMutex *redsync.MutexRelationMutex *redsync.Mutex
)
2、新建并初始化一个redisClient
-
新建
- 其中sync.Once 是 Go 标准库中提供的一个同步原语,用于保证某个操作仅执行一次。
调用 redisOnce.Do() 方法,传入一个函数作为参数。Do() 方法会判断该函数是否已经被执行过,如果没有,则执行该函数。在这个例子中,函数中的代码如下:
rdh := new(RedisHelper) rdh.Client = rdb redisHelper = rdh
在这段代码中,首先创建了一个 RedisHelper 对象,并将 rdb 赋值给其中的 Client 字段。然后,将 rdh 赋值给 redisHelper 变量。redisHelper 是一个全局变量,用于保存单例实例。
通过这样的方式,可以保证在多个并发请求中,只有第一次执行 Do() 方法时会初始化 Redis 连接单例,后续的请求都会直接返回已经初始化好的连接对象。 - 其中sync.Once 是 Go 标准库中提供的一个同步原语,用于保证某个操作仅执行一次。
func NewRedisHelper() *redis.Client {rdb := redis.NewClient(&redis.Options{Addr: fmt.Sprintf("%s:%s", config.Viper.GetString("redis.addr"), config.Viper.GetString("redis.port")),Password: config.Viper.GetString("redis.password"),DB: config.Viper.GetInt("redis.db"),DialTimeout: 10 * time.Second,ReadTimeout: 30 * time.Second,WriteTimeout: 30 * time.Second,//MaxConnAge: 1 * time.Minute, go-redis v9 已删去PoolSize: 10,PoolTimeout: 30 * time.Second,})redisOnce.Do(func() {rdh := new(RedisHelper)rdh.Client = rdbredisHelper = rdh})return rdb
}
-
初始化
- 为什么需要传入 ctx?
控制请求的超时和取消:通过传入 ctx,可以设置请求的超时时间,当超过指定时间后,可以自动取消请求,避免无限等待。这对于处理网络请求或长时间运行的操作非常重要,可以确保你的程序具有良好的健壮性,并能及时释放资源。
传递请求特定的值:ctx 可以用于在请求的不同组件之间传递请求特定的值,如身份验证令牌、用户信息等。通过使用 ctx,可以将这些值以一种可靠且类型安全的方式传递给相关的函数和方法。
协调并发请求:在并发请求的场景中,ctx 可以用于协调各个请求的完成状态。你可以通过 ctx 来等待所有请求完成或收集并汇总结果。
- 为什么需要传入 ctx?
func init() {ctx := context.Background()rdb := NewRedisHelper()//典型测试连接的代码if _, err := rdb.Ping(ctx).Result(); err != nil {zapLogger.Fatalln(err.Error())return}zapLogger.Info("Redis server connection successful!")// 开启定时同步至数据库GoCronFavorite()GoCronRelation()zapLogger.Info("MySQL synchronization is enabled.")// Redis锁// 创建Redis连接池pool := goredis.NewPool(rdb)// Create an instance of redisync to be used to obtain a mutual exclusion lock.rs := redsync.New(pool)// Obtain a new mutex by using the same name for all instances wanting the same lock.FavoriteMutex = rs.NewMutex("mutex-favorite")RelationMutex = rs.NewMutex("mutex-relation")
}
3. redis和mysql的一致性
使用定时同步的思想,将redis中的数据定时同步到数据库中
3.1 异步定时任务的执行
具体做法:
- 使用了 GoCron 库来创建一个定时任务,每隔一定频率执行 RedisDataMoveToDB 函数。
- 首先,通过 gocron.NewSchedule() 创建了一个调度器对象 s。
- 接下来,调用 s.Every(frequency) 方法设置定时任务的执行频率,frequency 是一个时间间隔。这里使用 .Seconds() 方法表示以秒为单位进行间隔设置。
- 然后,通过 .Tag(“favoriteRedis”) 方法给定时任务添加了一个标签,用于标识该任务,以便后续操作或管理。
- 最后,调用 .Do(FavoriteMoveToDB) 方法指定定时任务要执行的函数为 FavoriteMoveToDB,即在每个频率间隔结束时执行该函数。
- 最后一行的 s.StartAsync() 表示以异步方式开始执行定时任务。这会启动一个新的 goroutine 来执行定时任务,而不会阻塞当前的程序执行。这样可以保证定时任务在后台按照设定的频率执行,而不会影响主程序的执行。
func GoCronFavorite() {s := gocron.NewSchedule()s.Every(frequency).Tag("favoriteRedis").Seconds().Do(FavoriteMoveToDB)s.StartAsync()
}
其中使用到的gocron:
// Schedule 定时任务 gocron
type Schedule struct {*gocron.Scheduler
}
func NewSchedule() *gocron.Scheduler {return gocron.NewScheduler(time.Local)
}
3.2 redis同步到数据库
func RelationMoveToDB() error {logger := zap.InitLogger()ctx := context.Background()keys, err := getKeys(ctx, "user::*::to_user::*::w")if err != nil {logger.Errorln(err)return err}for _, key := range keys {res, err := GetRedisHelper().Get(ctx, key).Result()vSplit := strings.Split(res, "::")_, redisAt := vSplit[0], vSplit[1]if err != nil {logger.Errorln(err.Error())return err}// 拆分得keykSplit := strings.Split(key, "::")uid, tid := kSplit[1], kSplit[3]userID, err := strconv.ParseInt(uid, 10, 64)if err != nil {logger.Errorln(err.Error())return err}toUserID, err := strconv.ParseInt(tid, 10, 64)if err != nil {logger.Errorln(err.Error())return err}// 检查是否存在对应IDu, err := db.GetUserByID(ctx, userID)if err != nil {logger.Errorln(err.Error())return err}tu, err := db.GetUserByID(ctx, toUserID)if err != nil {logger.Errorln(err.Error())return err}if u == nil || tu == nil {delErr := deleteKeys(ctx, key, RelationMutex)if delErr != nil {logger.Errorln(delErr.Error())return delErr}continue}// 查询是否存在关注记录relation, err := db.GetRelationByUserIDs(ctx, userID, toUserID)if err != nil {logger.Errorln(err.Error())return err} else if relation == nil && redisAt == "1" {// 数据库中没有该关注记录,且最终状态为关注,则插入数据库err = db.CreateRelation(ctx, userID, toUserID)// 插入后,删除Redis中对应记录delErr := deleteKeys(ctx, key, RelationMutex)if delErr != nil {logger.Errorln(delErr.Error())return delErr}if err != nil {logger.Errorln(err.Error())return err}} else if relation != nil && redisAt == "2" {// 数据库中有该关注记录,且最终状态为取消关注,则从数据库中删除该记录err = db.DelRelationByUserIDs(ctx, userID, toUserID)// 删除Redis中对应记录delErr := deleteKeys(ctx, key, RelationMutex)if delErr != nil {logger.Errorln(delErr.Error())return delErr}if err != nil {logger.Errorln(err.Error())return err}}// 删除Redis中对应记录delErr := deleteKeys(ctx, key, RelationMutex)if delErr != nil {logger.Errorln(delErr.Error())return delErr}}return nil
}
相关文章:
golang云原生项目☞redis配置
配置redis适用与golang云原生架构。包括redis与数据库一致性等重要内容 1、编写redis配置文件、使用viper读取 配置文件 db.yml redis:addr: 127.0.0.1port: 6379password: tiktokRedisdb: 0 # 数据库编号读取配置文件 var (config viper.Init("db")zapL…...
C++ malloc/free/new/delete详解(内存管理)
C malloc/free/new/delete详解(内存管理) malloc/free典型用法内存分配实现过程brk和mmap申请小于128k的内存申请大于128k的内存释放内存brk和mmap的区别 new/delete典型用法 内存分配实现过程new/delete和malloc/free的区别malloc对于给每个进程分配的内…...
SpringBoot中Mapper.xml的入参方式
在SpringBoot开发过程中,我们使用 ***Mapper.xml***Mapper.java 来封装对数据库表的 CURD 操作,正常每张表会有一组对应的文件。 一、Mapper常见用法 下面例举一个查询操作: 数据表t_sap_customer,表中有字段id、code、name、c…...
回归预测 | MATLAB实现WOA-RBF鲸鱼优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现WOA-RBF鲸鱼优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现WOA-RBF鲸鱼优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图&#…...
浅析Python爬虫ip程序延迟和吞吐量影响因素
作为一名资深的爬虫程序员,今天我们很有必要来聊聊Python爬虫ip程序的延迟和吞吐量,这是影响我们爬取效率的重要因素。这里我们会提供一些实用的解决方案,让你的爬虫程序飞起来! 网络延迟 首先,让我们来看看网络延迟对…...
【100天精通python】Day43:python网络爬虫开发_爬虫基础(urlib库、Beautiful Soup库、使用代理+实战代码)
目录 1 urlib 库 2 Beautiful Soup库 3 使用代理 3.1 代理种类 HTTP、HTTPS 和 SOCKS5 3.2 使用 urllib 和 requests 库使用代理 3.3 案例:自建代理池 4 实战 提取视频信息并进行分析 1 urlib 库 urllib 是 Python 内置的标准库,用于处理URL、发送…...
Linux:安全技术与防火墙
目录 一、安全技术 1.安全技术 2.防火墙的分类 3.防水墙 4.netfilter/iptables关系 二、防火墙 1、iptables四表五链 2、黑白名单 3.iptables命令 3.1查看filter表所有链 iptables -L 编辑3.2用数字形式(fliter)表所有链 查看输出结果 iptables -nL 3.3 清空所有链…...
Confluent kafka 异常退出rd_tmpabuf_alloc0: rd kafka topic info_new_with_rack
rd_tmpabuf_alloc0: rd kafka topic info_new_with_rack 根据网上的例子,做了一个测试程序。 C# 操作Kafka_c# kafka_Riven Chen的博客-CSDN博客 但是执行下面一行时,弹出上面的异常,闪退。 consumer.Subscribe(queueName) 解决方案&…...
最新ChatGPT网站程序源码+AI系统+详细图文搭建教程/支持GPT4.0/AI绘画/H5端/Prompt知识库
一、前言 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧!…...
chatGPT-对话柏拉图
引言: 古希腊哲学家柏拉图,在他的众多著作中,尤以《理想国》为人所熟知。在这部杰作中,他勾勒了一个理想的政治制度,提出了各种政体,并阐述了他对于公正、智慧以及政治稳定的哲学观点。然而,其…...
Java项目-苍穹外卖-Day04
公共字段自动填充 这些字段在每张表基本都有,手动进行填充效率低,且后期维护更改繁琐 使用到注解AOP主要 先答应一个AutoFill注解 再定义一个切面类进行通知 对应代码 用到了枚举类和反射 package com.sky.aspect; /*** 自定义切面类,…...
SQL递归获取完整的树形结构数据
在 SQL 中,WITH RECURSIVE 用于创建递归查询,它允许在查询中引用自身。这种查询通常用于处理具有层次结构的数据,例如树形结构。 以下是使用 WITH RECURSIVE 创建递归查询的一般语法: WITH RECURSIVE [alias] ([column1], [colu…...
如何使用营销活动,提升小程序用户的参与度
在当今数字化时代,小程序已成为企业私域营销的重要一环。然而,仅仅拥有小程序还不足以吸引用户的兴趣和参与。营销活动作为推动用户参与的有效手段,可以在激烈的市场竞争中脱颖而出。本文将深入探讨如何使用营销活动,提升小程序用…...
IDEA中使用Docker插件构建镜像并推送至私服Harbor
一、开启Docker服务器的远程访问 1.1 开启2375远程访问 默认的dokcer是不支持远程访问的,需要加点配置,开启Docker的远程访问 # 首先查看docker配置文件所在位置 systemctl status docker# 会输出如下内容: ● docker.service - Docker Ap…...
第7章 高性能门户首页构建
mini商城第7章 高性能门户首页构建 一、课题 高性能门户建设 二、回顾 1、了解文件存储系统的概念 2、了解常用文件服务器的区别 3、掌握Minio的应用 三、目标 1、OpenResty 百万并发站点架构 OpenResty 特性介绍 搭建OpenResty Web站点动静分离方案剖析 2、多级缓存架…...
用加持了大模型的 Byzer-Notebook 做数据分析是什么体验
Byzer-Notebook 是专门为 SQL 而研发的一款 Web Notebook。他的第一公民是 SQL,而 Jupyter 则是是以 Python 为第一公民的。 随着 Byzer 引擎对大模型能力的支持日渐完善, Byzer-Notebook 也在不自觉中变得更加强大。我和小伙伴在聊天的过程中才发现他已…...
学习设计模式之观察者模式,但是宝可梦
前言 作者在准备秋招中,学习设计模式,做点小笔记,用宝可梦为场景举例,有错误欢迎指出。 观察者模式 观察者模式定义了一种一对多的依赖关系,一个对象的状态改变,其他所有依赖者都会接收相应的通知。 所…...
课程项目设计--spring security--用户管理功能--宿舍管理系统--springboot后端
写在前面: 还要实习,每次时间好少呀,进度会比较慢一点 本文主要实现是用户管理相关功能。 前文项目建立 文章目录 验证码功能验证码配置验证码生成工具类添加依赖功能测试编写controller接口启动项目 security配置拦截器配置验证码拦截器 …...
学习设计模式之装饰器模式,但是宝可梦
装饰模式 为了不改变组件的结构,动态地扩展其功能。 通常,扩展功能通过子类进行,但是继承的方式具有静态特征,耦合度高。 意图:动态地给对象添加额外的功能 主要解决:继承方式是静态特征,扩…...
【AWS】创建IAM用户;无法登录IAM用户怎么办?错误提示:您的身份验证信息错误,请重试(已解决)
目录 0.背景问题分析 1.解决步骤 0.背景问题分析 windows 11 ,64位 我的问题情景: 首先我创建了aws的账户,并且可以用ROOT用户登录,但是在登录时选择IAM用户,输入ROOT的名字和密码,就会提示【您的身份验证…...
微服务基础知识
文章目录 微服务基础知识一、系统架构的演变1、单体应用架构2、垂直应用架构3、分布式SOA架构(1)什么是SOA(2)SOA架构 4、微服务架构5、SOA和微服务的关系(1)SOA(2)微服务架构 二、分…...
倒残差结构
倒残差结构: 倒残差结构是MobileNetV2中引入的一种设计,用于增强网络的表达能力和特征提取能力,同时保持轻量级的特点。它的核心思想是在每个瓶颈块中,先使用一个扩张卷积(Dilated Convolution)&#x…...
Docker的基本使用
Docker 概念 Docker架构 docker分为客户端,Docker服务端,仓库 客户端 Docker 是一个客户端-服务器(C/S)架构程序。Docker 客户端只需要向 Docker 服务端发起请求,服务端将完成所有的工作并返回相应结果。 Docker …...
paddlenlp安装踩坑记录
错误1 ModuleNotFoundError: No module named paddle.metric我下载paddlepaddle-gpu2.5.0.post117解决了,最开始下载的2.5.1报错,post后面的117是我的cuda版本,不要写你对应的版本号 python3 -m pip install paddlepaddle-gpu2.5.0.post117…...
微服务流程引擎:简单又灵活,实现流程全生命周期管理!
伴随着日益激烈的市场竞争,传统的办公操作已经无法满足发展需要了。如果采用微服务流程引擎加油助力,就可以帮助企业更好地管理数据资源,高效做好各种表单制作,实现高效率办公。流辰信息以市场为导向,用心钻研低代码技…...
Qt表格数据处理
概述 在Qt表格数据处理中,涉及到如下几个具体的类: QAbstractItemModel:这是一个抽象基类,定义了模型(Model)的接口规范。所有的模型类都应该派生自QAbstractItemModel,并实现它的纯虚函数&…...
EasyPOI 实战总结
EasyPOI实战总结 简介 easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 语言(熟悉的表达式语法),完成以前复杂的写法 使用EasyPOI 环境搭建 # 1.引入相关依…...
【LeetCode-困难题】42. 接雨水
题目 题解一:暴力双重for循环(以行计算水量) 1.先找出最高的柱子有多高(max 3) 2.然后第一个for为行数(1,2,3) 3.第二个for计算每一行的雨水量(关键在于去除…...
npm install 安装依赖,报错 Host key verification failed
设置 git 的身份和邮箱 git config --global user.name "你的名字" > 用户名 git config --global user.email “你的邮箱" > 邮箱进入 > 用户 > [你的用户名] > .ssh文件夹下,删除 known_hosts 文件即可 进入之后有可能会看到 known_hosts…...
SOLIDWORKS焊件是什么?
SOLIDWORKS是一款广泛应用于机械设计领域的三维计算机辅助设计软件。SOLIDWORKS提供了强大的焊件功能,可以帮助工程师们以更高的效率设计焊接件。本文将介绍SOLIDWORKS焊件的概念、特点以及使用方法,以期帮助读者更好地理解和应用这一关键技术。 SOLIDWO…...
网上接网站开发不给钱怎么办/成都关键词seo推广电话
js封装的向某个元素后添加元素 由于js没有现成的方法我们需要自己进行封装 //param newElement新创建的元素 //param targetElement传递的已知元素 function insertAfter ( newElement, targetElement ) {var parent targetElement.parentNode;if ( parent.lastChild targe…...
昆山设计网站的公司哪家好/公司如何在百度宣传
目录 1、什么是性能测试? 2、性能测试概念分析以便全面理解性能测试 3、性能测试基本类型 4、性能测试应用场景 希望能帮助测试、开发盆友更全面理解性能测试,更好的开展性能测试工作~ 1、什么是性能测试? 指通过测试工具模拟多种正常、峰…...
手机网站模板 怎样做/东莞seo报价
描述SWRITE具有与CWRITE类似的功能和语法。但是,与CWRITE不同,SWRITE不会将数据写入通道,而是写入CHAR数组。1. 可以将CWRITE限制为将数据写入通道。 SWRITE可以执行更复杂的格式化任务。这使程序更加灵活。2. CWRITE最多可以处理10个变量。…...
可信网站图片logo安装/国外产品推广平台
本文转载:http://www.cnblogs.com/gis-crazy/archive/2013/03/17/2964132.html 查看公司项目代码时,存在这样一个问题:winform界面上有很多信息填写,提交后台服务器更新,但数据的合法验证及值的转换却不太敢恭维&#…...
做古风人物小图的网站或软件/网站建设技术外包
1(必选)、解压从adobe官方网站 http://get.adobe.com/cn/flashplayer/ 下载下来的flash player的*.tar.gz文件 2(必选)、将libflashplayer.so文件拷贝到/usr/lib/mozilla/plugins目录下命令:sudo cp libflashplayer.so /usr/lib/mozilla/plugins/libflashplayer.so…...
域名做非法网站/郑州网络推广方法
课程介绍Shell语言是生产环境中应用广泛的脚本型语言,主要用来处理多任务、自动化部署等任务。在Linux中shell语言是举足轻重的超级工具语言,它保证了Linux高效工作的同时,还兼顾在命令行中处理用户指令。利用shell脚本可以编写自动化管理工具…...