Changing read replica selection method to round-robin instead of random. (#4351)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
f82667f3b8
Коммит
55803ebcc8
@@ -15,14 +15,15 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
l4g "github.com/alecthomas/log4go"
|
|
||||||
"io"
|
"io"
|
||||||
sqltrace "log"
|
sqltrace "log"
|
||||||
"math/rand"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
l4g "github.com/alecthomas/log4go"
|
||||||
|
|
||||||
"github.com/go-gorp/gorp"
|
"github.com/go-gorp/gorp"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
@@ -84,10 +85,13 @@ type SqlStore struct {
|
|||||||
status StatusStore
|
status StatusStore
|
||||||
fileInfo FileInfoStore
|
fileInfo FileInfoStore
|
||||||
SchemaVersion string
|
SchemaVersion string
|
||||||
|
rrCounter int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func initConnection() *SqlStore {
|
func initConnection() *SqlStore {
|
||||||
sqlStore := &SqlStore{}
|
sqlStore := &SqlStore{
|
||||||
|
rrCounter: 0,
|
||||||
|
}
|
||||||
|
|
||||||
sqlStore.master = setupConnection("master", utils.Cfg.SqlSettings.DriverName,
|
sqlStore.master = setupConnection("master", utils.Cfg.SqlSettings.DriverName,
|
||||||
utils.Cfg.SqlSettings.DataSource, utils.Cfg.SqlSettings.MaxIdleConns,
|
utils.Cfg.SqlSettings.DataSource, utils.Cfg.SqlSettings.MaxIdleConns,
|
||||||
@@ -205,11 +209,11 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle
|
|||||||
return dbmap
|
return dbmap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) TotalMasterDbConnections() int {
|
func (ss *SqlStore) TotalMasterDbConnections() int {
|
||||||
return ss.GetMaster().Db.Stats().OpenConnections
|
return ss.GetMaster().Db.Stats().OpenConnections
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) TotalReadDbConnections() int {
|
func (ss *SqlStore) TotalReadDbConnections() int {
|
||||||
|
|
||||||
if len(utils.Cfg.SqlSettings.DataSourceReplicas) == 0 {
|
if len(utils.Cfg.SqlSettings.DataSourceReplicas) == 0 {
|
||||||
return 0
|
return 0
|
||||||
@@ -225,12 +229,12 @@ func (ss SqlStore) TotalReadDbConnections() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) GetCurrentSchemaVersion() string {
|
func (ss *SqlStore) GetCurrentSchemaVersion() string {
|
||||||
version, _ := ss.GetMaster().SelectStr("SELECT Value FROM Systems WHERE Name='Version'")
|
version, _ := ss.GetMaster().SelectStr("SELECT Value FROM Systems WHERE Name='Version'")
|
||||||
return version
|
return version
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) MarkSystemRanUnitTests() {
|
func (ss *SqlStore) MarkSystemRanUnitTests() {
|
||||||
if result := <-ss.System().Get(); result.Err == nil {
|
if result := <-ss.System().Get(); result.Err == nil {
|
||||||
props := result.Data.(model.StringMap)
|
props := result.Data.(model.StringMap)
|
||||||
unitTests := props[model.SYSTEM_RAN_UNIT_TESTS]
|
unitTests := props[model.SYSTEM_RAN_UNIT_TESTS]
|
||||||
@@ -241,7 +245,7 @@ func (ss SqlStore) MarkSystemRanUnitTests() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) DoesTableExist(tableName string) bool {
|
func (ss *SqlStore) DoesTableExist(tableName string) bool {
|
||||||
if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
|
if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
|
||||||
count, err := ss.GetMaster().SelectInt(
|
count, err := ss.GetMaster().SelectInt(
|
||||||
`SELECT count(relname) FROM pg_class WHERE relname=$1`,
|
`SELECT count(relname) FROM pg_class WHERE relname=$1`,
|
||||||
@@ -286,7 +290,7 @@ func (ss SqlStore) DoesTableExist(tableName string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool {
|
func (ss *SqlStore) DoesColumnExist(tableName string, columnName string) bool {
|
||||||
if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
|
if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
|
||||||
count, err := ss.GetMaster().SelectInt(
|
count, err := ss.GetMaster().SelectInt(
|
||||||
`SELECT COUNT(0)
|
`SELECT COUNT(0)
|
||||||
@@ -341,7 +345,7 @@ func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, mySqlColType string, postgresColType string, defaultValue string) bool {
|
func (ss *SqlStore) CreateColumnIfNotExists(tableName string, columnName string, mySqlColType string, postgresColType string, defaultValue string) bool {
|
||||||
|
|
||||||
if ss.DoesColumnExist(tableName, columnName) {
|
if ss.DoesColumnExist(tableName, columnName) {
|
||||||
return false
|
return false
|
||||||
@@ -375,7 +379,7 @@ func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool {
|
func (ss *SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool {
|
||||||
|
|
||||||
if !ss.DoesColumnExist(tableName, columnName) {
|
if !ss.DoesColumnExist(tableName, columnName) {
|
||||||
return false
|
return false
|
||||||
@@ -391,7 +395,7 @@ func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) boo
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool {
|
func (ss *SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool {
|
||||||
if !ss.DoesColumnExist(tableName, oldColumnName) {
|
if !ss.DoesColumnExist(tableName, oldColumnName) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -412,7 +416,7 @@ func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string,
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) GetMaxLengthOfColumnIfExists(tableName string, columnName string) string {
|
func (ss *SqlStore) GetMaxLengthOfColumnIfExists(tableName string, columnName string) string {
|
||||||
if !ss.DoesColumnExist(tableName, columnName) {
|
if !ss.DoesColumnExist(tableName, columnName) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -434,7 +438,7 @@ func (ss SqlStore) GetMaxLengthOfColumnIfExists(tableName string, columnName str
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) AlterColumnTypeIfExists(tableName string, columnName string, mySqlColType string, postgresColType string) bool {
|
func (ss *SqlStore) AlterColumnTypeIfExists(tableName string, columnName string, mySqlColType string, postgresColType string) bool {
|
||||||
if !ss.DoesColumnExist(tableName, columnName) {
|
if !ss.DoesColumnExist(tableName, columnName) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -455,19 +459,19 @@ func (ss SqlStore) AlterColumnTypeIfExists(tableName string, columnName string,
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) CreateUniqueIndexIfNotExists(indexName string, tableName string, columnName string) {
|
func (ss *SqlStore) CreateUniqueIndexIfNotExists(indexName string, tableName string, columnName string) {
|
||||||
ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_DEFAULT, true)
|
ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_DEFAULT, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) CreateIndexIfNotExists(indexName string, tableName string, columnName string) {
|
func (ss *SqlStore) CreateIndexIfNotExists(indexName string, tableName string, columnName string) {
|
||||||
ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_DEFAULT, false)
|
ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_DEFAULT, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) CreateFullTextIndexIfNotExists(indexName string, tableName string, columnName string) {
|
func (ss *SqlStore) CreateFullTextIndexIfNotExists(indexName string, tableName string, columnName string) {
|
||||||
ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_FULL_TEXT, false)
|
ss.createIndexIfNotExists(indexName, tableName, columnName, INDEX_TYPE_FULL_TEXT, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) createIndexIfNotExists(indexName string, tableName string, columnName string, indexType string, unique bool) {
|
func (ss *SqlStore) createIndexIfNotExists(indexName string, tableName string, columnName string, indexType string, unique bool) {
|
||||||
|
|
||||||
uniqueStr := ""
|
uniqueStr := ""
|
||||||
if unique {
|
if unique {
|
||||||
@@ -526,7 +530,7 @@ func (ss SqlStore) createIndexIfNotExists(indexName string, tableName string, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) RemoveIndexIfExists(indexName string, tableName string) {
|
func (ss *SqlStore) RemoveIndexIfExists(indexName string, tableName string) {
|
||||||
|
|
||||||
if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
|
if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
|
||||||
_, err := ss.GetMaster().SelectStr("SELECT $1::regclass", indexName)
|
_, err := ss.GetMaster().SelectStr("SELECT $1::regclass", indexName)
|
||||||
@@ -580,22 +584,23 @@ func IsUniqueConstraintError(err string, indexName []string) bool {
|
|||||||
return unique && field
|
return unique && field
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) GetMaster() *gorp.DbMap {
|
func (ss *SqlStore) GetMaster() *gorp.DbMap {
|
||||||
return ss.master
|
return ss.master
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) GetReplica() *gorp.DbMap {
|
func (ss *SqlStore) GetReplica() *gorp.DbMap {
|
||||||
return ss.replicas[rand.Intn(len(ss.replicas))]
|
rrNum := atomic.AddInt64(&ss.rrCounter, 1) % int64(len(ss.replicas))
|
||||||
|
return ss.replicas[rrNum]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) GetAllConns() []*gorp.DbMap {
|
func (ss *SqlStore) GetAllConns() []*gorp.DbMap {
|
||||||
all := make([]*gorp.DbMap, len(ss.replicas)+1)
|
all := make([]*gorp.DbMap, len(ss.replicas)+1)
|
||||||
copy(all, ss.replicas)
|
copy(all, ss.replicas)
|
||||||
all[len(ss.replicas)] = ss.master
|
all[len(ss.replicas)] = ss.master
|
||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Close() {
|
func (ss *SqlStore) Close() {
|
||||||
l4g.Info(utils.T("store.sql.closing.info"))
|
l4g.Info(utils.T("store.sql.closing.info"))
|
||||||
ss.master.Db.Close()
|
ss.master.Db.Close()
|
||||||
for _, replica := range ss.replicas {
|
for _, replica := range ss.replicas {
|
||||||
@@ -603,75 +608,75 @@ func (ss SqlStore) Close() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Team() TeamStore {
|
func (ss *SqlStore) Team() TeamStore {
|
||||||
return ss.team
|
return ss.team
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Channel() ChannelStore {
|
func (ss *SqlStore) Channel() ChannelStore {
|
||||||
return ss.channel
|
return ss.channel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Post() PostStore {
|
func (ss *SqlStore) Post() PostStore {
|
||||||
return ss.post
|
return ss.post
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) User() UserStore {
|
func (ss *SqlStore) User() UserStore {
|
||||||
return ss.user
|
return ss.user
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Session() SessionStore {
|
func (ss *SqlStore) Session() SessionStore {
|
||||||
return ss.session
|
return ss.session
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Audit() AuditStore {
|
func (ss *SqlStore) Audit() AuditStore {
|
||||||
return ss.audit
|
return ss.audit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Compliance() ComplianceStore {
|
func (ss *SqlStore) Compliance() ComplianceStore {
|
||||||
return ss.compliance
|
return ss.compliance
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) OAuth() OAuthStore {
|
func (ss *SqlStore) OAuth() OAuthStore {
|
||||||
return ss.oauth
|
return ss.oauth
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) System() SystemStore {
|
func (ss *SqlStore) System() SystemStore {
|
||||||
return ss.system
|
return ss.system
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Webhook() WebhookStore {
|
func (ss *SqlStore) Webhook() WebhookStore {
|
||||||
return ss.webhook
|
return ss.webhook
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Command() CommandStore {
|
func (ss *SqlStore) Command() CommandStore {
|
||||||
return ss.command
|
return ss.command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Preference() PreferenceStore {
|
func (ss *SqlStore) Preference() PreferenceStore {
|
||||||
return ss.preference
|
return ss.preference
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) License() LicenseStore {
|
func (ss *SqlStore) License() LicenseStore {
|
||||||
return ss.license
|
return ss.license
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) PasswordRecovery() PasswordRecoveryStore {
|
func (ss *SqlStore) PasswordRecovery() PasswordRecoveryStore {
|
||||||
return ss.recovery
|
return ss.recovery
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Emoji() EmojiStore {
|
func (ss *SqlStore) Emoji() EmojiStore {
|
||||||
return ss.emoji
|
return ss.emoji
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) Status() StatusStore {
|
func (ss *SqlStore) Status() StatusStore {
|
||||||
return ss.status
|
return ss.status
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) FileInfo() FileInfoStore {
|
func (ss *SqlStore) FileInfo() FileInfoStore {
|
||||||
return ss.fileInfo
|
return ss.fileInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss SqlStore) DropAllTables() {
|
func (ss *SqlStore) DropAllTables() {
|
||||||
ss.master.TruncateTables()
|
ss.master.TruncateTables()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user