keygen.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package utils
  2. import (
  3. "errors"
  4. "github.com/spf13/viper"
  5. "net"
  6. "sync"
  7. "time"
  8. )
  9. // 获取新的程序生成的编号
  10. func NextId() Long {
  11. id, e := SingletonSnowflakeKeyGen().NextId()
  12. if nil != e {
  13. println("get next id failed", e)
  14. return 0
  15. }
  16. return Long(id)
  17. }
  18. /*------------------------------------------------------Singleton----------------------------------------------------*/
  19. var snowflakeKeyGen *Snowflake
  20. var once sync.Once
  21. func SingletonSnowflakeKeyGen() *Snowflake {
  22. once.Do(func() {
  23. snowflakeKeyGen = NewSnowflake(SnowflakeSettings{})
  24. })
  25. return snowflakeKeyGen
  26. }
  27. /*----------------------------------------------------SnowflakeKeyGen------------------------------------------------*/
  28. // Snowflake程序id生成器
  29. // 源于Twitter的Snowflake算法
  30. // 但由于原版算法对应的分布式层级结构太简单,所以目前的算法实际是Sony对Snowflake算法的改进版本的Sonyflake算法
  31. // Sonyflake算法原版可参考github中的开源项目,当前算法有进一步细微调整
  32. const (
  33. SnowflakeTimeUnit = 1e7 // 时间单位,一纳秒的多少倍,1e6 = 一毫秒,1e7 = 百分之一秒,1e8 = 十分之一秒
  34. BitLenSequence = 8 // 序列号的个数最多256个(0-255),即每单位时间并发数,如时间单位是1e7,则单实例qps = 25600
  35. BitLenDataCenterId = 3 // 数据中心个数最多8个(0-7),即同一个环境(生产、预发布、测试等)的数据中心(假设一个机房相同数据域的应用服务器集群只有一个,则数据中心数等于机房数)最多有8个
  36. BitLenMachineId = 16 // 同一个数据中心下最多65536个应用实例(0-65535),默认是根据实例ip后两段算实例id(k8s环境动态创建Pod,也建议用此方式),所以需要预留255 * 255这么多
  37. BitLenTime = 1 << 36 // 时间戳之差最大 = 2的36次方 * 时间单位 / 1e9 秒,目前的设计最多可以用21.79年就需要更新开始时间(随之还需要归档旧数据和更新次新数据id)
  38. // 总共63位,不超过bit64
  39. )
  40. type SnowflakeSettings struct {
  41. StartTime time.Time
  42. DataCenterId func() (uint16, error)
  43. MachineId func() (uint16, error)
  44. CheckMachineId func(uint16) bool
  45. }
  46. type Snowflake struct {
  47. mutex *sync.Mutex
  48. startTime int64
  49. elapsedTime int64
  50. sequence uint16
  51. dataCenterId uint16
  52. machineId uint16
  53. }
  54. func NewSnowflake(st SnowflakeSettings) *Snowflake {
  55. sf := new(Snowflake)
  56. sf.mutex = new(sync.Mutex)
  57. sf.sequence = uint16(1<<BitLenSequence - 1)
  58. if st.StartTime.After(time.Now()) {
  59. return nil
  60. }
  61. if st.StartTime.IsZero() {
  62. sf.startTime = toSnowflakeTime(time.Date(2020, 8, 10, 0, 0, 0, 0, time.UTC)) //没有配置默认使用此时间
  63. } else {
  64. sf.startTime = toSnowflakeTime(st.StartTime)
  65. }
  66. var err error
  67. if st.MachineId == nil {
  68. sf.machineId, err = GetPrivateIPv4Id() // 没有配置会读机器内网ip后两段,然后计算出一个值
  69. } else {
  70. sf.machineId, err = st.MachineId()
  71. }
  72. if nil != err {
  73. err = nil
  74. sf.machineId = uint16(0)
  75. }
  76. if st.DataCenterId == nil {
  77. if id := viper.GetInt("data_center_id"); id > 0 { // 没有配置会尝试从配置文件读取数据中心id
  78. sf.dataCenterId = uint16(id)
  79. } else { // 如果配置文件也没有,默认数据中心id为0
  80. sf.dataCenterId = uint16(0)
  81. }
  82. } else {
  83. sf.dataCenterId, err = st.DataCenterId()
  84. if nil != err {
  85. sf.dataCenterId = uint16(0)
  86. }
  87. }
  88. if st.CheckMachineId != nil && !st.CheckMachineId(sf.machineId) {
  89. return nil
  90. }
  91. return sf
  92. }
  93. func (sf *Snowflake) NextId() (uint64, error) {
  94. const maskSequence = uint16(1<<BitLenSequence - 1)
  95. sf.mutex.Lock()
  96. defer sf.mutex.Unlock()
  97. current := getCurrentElapsedTime(sf.startTime)
  98. if sf.elapsedTime < current {
  99. sf.elapsedTime = current
  100. sf.sequence = 0
  101. } else { // sf.elapsedTime >= current
  102. sf.sequence = (sf.sequence + 1) & maskSequence
  103. if sf.sequence == 0 {
  104. sf.elapsedTime++
  105. overtime := sf.elapsedTime - current
  106. time.Sleep(getSleepTime(overtime))
  107. }
  108. }
  109. return sf.toId()
  110. }
  111. func toSnowflakeTime(t time.Time) int64 {
  112. return t.UTC().UnixNano() / SnowflakeTimeUnit
  113. }
  114. func getCurrentElapsedTime(startTime int64) int64 {
  115. return toSnowflakeTime(time.Now()) - startTime
  116. }
  117. func getSleepTime(overtime int64) time.Duration {
  118. return time.Duration(overtime)*10*time.Millisecond -
  119. time.Duration(time.Now().UTC().UnixNano()%SnowflakeTimeUnit)*time.Nanosecond
  120. }
  121. func (sf *Snowflake) toId() (uint64, error) {
  122. if sf.elapsedTime >= BitLenTime {
  123. return 0, errors.New("over the time limit")
  124. }
  125. return uint64(sf.elapsedTime)<<(BitLenSequence+BitLenDataCenterId+BitLenMachineId) |
  126. uint64(sf.sequence)<<(BitLenDataCenterId+BitLenMachineId) |
  127. uint64(sf.dataCenterId)<<BitLenMachineId |
  128. uint64(sf.machineId), nil
  129. }
  130. func PrivateIPv4() (net.IP, error) {
  131. as, err := net.InterfaceAddrs()
  132. if err != nil {
  133. return nil, err
  134. }
  135. for _, a := range as {
  136. ipnet, ok := a.(*net.IPNet)
  137. if !ok || ipnet.IP.IsLoopback() {
  138. continue
  139. }
  140. ip := ipnet.IP.To4()
  141. if isPrivateIPv4(ip) {
  142. return ip, nil
  143. }
  144. }
  145. return nil, errors.New("no private ip address")
  146. }
  147. func isPrivateIPv4(ip net.IP) bool {
  148. return ip != nil && len(ip) > 3 &&
  149. (ip[0] == 10 || ip[0] == 172 && (ip[1] >= 16 && ip[1] < 32) || ip[0] == 192 && ip[1] == 168)
  150. }
  151. func GetPrivateIPv4Id() (uint16, error) {
  152. ip, err := PrivateIPv4()
  153. if err != nil {
  154. return 0, err
  155. }
  156. return uint16(ip[2])<<8 + uint16(ip[3]), nil
  157. }
  158. func Decompose(id uint64) map[string]uint64 {
  159. const maskDataCenterId = uint64((1<<BitLenDataCenterId - 1) << BitLenMachineId)
  160. const maskMachineId = uint64(1<<BitLenMachineId - 1)
  161. dataCenterId := id & maskDataCenterId >> BitLenMachineId
  162. machineId := id & maskMachineId
  163. return map[string]uint64{
  164. "id": id,
  165. "dataCenterId": dataCenterId,
  166. "machineId": machineId,
  167. }
  168. }