Best way to connect to multiple database in go postgress

huangapple go评论77阅读模式
英文:

Best way to connect to multiple database in go postgress

问题

我正在开发一个网站构建器,并将每个网站的数据存储在单独的数据库中。我的问题是如何正确高效地处理多个数据库连接。所有数据库和代码都在同一台服务器上。

英文:

I'm developing a website builder and store each website data in separate databases.
My question is how to handle multiple database connection properly and efficiently.
All databases and code are in same server

答案1

得分: 3

我已经创建了自己的方法来连接多个数据库。

首先,我创建了用于postgre的基本文件:

type PostgreHost struct {
    Driver   string
    Database string
    Username string
    Ssl      string
    Password string
}

type PostgreSystem interface {
    Init()
    Connect() (*sqlx.DB, error)
}

var logger *log.Logger

func (p PostgreHost) Init() {
    logger = log.New(os.Stderr,
        "Postgre",
        log.Ldate|log.Ltime|log.Lshortfile)
}

func (p *PostgreHost) Connect() (*sqlx.DB, error) {
    connection := fmt.Sprintf("user=%v password= %v dbname=%v sslmode=%v", p.Username, p.Password, p.Database, p.Ssl)
    db, err := sqlx.Connect(
        p.Driver,
        connection)
    if err != nil {
        logger.Fatal(err)
        return nil, err
    }

    return db, nil
}

func GetPostgreDb(postgre PostgreSystem) (*sqlx.DB, error) {
    return postgre.Connect()
}

然后,调用它来创建连接列表,类似于这样

// 在这里创建不同类型的数据库连接
func SystemConnection() map[string]interface{} {
    listConnection := make(map[string]interface{})
    var err error
    // 创建 Redis 连接
    redisConn := RedisHost{
        Address:  "localhost:6379",
        Password: "",
        DB:       0,
    }

    redisConnection, err := redisConn.Connect()
    if err != nil {
        panic(err)
    }

    // 创建 Postgre 连接
    postgreConn := PostgreHost{
        Driver:   "postgres",
        Database: "postgres",
        Username: "postgres",
        Ssl:      "disable",
        Password: "root",
    }
    // 在这里可以创建另一个连接:
    postgreConn2 := PostgreHost{
        Driver:   "postgres",
        Database: "postgres",
        Username: "postgres",
        Ssl:      "disable",
        Password: "root",
    }

    postgreConnection, err := GetPostgreDb(&postgreConn)

    if err != nil {
        panic(err)
    }

    postgreConnection2, err := GetPostgreDb(&postgreConn2)

    if err != nil {
        panic(err)
    }

    listConnection["redis"] = redisConnection
    listConnection["postgre"] = postgreConnection
    listConnection["postgre2"] = postgreConnection2
    return listConnection
}

最后,从映射中调用所有连接:

// 获取所有连接的列表
listConnection := database.SystemConnection()

// 获取 Redis 连接并将其转换为 *redisClient
redisConn := listConnection["redis"].(*redis.Client)

// 获取 Postgre 连接
postgreConn := listConnection["postgre"].(*sqlx.DB)
postgreConn2 := listConnection["postgre2"].(*sqlx.DB)

你可以从这里获取所有源代码。它仍在进行中,但希望能给你一个思路。希望能帮到你。

英文:

I have create my own way to connect to multiple connection database.

first I create the base file for postgre :

type PostgreHost struct {
	Driver   string
	Database string
	Username string
	Ssl      string
	Password string
}

type PostgreSystem interface {
	Init()
	Connect() (*sqlx.DB, error)
}

var logger *log.Logger

func (p PostgreHost) Init() {
	logger = log.New(os.Stderr,
		"Postgre",
		log.Ldate|log.Ltime|log.Lshortfile)
}

func (p *PostgreHost) Connect() (*sqlx.DB, error) {
	connection := fmt.Sprintf("user=%v password= %v dbname=%v sslmode=%v", p.Username, p.Password, p.Database, p.Ssl)
	db, err := sqlx.Connect(
		p.Driver,
		connection)
	if err != nil {
		logger.Fatal(err)
		return nil, err
	}

	return db, nil
}

func GetPostgreDb(postgre PostgreSystem) (*sqlx.DB, error) {
	return postgre.Connect()
}

and then call it to create list of the connection like this :

//we create different types of databse connection here
func SystemConnection() map[string]interface{} {
	listConnection := make(map[string]interface{})
	var err error
	// create redis connection
	redisConn := RedisHost{
		Address:  "localhost:6379",
		Password: "",
		DB:       0,
	}

	redisConnection, err := redisConn.Connect()
	if err != nil {
		panic(err)
	}

	// create postgre connection
	postgreConn := PostgreHost{
		Driver:   "postgres",
		Database: "postgres",
		Username: "postgres",
		Ssl:      "disable",
		Password: "root",
	}
   // you can create your another connection here : 
   postgreConn2 := PostgreHost{
		Driver:   "postgres",
		Database: "postgres",
		Username: "postgres",
		Ssl:      "disable",
		Password: "root",
	}

	postgreConnection, err := GetPostgreDb(&postgreConn)

	if err != nil {
		panic(err)
	}

    postgreConnection2, err := GetPostgreDb(&postgreConn2)
    
    if err != nil {
		panic(err)
	}
	
    listConnection["redis"] = redisConnection
	listConnection["postgre"] = postgreConnection
    listConnection["postgre2"] = postgreConnection2
	return listConnection
}

and finally call all the connection from the map :

    //getting list of all the connection.
	listConnection := database.SystemConnection()

	//getting redis connection convert it from interface to *redisClient.
	redisConn := listConnection["redis"].(*redis.Client)

	// get postgre connection.
	postgreConn := listConnection["postgre"].(*sqlx.DB)
	postgreConn2 := listConnection["postgre2"].(*sqlx.DB)

you can get all the source code from here. it still on progress but hopefully you can get the idea. Hope it helps.

答案2

得分: 2

  • 有一个上下文结构体来表示一个站点。
  • 这个上下文结构体保存了一个数据库连接。
  • 当用户登录时,还要设置他/她所属的活跃站点(我假设一个用户账户可以有多个站点)。
  • 当用户访问服务器时,检查cookie以获取站点信息。
  • 谨慎使用互斥锁,根据从cookie中获取的站点名称,从全局列表/映射(映射可以是map[string]Context)中获取上下文。
  • 如果上下文不存在,则实例化一个。在内部,它会根据站点创建与适当表格的数据库连接,并将自身注册到全局列表中(使用互斥锁)。
  • 在每个上下文实例中,设置一个定时器,用于一定时间后重置。当定时器超时(即一定时间内未被访问),或者最后一个拥有该站点的用户退出登录时,它将从全局列表中移除自身(再次使用互斥锁),并关闭与数据库的连接。
英文:
  • Have a context struct to represent a site
  • This context struct holds a DB connection
  • When a user logged in, also set which site is active for him / her (I assume that a user account can have more than one sites).
  • When the user accesses the server, check the cookie for the site
  • Carefully use mutex to get the context from global list / map (map would be map[string]Context) based on the site name obtained from the cookie.
  • If the context doesn't exist, instantiate one. Internally, it creates a connection to the DB to the appropriate table for the site and registers itself to the global list (use mutex).
  • In each context instance, have a timer for certain minutes which resets when accessed. When it timed out (i.e., when it's not accessed for certain minutes), or the last user who owns the site logged out, it will remove itself from global list (again, use mutex) and drop its DB connection.

huangapple
  • 本文由 发表于 2017年1月17日 22:25:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/41699630.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定