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 }