-1

[Golang] Chiến Lược Quản Lý Kết Nối Database Thông Qua Gorm

Nói đến Gorm chắc đa số các bạn develop Golang điều biết, nhưng hôm nay mình giới thiệu cách để quản lý kết nối đến database ( không đề cập đến connection pool)

Có 2 cách để connect đến Gorm:

Cách 1

  1. đoạn mã code.
type (
    dbInstance struct {
		db    *gorm.DB
	}
)

func NewDBInstanceRepository(db *gorm.DB) *dbInstance {
	return &dbInstance{
		db: db,
	}
}

func (l *dbInstance) getDB() *gorm.DB {
	return l.db
}

  1. Giải thích:
  • Định nghĩa dbInstance,
    • dbInstance là một struct có một trường db kiểu *gorm.DB, biểu thị một kết nối đến cơ sở dữ liệu.
  • Hàm NewDBInstanceRepository:
    • Hàm này là một constructor để khởi tạo một instance của dbInstance.
    • Nó nhận một tham số *gorm.DB (kết nối cơ sở dữ liệu) và trả về một con trỏ của dbInstance.
  • Hàm getDB:
    • Đây là một getter để truy xuất đối tượng *gorm.DB từ dbInstance.
  1. Công dụng:
  • Đoạn mã này giúp đóng gói kết nối cơ sở dữ liệu (*gorm.DB) vào một struct, đồng thời cung cấp phương pháp truy cập qua hàm getDB. Đây là cách tiếp cận đơn giản và thường dùng khi bạn muốn quản lý kết nối cơ sở dữ liệu trong một phạm vi hẹp.

Cách 2

  1. Code:

var dbs sync.Map

type DB struct {
	*gorm.DB
}
type DBConf struct {
	Driver   string `yaml:"Driver"`
	Host     string `yaml:"Host"`
	Port     int64  `yaml:"Port"`
	User     string `yaml:"User"`
	Password string `yaml:"Password"`
	Db       string `yaml:"Db"`
	Schema   string `yaml:"Schema"`
}
// DbGet get db connection for specified conf
func DbGet(conf DBConf, ops ...func(*gorm.DB)) *DB {
	dsn := "config url"
	db, ok := dbs.Load(dsn)
	if !ok {
		logger.Infof("connecting '%s' '%s' '%s' '%d' '%s'", conf.Driver, conf.Host, conf.User, conf.Port, conf.Db)
		db1, err := gorm.Open(getGormDialetor(conf.Driver, dsn), &gorm.Config{
		})
		dtmimp.E2P(err)
		err = db1.Use(&tracePlugin{})
		dtmimp.E2P(err)
		db = &DB{DB: db1}
		for _, op := range ops {
			op(db1)
		}
		dbs.Store(dsn, db)
	}
	return db.(*DB)
}
  1. Giải thích:
  • Sử dụng sync.Map:
    • sync.Map là một cấu trúc dữ liệu thread-safe cho việc lưu trữ các kết nối cơ sở dữ liệu (DB) theo khóa dsn (Data Source Name).
    • Điều này đảm bảo việc truy cập/kết nối là an toàn khi có nhiều goroutines.
  • Struct DB:
    • DB là một wrapper cho *gorm.DB.
  • Hàm DbGet:
    • Nhận cấu hình cơ sở dữ liệu conf kiểu DBConf và một số thao tác bổ sung (qua ops).
    • Tạo dsn từ cấu hình thông qua dtmimp.GetDsn.
    • Kiểm tra xem kết nối với dsn đã tồn tại trong sync.Map chưa.
      • Nếu chưa, nó sẽ:
      • Kết nối cơ sở dữ liệu qua gorm.Open.
      • Lưu kết nối này vào sync.Map.
    • Nếu đã tồn tại, lấy kết nối ra và trả về.
  1. Công dụng:
  • Đảm bảo mỗi dsn chỉ có một kết nối duy nhất (Singleton pattern).
  • Hỗ trợ thread-safe khi sử dụng trong các ứng dụng đa luồng hoặc microservices.
  • Tiện lợi khi cần sử dụng nhiều kết nối cơ sở dữ liệu với các cấu hình khác nhau.

So sánh và ứng dụng:

Đặc điểm Code 1 Code 2
Mục tiêu Quản lý đơn giản một kết nối cơ sở dữ liệu. Quản lý nhiều kết nối cơ sở dữ liệu.
Phạm vi sử dụng Ứng dụng nhỏ, ít kết nối. Ứng dụng lớn, nhiều kết nối, đa luồng.
Quản lý kết nối Không có quản lý đồng bộ (thread-safe). Đồng bộ qua sync.Map.
Phức tạp Đơn giản, dễ hiểu. Phức tạp hơn do xử lý nhiều kết nối
  • Tùy vào nhu cầu, bạn chọn cách tiếp cận phù hợp. Code 1 thích hợp cho ứng dụng nhỏ gọn, trong khi Code 2 tối ưu cho các hệ thống phức tạp và yêu cầu đồng bộ cao.

All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.