当前位置: 首页 > news >正文

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
}

相关文章:

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?小编这里写一个详细图文教程吧&#xff01…...

chatGPT-对话柏拉图

引言: 古希腊哲学家柏拉图,在他的众多著作中,尤以《理想国》为人所熟知。在这部杰作中,他勾勒了一个理想的政治制度,提出了各种政体,并阐述了他对于公正、智慧以及政治稳定的哲学观点。然而,其…...

Java项目-苍穹外卖-Day04

公共字段自动填充 这些字段在每张表基本都有,手动进行填充效率低,且后期维护更改繁琐 使用到注解AOP主要 先答应一个AutoFill注解 再定义一个切面类进行通知 对应代码 用到了枚举类和反射 package com.sky.aspect; /*** 自定义切面类&#xff0c…...

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的名字和密码,就会提示【您的身份验证…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​:Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...

深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏

一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

DiscuzX3.5发帖json api

参考文章&#xff1a;PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下&#xff0c;适配我自己的需求 有一个站点存在多个采集站&#xff0c;我想通过主站拿标题&#xff0c;采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...