gitee.com/curryzheng/dm@v0.0.1/zx.go (about)

     1  /*
     2   * Copyright (c) 2000-2018, 达梦数据库有限公司.
     3   * All rights reserved.
     4   */
     5  
     6  package dm
     7  
     8  import (
     9  	"gitee.com/curryzheng/dm/util"
    10  	"math/rand"
    11  	"strconv"
    12  	"time"
    13  )
    14  
    15  var rwMap = make(map[string]*rwCounter)
    16  
    17  type rwCounter struct {
    18  	ntrx_primary int64
    19  
    20  	ntrx_total int64
    21  
    22  	primaryPercent float64
    23  
    24  	standbyPercent float64
    25  
    26  	standbyNTrxMap map[string]int64
    27  
    28  	standbyIdMap map[string]int32
    29  
    30  	standbyCount int32
    31  
    32  	flag []int32
    33  
    34  	increments []int32
    35  }
    36  
    37  func newRWCounter(primaryPercent int32, standbyCount int32) *rwCounter {
    38  	rwc := new(rwCounter)
    39  	rwc.standbyNTrxMap = make(map[string]int64)
    40  	rwc.standbyIdMap = make(map[string]int32)
    41  	rwc.reset(primaryPercent, standbyCount)
    42  	return rwc
    43  }
    44  
    45  func (rwc *rwCounter) reset(primaryPercent int32, standbyCount int32) {
    46  	rwc.ntrx_primary = 0
    47  	rwc.ntrx_total = 0
    48  	rwc.standbyCount = standbyCount
    49  	rwc.increments = make([]int32, standbyCount+1)
    50  	rwc.flag = make([]int32, standbyCount+1)
    51  	var gcd = util.GCD(primaryPercent*standbyCount, 100-primaryPercent)
    52  	rwc.increments[0] = primaryPercent * standbyCount / gcd
    53  	for i, tmp := 1, (100-primaryPercent)/gcd; i < len(rwc.increments); i++ {
    54  		rwc.increments[i] = tmp
    55  	}
    56  	copy(rwc.flag, rwc.increments)
    57  
    58  	if standbyCount > 0 {
    59  		rwc.primaryPercent = float64(primaryPercent) / 100.0
    60  		rwc.standbyPercent = float64(100-primaryPercent) / 100.0 / float64(standbyCount)
    61  	} else {
    62  		rwc.primaryPercent = 1
    63  		rwc.standbyPercent = 0
    64  	}
    65  }
    66  
    67  // 连接创建成功后调用,需要服务器返回standbyCount
    68  func getRwCounterInstance(conn *DmConnection, standbyCount int32) *rwCounter {
    69  	key := conn.dmConnector.host + "_" + strconv.Itoa(int(conn.dmConnector.port)) + "_" + strconv.Itoa(int(conn.dmConnector.rwPercent))
    70  
    71  	rwc, ok := rwMap[key]
    72  	if !ok {
    73  		rwc = newRWCounter(conn.dmConnector.rwPercent, standbyCount)
    74  		rwMap[key] = rwc
    75  	} else if rwc.standbyCount != standbyCount {
    76  		rwc.reset(conn.dmConnector.rwPercent, standbyCount)
    77  	}
    78  	return rwc
    79  }
    80  
    81  /**
    82  * @return 主机;
    83   */
    84  func (rwc *rwCounter) countPrimary() RWSiteEnum {
    85  	rwc.adjustNtrx()
    86  	rwc.increasePrimaryNtrx()
    87  	return PRIMARY
    88  }
    89  
    90  /**
    91  * @param dest 主机; 备机; any;
    92  * @return 主机; 备机
    93   */
    94  func (rwc *rwCounter) count(dest RWSiteEnum, standby *DmConnection) RWSiteEnum {
    95  	rwc.adjustNtrx()
    96  	switch dest {
    97  	case ANYSITE:
    98  		{
    99  			if rwc.primaryPercent == 1 || (rwc.flag[0] > rwc.getStandbyFlag(standby) && rwc.flag[0] > util.Sum(rwc.flag[1:])) {
   100  				rwc.increasePrimaryNtrx()
   101  				dest = PRIMARY
   102  			} else {
   103  				rwc.increaseStandbyNtrx(standby)
   104  				dest = STANDBY
   105  			}
   106  		}
   107  	case STANDBY:
   108  		{
   109  			rwc.increaseStandbyNtrx(standby)
   110  		}
   111  	case PRIMARY:
   112  		{
   113  			rwc.increasePrimaryNtrx()
   114  		}
   115  	}
   116  	return dest
   117  }
   118  
   119  /**
   120  * 防止ntrx超出有效范围,等比调整
   121   */
   122  func (rwc *rwCounter) adjustNtrx() {
   123  	if rwc.ntrx_total >= INT64_MAX {
   124  		var min int64
   125  		var i = 0
   126  		for _, num := range rwc.standbyNTrxMap {
   127  			if i == 0 || num < min {
   128  				min = num
   129  			}
   130  			i++
   131  		}
   132  		if rwc.ntrx_primary < min {
   133  			min = rwc.ntrx_primary
   134  		}
   135  		rwc.ntrx_primary /= min
   136  		rwc.ntrx_total /= min
   137  		for k, v := range rwc.standbyNTrxMap {
   138  			rwc.standbyNTrxMap[k] = v / min
   139  		}
   140  	}
   141  
   142  	if rwc.flag[0] <= 0 && util.Sum(rwc.flag[1:]) <= 0 {
   143  		// 如果主库事务数以及所有备库事务数的总和 都 <= 0, 重置事务计数,给每个库的事务计数加上初始计数值
   144  		for i := 0; i < len(rwc.flag); i++ {
   145  			rwc.flag[i] += rwc.increments[i]
   146  		}
   147  	}
   148  }
   149  
   150  func (rwc *rwCounter) increasePrimaryNtrx() {
   151  	rwc.ntrx_primary++
   152  	rwc.flag[0]--
   153  	rwc.ntrx_total++
   154  }
   155  
   156  //func (rwc *rwCounter) getStandbyNtrx(standby *DmConnection) int64 {
   157  //	key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port))
   158  //	ret, ok := rwc.standbyNTrxMap[key]
   159  //	if !ok {
   160  //		ret = 0
   161  //	}
   162  //
   163  //	return ret
   164  //}
   165  
   166  func (rwc *rwCounter) getStandbyId(standby *DmConnection) int32 {
   167  	key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port))
   168  	sid, ok := rwc.standbyIdMap[key]
   169  	if !ok {
   170  		sid = int32(len(rwc.standbyIdMap) + 1) // 下标0是primary
   171  		if sid > rwc.standbyCount {
   172  			// 不在有效备库中
   173  			return -1
   174  		}
   175  		rwc.standbyIdMap[key] = sid
   176  	}
   177  	return sid
   178  }
   179  
   180  func (rwc *rwCounter) getStandbyFlag(standby *DmConnection) int32 {
   181  	sid := rwc.getStandbyId(standby)
   182  	if sid > 0 && sid < int32(len(rwc.flag)) {
   183  		// 保证备库有效
   184  		return rwc.flag[sid]
   185  	}
   186  	return 0
   187  }
   188  
   189  func (rwc *rwCounter) increaseStandbyNtrx(standby *DmConnection) {
   190  	key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port))
   191  	ret, ok := rwc.standbyNTrxMap[key]
   192  	if ok {
   193  		ret += 1
   194  	} else {
   195  		ret = 1
   196  	}
   197  	rwc.standbyNTrxMap[key] = ret
   198  	sid, ok := rwc.standbyIdMap[key]
   199  	if !ok {
   200  		sid = int32(len(rwc.standbyIdMap) + 1) // 下标0是primary
   201  		rwc.standbyIdMap[key] = sid
   202  	}
   203  	rwc.flag[sid]--
   204  	rwc.ntrx_total++
   205  }
   206  
   207  func (rwc *rwCounter) random(rowCount int32) int32 {
   208  	rand.Seed(time.Now().UnixNano())
   209  	if rowCount > rwc.standbyCount {
   210  		return rand.Int31n(rwc.standbyCount)
   211  	} else {
   212  		return rand.Int31n(rowCount)
   213  	}
   214  }
   215  
   216  func (rwc *rwCounter) String() string {
   217  	return "PERCENT(P/S) : " + strconv.FormatFloat(rwc.primaryPercent, 'f', -1, 64) + "/" + strconv.FormatFloat(rwc.standbyPercent, 'f', -1, 64) + "\nNTRX_PRIMARY : " +
   218  		strconv.FormatInt(rwc.ntrx_primary, 10) + "\nNTRX_TOTAL : " + strconv.FormatInt(rwc.ntrx_total, 10) + "\nNTRX_STANDBY : "
   219  }