我是靠谱客的博主 名字长了才好记,最近开发中收集的这篇文章主要介绍golang实现一个mysql连接池, 用户数据根据id余数分散保存到固定的数据库的固定分表中,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

要在每个数据库内再分表,且根据算法决定将数据存储在指定的数据库和表中,我们需要做以下调整:

  1. 选择数据库和表: 除了根据用户 ID 选择数据库外,还要根据用户 ID 的余数选择数据库中的表。

  2. 表的命名策略: 为了简化,我们假设每个数据库中有多个表,表名可以通过用户 ID 的余数来决定。例如:users_0, users_1, users_2 等。

解决方案设计

  1. 数据库选择: 使用 userID % len(dbConfigs) 来决定数据库。

  2. 表选择: 使用 userID % len(tables) 来决定表,在每个数据库中都有若干个表(例如 users_0, users_1, users_2)。

  3. 修改 ORM 模型: 根据选择的表来操作数据。

代码实现

主要修改:

  • 通过用户 ID 的余数来决定 数据库

  • 使用 gormTable 方法来动态指定表。

完整代码示例

package main

import (
	"fmt"
	"log"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"github.com/gin-gonic/gin"
	"strconv"
)

var dbPools map[int]*gorm.DB

// 数据库配置,假设有3个数据库
var dbConfigs = []string{
	"root:password@tcp(127.0.0.1:3306)/db1?charset=utf8mb4&parseTime=True&loc=Local",
	"root:password@tcp(127.0.0.1:3306)/db2?charset=utf8mb4&parseTime=True&loc=Local",
	"root:password@tcp(127.0.0.1:3306)/db3?charset=utf8mb4&parseTime=True&loc=Local",
}

// 每个数据库有3个表
var tableCount = 3

// 初始化数据库连接池
func initDBPools() {
	dbPools = make(map[int]*gorm.DB)

	for i, dbConfig := range dbConfigs {
		db, err := gorm.Open(mysql.Open(dbConfig), &gorm.Config{})
		if err != nil {
			log.Fatalf("failed to connect to database %d: %v", i, err)
		}
		dbPools[i] = db
	}
}

// 选择数据库,根据用户 ID 的余数
func getDatabaseByUserID(userID int) *gorm.DB {
	dbIndex := userID % len(dbConfigs)
	return dbPools[dbIndex]
}

// 选择表,根据用户 ID 的余数
func getTableNameByUserID(userID int) string {
	tableIndex := userID % tableCount
	return fmt.Sprintf("users_%d", tableIndex)
}

// 用户数据结构体
type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func main() {
	// 初始化数据库连接池
	initDBPools()

	// 创建 Gin 路由
	r := gin.Default()

	// 路由:根据用户 ID 获取用户信息
	r.GET("/user/:id", func(c *gin.Context) {
		userID, err := strconv.Atoi(c.Param("id"))
		if err != nil {
			c.JSON(400, gin.H{"error": "Invalid user ID"})
			return
		}

		// 选择数据库
		db := getDatabaseByUserID(userID)

		// 根据 ID 选择表
		tableName := getTableNameByUserID(userID)

		var user User
		// 使用 Table() 方法动态指定表
		if err := db.Table(tableName).First(&user, userID).Error; err != nil {
			c.JSON(404, gin.H{"error": "User not found"})
			return
		}

		c.JSON(200, user)
	})

	// 路由:添加用户
	r.POST("/user", func(c *gin.Context) {
		var user User
		if err := c.ShouldBindJSON(&user); err != nil {
			c.JSON(400, gin.H{"error": "Invalid input"})
			return
		}

		// 选择数据库
		db := getDatabaseByUserID(user.ID)

		// 根据 ID 选择表
		tableName := getTableNameByUserID(user.ID)

		// 使用 Table() 方法动态指定表
		if err := db.Table(tableName).Create(&user).Error; err != nil {
			c.JSON(500, gin.H{"error": "Failed to create user"})
			return
		}

		c.JSON(201, gin.H{"message": "User created successfully"})
	})

	// 启动服务
	r.Run(":8080")
}

数据库和表设计

假设你有 3 个数据库:db1, db2, db3,每个数据库有 3 个表:users_0, users_1, users_2

每个表结构一样,示例表结构:

CREATE TABLE users_0 (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);

CREATE TABLE users_1 (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);

CREATE TABLE users_2 (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);

测试

  1. 插入用户
    使用 POST 请求插入用户数据,数据会根据 userID 的余数自动分配到正确的数据库和表中。

POST /user
{
    "id": 1,
    "name": "Alice"
}
  1. 用户 ID 为 1,假设余数分配为 db1users_1,数据就会保存到 db1.users_1 中。

  2. 查询用户
    使用 GET /user/1 查询 ID 为 1 的用户,系统会根据 ID 计算到正确的数据库和表来查询。

总结

这种方式能够根据用户的 ID 动态地选择数据库和表,并且通过 Gin 提供 API 进行用户信息的增删改查操作。通过余数算法,可以均匀地将数据分布到不同的数据库和表中,避免单个数据库的压力过大。


最后

以上就是名字长了才好记为你收集整理的golang实现一个mysql连接池, 用户数据根据id余数分散保存到固定的数据库的固定分表中的全部内容,希望文章能够帮你解决golang实现一个mysql连接池, 用户数据根据id余数分散保存到固定的数据库的固定分表中所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(115)

评论列表共有 0 条评论

立即
投稿
返回
顶部