golang云原生项目☞redis配置

配置redis适用与golang云原生架构。包括redis与数据库一致性等重要内容

1、编写redis配置文件、使用viper读取

  1. 配置文件
    db.yml
redis:addr: 127.0.0.1port: 6379password: tiktokRedisdb: 0 # 数据库编号
  1. 读取配置文件
var (config        = viper.Init("db")zapLogger     = zap.InitLogger()redisOnce     sync.OnceredisHelper   *RedisHelperFavoriteMutex *redsync.MutexRelationMutex *redsync.Mutex
)

2、新建并初始化一个redisClient

  1. 新建

    • 其中sync.Once 是 Go 标准库中提供的一个同步原语,用于保证某个操作仅执行一次。
      调用 redisOnce.Do() 方法,传入一个函数作为参数。Do() 方法会判断该函数是否已经被执行过,如果没有,则执行该函数。在这个例子中,函数中的代码如下:
    rdh := new(RedisHelper)
    rdh.Client = rdb
    redisHelper = rdh
    

    在这段代码中,首先创建了一个 RedisHelper 对象,并将 rdb 赋值给其中的 Client 字段。然后,将 rdh 赋值给 redisHelper 变量。redisHelper 是一个全局变量,用于保存单例实例。
    通过这样的方式,可以保证在多个并发请求中,只有第一次执行 Do() 方法时会初始化 Redis 连接单例,后续的请求都会直接返回已经初始化好的连接对象。

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
}
  1. 初始化

    • 为什么需要传入 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 异步定时任务的执行

具体做法:

  1. 使用了 GoCron 库来创建一个定时任务,每隔一定频率执行 RedisDataMoveToDB 函数。
  2. 首先,通过 gocron.NewSchedule() 创建了一个调度器对象 s。
  3. 接下来,调用 s.Every(frequency) 方法设置定时任务的执行频率,frequency 是一个时间间隔。这里使用 .Seconds() 方法表示以秒为单位进行间隔设置。
  4. 然后,通过 .Tag(“favoriteRedis”) 方法给定时任务添加了一个标签,用于标识该任务,以便后续操作或管理。
  5. 最后,调用 .Do(FavoriteMoveToDB) 方法指定定时任务要执行的函数为 FavoriteMoveToDB,即在每个频率间隔结束时执行该函数。
  6. 最后一行的 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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/51931.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【面试经典150题】删除有序数组中的重复项-JavaScript版

题目链接 思路1&#xff1a;使用set。 /*** param {number[]} nums* return {number}*/ var removeDuplicates function(nums) {const uniqueSetnew Set();for(let i0;i<nums.length;i){uniqueSet.add(nums[i]);}const uniqueArrayArray.from(uniqueSet);nums.length0;nu…

软考高级系统架构设计师系列论文七十九:论软件产品线技术

软考高级系统架构设计师系列论文七十九:论软件产品线技术 一、摘要二、正文三、总结一、摘要 根据公司软件系统开发的需要,我们在软件的开发过程中引入了软件产品线技术,成立了基于软件产品线的项目组。本人有幸参加了该项目,并在其中担任软件分析与设计、软件产品线核心资…

控制疫情蔓延嵌入式物联网能帮大忙

联合国所订定之永续发展目标之一&#xff0c;便是针对防治传染病的蔓延做好准备。在新型冠状病毒(COVID-19)流行期间&#xff0c;防疫已成为当前最重要目标&#xff0c;科技在对抗传染病方面扮演重要角色&#xff0c;而物联网(IoT)相关技术正是我们重要的防疫武器──降低成本、…

基于Java+SpringBoot+vue前后端分离华强北商城二手手机管理系统设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

win10系统rust串口通信实现

一、用cargo创建新工程 命令&#xff1a;cargo new comport use std::env; use std::{thread, time}; use serialport::{DataBits, StopBits, Parity, FlowControl}; use std::io::{self, Read, Write}; use std::time::Duration;fn main() -> io::Result<()> {let m…

Matlab分割彩色图像

彩色图像 彩色图像除有亮度信息外&#xff0c;还包含有颜色信息。以最常见的RGB&#xff08;红绿蓝&#xff09;彩色空间为例来简要说明彩色图像&#xff1a; 彩色图像可按照颜色的数目来划分。例如&#xff0c;256色图像和真彩色图像&#xff08;2的16次方&#xff1d;21677…

『C语言入门』C语言数组详解

文章目录 引言一、一维数组1.1 数组的创建1.2 数组的初始化1.3 一维数组的使用1.4 一维数组在内存中的存储1.4.1 内存中的数组布局1.4.2 计算元素的内存地址1.4.3 内存中的数组可视化1.4.4 指针与数组的关系1.5.5 内存布局的影响 二、二维数组2.1 二维数组的创建2.2 二维数组的…

JDK JRE JVM 三者之间的详解

JDK : Java Development Kit JRE: Java Runtime Environment JVM : JAVA Virtual Machine JDK : Java Development Kit JDK : Java Development Kit【 Java开发者工具】&#xff0c;可以从上图可以看出&#xff0c;JDK包含JRE&#xff1b;java自己的一些开发工具中&#…

第十五天|104.二叉树的最大深度、111.二叉树的最小深度、 222.完全二叉树的节点个数

104.二叉树的最大深度 题目链接&#xff1a;104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullp…

Java后端开发面试题——消息中间篇

RabbitMQ-如何保证消息不丢失 交换机持久化&#xff1a; Bean public DirectExchange simpleExchange(){// 三个参数&#xff1a;交换机名称、是否持久化、当没有queue与其绑定时是否自动删除 return new DirectExchange("simple.direct", true, false); }队列持久化…

[Linux]环境变量

[Linux]环境变量 文章目录 [Linux]环境变量环境变量的概念查看环境变量环境变量的加载原理环境变量的添加刷新环境变量配置文件的路径 环境变量的概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。 环境变量的本质&#xff1a;…

css层叠关系

文章目录 cascading声明冲突应用重置样式表a元素的类选择器顺序问题 cascading cascading – 层叠 解决声明冲突的过程&#xff0c;浏览器会自动处理&#xff1b;就是计算样式的权重&#xff0c;权重大的就被选择&#xff1b; 声明冲突 是指多个选择器选中同一个标签&#x…

AMEYA360代理品牌:纳芯微芯片解决方案为光伏市场赋能

近年来&#xff0c;光伏市场进入了一个新的增长维度。SolarPower Europe数据显示&#xff0c;2022年全球光伏新增装机量达239GW&#xff0c;占所有可再生能源新增容量的三分之二。国家能源局也宣称&#xff0c;2022年我国工商业光伏新增装机达25.87GW&#xff0c;同比增长236.7…

C#面向对象程序设计之变量的作用域,深入浅出 入门和进阶教程3

1、效果镇楼: 最近忒忙了!真的忙到不可开交的呢,繁杂业务的处理真的不是您,我个人想象的样子,完全比您个人想象的要复杂至少三倍以上的难度!也是客观事实。 菜鸟程序员面临的客观残酷现实!尤其您这个年龄阶段,实在是堪忧,尴尬的很啊,非常严峻的形势,也可以说特别严峻…

Element table根据字段合并表格(可多字段合并),附带拖拽列动态合并

效果如图&#xff0c;姓名 数值1 字段进行自动合并 封装合并列js - tableMerge.js // 获取列合并的行数 // params // tableData: 表格数据 // mergeId: 合并的列的字段名 export const tagRowSpan (tableData, mergeId) >{const tagArr [];let pos 0;tableData.map((i…

vue组件的scope 以及 如何样式穿透

个人复习&#xff01;&#xff01;&#xff01; 有什么用 让当前组件的样式不会修改到其它地方的样式&#xff0c;使用了data-v-hash的方式来使css有了它对应模块的标识 实现原理 1、给HTML的dom节点添加一个不重复的data属性(例如: data-v-5558831a)来唯一标识这个dom 元素…

linux启动jar 缺失lib

linux启动jar包时&#xff0c;找不到报错 [rootebs-141185 xl-admin]# java -Djava.library.path/home/kabangke/xl-admin/lib -jar /home/kabangke/xl-admin/xl-admin.jar Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/web/se…

诺依框架ruoyi.js添加默认当年日期范围

ruoyi.js添加方法 // 默认当年日期范围如&#xff1a;2023-01-01到2023-08-22&#xff08;至今&#xff09; export function defaultYearDate(data) {// this.dateDefaultShow new Date();// this.dateDefaultShow.setMonth(new Date().getMonth() - 1);const end new Date…

ubuntu 对多CPU统一设置高性能模式

文章目录 一、问题描述二、软件安装与设置三、查看各CPU状态四、开机默认高性能4.1 安装cpufrequtils4.2 编写脚本4.3 设为默认开机脚本 参考链接 一、问题描述 之前在网上找到的CPU设置高性能模式&#xff0c;只能设置CPU0单个CPU&#xff0c;下述是对多核CPU统一设置工作模式…

Linux 设置mysql开机自启动和安装JDK

0目录 1.mysql设置开机自启动 2.linux安装jdk 1.mysql设置开机自启动 去到cd /etc/rc.d/init.d目录 创建一个sh脚本 编辑脚本 设置开机自启动 重启 检查是否自启动 2.linux安装jdk 下载安装包 放在opt目录下 新建soft文件夹&#xff08;opt目录下&#xff09;…