golang 分布式微服务DAO层构建
构建云原生项目的dao层
配置读写分离的mysql集群
1. 编写yml配置文件
搭建一主二从的mysql集群、单机redis
db.yml
mysql:source: # 主数据库driverName: mysqlhost: 127.0.0.1port: 3309database: db_tiktokusername: tiktokDBpassword: tiktokDBcharset: utf8mb4replica1: # 从数据库driverName: mysqlhost: 127.0.0.1port: 3310database: db_tiktokusername: tiktokDBpassword: tiktokDBcharset: utf8mb4replica2: # 从数据库driverName: mysqlhost: 127.0.0.1port: 3311database: db_tiktokusername: tiktokDBpassword: tiktokDBcharset: utf8mb4redis:addr: 127.0.0.1port: 6379password: 123456db: 0 # 数据库编号
2. 使用viper,读对应yml文件,保存到生成的对象中
var (_db *gorm.DBconfig = viper.Init("db")zapLogger = zap.InitLogger()
)
其中viper init方法的逻辑如下:
// Init 初始化Viper配置
func Init(configName string) Config {config := Config{Viper: V.New()}v := config.Viperv.SetConfigType("yml") //设置配置文件类型v.SetConfigName(configName)//设置配置文件搜索路径v.AddConfigPath("./config") //设置配置文件路径 !!!注意路径问题v.AddConfigPath("../config")v.AddConfigPath("../../config")//读取配置文件的内容if err := v.ReadInConfig(); err != nil {//global.SugarLogger.Fatalf("read config files failed,errors is %+v", err)log.Fatalf("errno is %+v", err)}return config
}
3. 从viper的config中,构建目标数据库的dsn
func getDsn(driverWithRole string) string {username := config.Viper.GetString(fmt.Sprintf("%s.username", driverWithRole))password := config.Viper.GetString(fmt.Sprintf("%s.password", driverWithRole))host := config.Viper.GetString(fmt.Sprintf("%s.host", driverWithRole))port := config.Viper.GetInt(fmt.Sprintf("%s.port", driverWithRole))Dbname := config.Viper.GetString(fmt.Sprintf("%s.database", driverWithRole))// data source namedsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, host, port, Dbname)return dsn
}
例如现在要获取mysql “一主二从” 的主机dsn:
dsn1 := getDsn("mysql.source")
4. 拿到dsn之后,可以使用gorm连接数据库
将一主二从都连接上
var err error_db, err = gorm.Open(mysql.Open(dsn1), &gorm.Config{Logger: logger.Default.LogMode(logger.Info),PrepareStmt: true,SkipDefaultTransaction: true,})if err != nil {panic(err.Error())}dsn2 := getDsn("mysql.replica1")dsn3 := getDsn("mysql.replica2")
5. 配置mysql数据库读写分离
- dbresolver 的作用是将数据库的读写操作分发到不同的数据库实例上。在配置中,Sources 字段表示主数据库(写操作)的连接信息,Replicas 字段表示从数据库(读操作)的连接信息。通过配置这些连接信息,dbresolver 可以根据一定的策略将读操作分发到从数据库实例上,以减轻主数据库的读压力,提高系统的并发性能。
- 代码中,Sources 设置了一个主数据库连接,Replicas 则设置了两个从数据库连接。这样 dbresolver 就知道在进行数据库操作时应该选择主数据库还是从数据库。同时,Policy 字段指定了负载均衡策略,这里采用的是随机策略即 RandomPolicy。最后,TraceResolverMode 字段表示是否在日志中打印数据库的主从模式,对于调试和跟踪非常有用。
// 配置dbresolver_db.Use(dbresolver.Register(dbresolver.Config{// use `db1` as sources, `db2` as replicasSources: []gorm.Dialector{mysql.Open(dsn1)},Replicas: []gorm.Dialector{mysql.Open(dsn2), mysql.Open(dsn3)},// sources/replicas load balancing policyPolicy: dbresolver.RandomPolicy{},// print sources/replicas mode in loggerTraceResolverMode: false,}))
6. 创建表
// AutoMigrate会创建表,缺失的外键,约束,列和索引。如果大小,精度,是否为空,可以更改,则AutoMigrate会改变列的类型。出于保护您数据的目的,它不会删除未使用的列// 刷新数据库的表格,使其保持最新。即如果我在旧表的基础上增加一个字段age,那么调用autoMigrate后,旧表会自动多出一列age,值为空if err := _db.AutoMigrate(&User{}, &Video{}, &Comment{}, &FavoriteVideoRelation{}, &FollowRelation{}, &Message{}, &FavoriteCommentRelation{}); err != nil {zapLogger.Fatalln(err.Error())}
整体代码
var (_db *gorm.DBconfig = viper.Init("db")zapLogger = zap.InitLogger()
)func getDsn(driverWithRole string) string {username := config.Viper.GetString(fmt.Sprintf("%s.username", driverWithRole))password := config.Viper.GetString(fmt.Sprintf("%s.password", driverWithRole))host := config.Viper.GetString(fmt.Sprintf("%s.host", driverWithRole))port := config.Viper.GetInt(fmt.Sprintf("%s.port", driverWithRole))Dbname := config.Viper.GetString(fmt.Sprintf("%s.database", driverWithRole))// data source namedsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, host, port, Dbname)return dsn
}func init() {zapLogger.Info("Redis server connection successful!")dsn1 := getDsn("mysql.source")var err error_db, err = gorm.Open(mysql.Open(dsn1), &gorm.Config{Logger: logger.Default.LogMode(logger.Info),PrepareStmt: true,SkipDefaultTransaction: true,})if err != nil {panic(err.Error())}dsn2 := getDsn("mysql.replica1")dsn3 := getDsn("mysql.replica2")// 配置dbresolver_db.Use(dbresolver.Register(dbresolver.Config{// use `db1` as sources, `db2` as replicasSources: []gorm.Dialector{mysql.Open(dsn1)},Replicas: []gorm.Dialector{mysql.Open(dsn2), mysql.Open(dsn3)},// sources/replicas load balancing policyPolicy: dbresolver.RandomPolicy{},// print sources/replicas mode in loggerTraceResolverMode: false,}))// AutoMigrate会创建表,缺失的外键,约束,列和索引。如果大小,精度,是否为空,可以更改,则AutoMigrate会改变列的类型。出于保护您数据的目的,它不会删除未使用的列// 刷新数据库的表格,使其保持最新。即如果我在旧表的基础上增加一个字段age,那么调用autoMigrate后,旧表会自动多出一列age,值为空if err := _db.AutoMigrate(&User{}, &Video{}, &Comment{}, &FavoriteVideoRelation{}, &FollowRelation{}, &Message{}, &FavoriteCommentRelation{}); err != nil {zapLogger.Fatalln(err.Error())}db, err := _db.DB()if err != nil {zapLogger.Fatalln(err.Error())}db.SetMaxOpenConns(100)db.SetMaxIdleConns(20)
}func GetDB() *gorm.DB {return _db
}
相关文章:
golang 分布式微服务DAO层构建
构建云原生项目的dao层 配置读写分离的mysql集群 1. 编写yml配置文件 搭建一主二从的mysql集群、单机redis db.yml mysql:source: # 主数据库driverName: mysqlhost: 127.0.0.1port: 3309database: db_tiktokusername: tiktokDBpassword: tiktokDBcharset: utf8mb4replica1…...

Java 项目日志实例:LogBack
点击下方关注我,然后右上角点击...“设为星标”,就能第一时间收到更新推送啦~~~ LogBack 和 Log4j 都是开源日记工具库,LogBack 是 Log4j 的改良版本,比 Log4j 拥有更多的特性,同时也带来很大性能提升。LogBack 官方建…...

什么是条件get方法?
条件GET方法通常指的是HTTP协议中的"GET"请求,但它带有一些条件,这些条件用于控制服务器是否应该返回请求的资源。这些条件通常使用HTTP标头字段来指定,以便客户端可以告诉服务器在某些条件下是否需要新的或更新的资源。 条件GET方…...
Python爬虫——scrapy_crawlspider读书网
创建crawlspider爬虫文件: scrapy genspider -t crawl 爬虫文件名 爬取的域名scrapy genspider -t crawl read https://www.dushu.com/book/1206.htmlLinkExtractor 链接提取器通过它,Spider可以知道从爬取的页面中提取出哪些链接,提取出的链…...

Spring源码编译-for mac
超详细的spring源码编译 记:编译成功时间:2023.08.19 环境准备: 1.idea 2023.1.1 Community Edition 2.jdk1.8 3.gradlegradle-5.6.4 4.spring源码(版本:spring-framework-v5.2.25.RELEASE) 一.spring源码下载 github 加速网站&…...

视频汇聚平台EasyCVR安防监控视频汇聚平台的FLV视频流在VLC中无法播放的问题解决方案
众所周知,TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入,包括主流标准协议国标GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。在视频流的处理与分发上,视频监控…...
中间件:RocketMQ安装部署
单机部署 下载 cd /opt/soft/archive wget https://archive.apache.org/dist/rocketmq/4.9.4/rocketmq-all-4.9.4-bin-release.zip unzip -d ../ rocketmq-all-4.9.4-bin-release.zip配置 broker.conf 的brokerIP1 为公网ip 启动命令: nohup sh bin/mqnamesrv &a…...
leetcode-动态规划-42-接雨水
题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1…...
[静态时序分析简明教程(十一)]浅议tcl语言
静态时序分析简明教程-浅议tcl语言 一、写在前面1.1 快速导航链接 二、Tcl基础知识三、Tcl的语言结构3.1 Tcl变量3.2 Tcl表达式与运算符3.3 Tcl的控制流语句3.3.1 列表遍历3.3.2 决策3.3.3 Tcl循环3.3.4 Tcl过程 3.4 其他Tcl命令3.4.1 open/close3.4.2 gets/puts3.4.3 catch3.4…...
大数据-玩转数据-Flink 网站UV统计
一、说明 在实际应用中,我们往往会关注,到底有多少不同的用户访问了网站,所以另外一个统计流量的重要指标是网站的独立访客数(Unique Visitor,UV)。 二、数据准备 package com.lyh.flink06;import lombo…...
3分钟了解下cwnd和TCP拥塞控制算法
文章首发地址 cwnd是什么? cwnd是TCP拥塞控制中的一个重要概念,全称为“congestion window”,也被称为拥塞窗口。它用于限制发送方向网络发送数据的速度,以避免网络拥塞。cwnd是一个动态的值,可以根据网络状况动态调…...

设计模式之状态模式(State)的C++实现
1、状态模式的提出 在组件功能开发过程中,某些对象的状态经常面临变化,不同的状态,其对象的操作行为不同。比如根据状态写的if else条件情况,且这种条件变化是经常变化的,这样的代码不易维护。可以使用状态模式解决这…...

无涯教程-TensorFlow - Keras
Keras易于学习的高级Python库,可在TensorFlow框架上运行,它的重点是理解深度学习技术,如为神经网络创建层,以维护形状和数学细节的概念。框架的创建可以分为以下两种类型- 顺序API功能API 无涯教程将使用Jupyter Notebook执行和…...

使用SSH隧道将Ubuntu云服务器Jupyter Notebook端口映射到本地
本文主要实现了在Ubuntu云服务器后台运行Jupyter Notebook,并使用SSH隧道将服务器端口映射到本地 1. 生成配置文件 运行以下命令生成Jupyter Notebook的配置文件: jupyter notebook --generate-config这将在用户主目录下生成一个名为.jupyter的文件夹&…...
Keepalived+LVS部署高可用集群
文章目录 KeepalivedLVS(DR)部署高可用Web集群集群环境MASTER配置BACKUP配置检查Virtual IP是否漂移IPVS检查MASTERBACKUP Real Server配置附上个人写的小脚本 测试停用Real Server某一台的Apache服务停用Master上的keepalived检测Backup是否接管资源 KeepalivedLVS(DR)部署高可…...

2023河南萌新联赛第(五)场:郑州轻工业大学
A.买爱心气球 原题链接 : 登录—专业IT笔试面试备考平台_牛客网 博弈论 : #include <iostream> using namespace std; int t,n,m; string s1 "Alice",s2 "Bob"; int main() {cin>>t;while(t--){cin>>n>>m;if (n % 3 0) {cou…...

在Orangepi5开发板3588s使用opencv获取摄像头画面
先感谢香橙派群的管理员耐心指导,经过不断的调试修改最后成功通过opencv调用mipi摄像头获取画面 就记录分享一下大概步骤希望大家少踩点坑!!!!!! 我用的固件系统是ubuntu2022.0.4 固件是&#x…...
音视频 ffmpeg命令分类查询
命令参数内容-version显示版本 -bsfs 显示可用比特流filter-buildconf显示编译配置-formats显示可用格式(muxersdemuxers)-muxers显示可用复用器-demuxers显示可用解复用器-codecs显示可用编解码器(decodersencoders)-decoders显示可用解码器-encoders显示可用编码器-bsfs显示可…...

VSCode无法从Extensions下载工具时,把工具下载到本地并添加到VSCode编辑器
从VSCode 的 Extensions 下载 下载报错:Error while installing ...... extension. Please check the log for more details. 由于内网限制(或者其他网络限制)无法正常下载扩展工具到VSCode编辑器,可以把工具下载到本地再添加到V…...

WebStrom 前端项目Debug
1. 正常启动前端项目 2. 配置webStrom的JavaScript Debugger 点击Edit Configurations添加avaScript Debug填写URL 为项目启动路径配置要Debug的浏览器-remote-allow-origins* (最重要,否则唤起的是一个about:blank空白页面) 3. 启动Debug模…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...