英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论