package study import ( "math" "sync" ) type Bucket struct { sum uint //当前桶总质押币的数量 priceList [bucketSize]*OrderInfo // 100的价格数组 lockMap sync.Map // 数组锁 只有在使用的时候才创建 避免内存开销 但是建议priceList的长度在3-5万以内使用,如果百万级别用方案二 rwmu sync.RWMutex // 读写锁 } type OrderInfo struct { OrderId string Count uint //当前桶下币的数量 next *OrderInfo //同等价位就用链表 TripPrice int //触发价格 addressCoin string //订单币种 } // 每一种币价都有自己的步长 一旦确定不能更改 const bucketSize = 5 //桶步长 // 方案二 分层锁机制 const topLevelLocks = 1024 var ( buckets = make(map[int]*Bucket) // 使用指针类型 addressCoin string = "BTC" //币合约的地址,每一个桶都只能是同一币种 prevPrice int = 71 bucketsMu sync.Mutex // 保护 map[bucketKey]*Bucket zoneLocks [topLevelLocks]sync.RWMutex // 方案二 ) func AddOrderInfo() { AddBucket(&OrderInfo{ OrderId: "1", Count: 2, TripPrice: 77, addressCoin: "BTC", }) AddBucket(&OrderInfo{ OrderId: "2", Count: 2, TripPrice: 53, addressCoin: "BTC", }) AddBucket(&OrderInfo{ OrderId: "3", Count: 2, TripPrice: 47, addressCoin: "BTC", }) AddBucket(&OrderInfo{ OrderId: "4", Count: 2, TripPrice: 39, addressCoin: "BTC", }) AddBucket(&OrderInfo{ OrderId: "5", Count: 2, TripPrice: 33, addressCoin: "BTC", }) AddBucket(&OrderInfo{ OrderId: "6", Count: 1, TripPrice: 33, addressCoin: "BTC", }) println("GetBuckets()") } func DoBucket(currentPrice int) { //说明行情上涨 不处理 if currentPrice-prevPrice >= 0 { return } //行情下跌 diff := math.Abs(float64(currentPrice - prevPrice)) result := uint(diff / float64(bucketSize)) quotient := currentPrice / bucketSize // 商: 60 remainder := currentPrice % bucketSize //余数 key := quotient * bucketSize doSingleBucketToOrder(key, remainder) if result > 0 { //说明夸区间了 急跌 需要 处理之前的区间 //说明夸区间了 quotientPrev := prevPrice / bucketSize // 商: 60 keyPrev := quotientPrev * bucketSize for i := keyPrev; i > key; i -= bucketSize { doSingleBucket(i) } } println("GetBuckets()") } /** * 处理单个桶区间 */ func doSingleBucket(key int) { existing, ok := buckets[key] if !ok || existing.bucketSumRead() == 0 { return } //先执行清算逻辑 existing.liquidationByBucket() var wg sync.WaitGroup for i := 0; i < len(existing.priceList); i++ { wg.Add(1) go func(slot int) { defer wg.Done() processOrder(key, slot) }(i) } wg.Wait() //后续处理逻辑 } /** * 处理一个价位链表,这样做的目的只锁 一个价位链表,其他价位链表可以继续处理 */ func processOrder(key int, remainder int) { if existing, ok := buckets[key]; ok { //在处理订单数据的时候 不允许其他线程读priceList[remainder]防止有问题 lock, _ := existing.lockMap.LoadOrStore(remainder, &sync.Mutex{}) slotLock := lock.(*sync.Mutex) slotLock.Lock() order := existing.priceList[remainder] var count uint if order != nil { current := order for current != nil { next := current.next count += current.Count go liquidationByOrder(current.OrderId, current.Count) //先执行清算逻辑 go doDBOrderInfo(current.OrderId) //处理订单数据库部分, current = next } } existing.priceList[remainder] = nil //修正数据 slotLock.Unlock() } } func doSingleBucketToOrder(key int, remainder int) { if existing, ok := buckets[key]; ok { //在处理订单数据的时候 不允许其他线程读priceList[remainder]防止有问题 lock, _ := existing.lockMap.LoadOrStore(remainder, &sync.Mutex{}) slotLock := lock.(*sync.Mutex) slotLock.Lock() order := existing.priceList[remainder] var count uint if order != nil { current := order for current != nil { next := current.next count += current.Count go liquidationByOrder(current.OrderId, current.Count) //先执行清算逻辑 go doDBOrderInfo(current.OrderId) //处理订单数据库部分, current = next } } //修正数据 existing.priceList[remainder] = nil existing.bucketSumWrite(existing.bucketSumRead() - count) slotLock.Unlock() } } func liquidationByOrder(orderId string, count uint) { println(orderId+"执行清算逻辑需卖出的币数量:", count) //异步执行-清算逻辑待实现.... } func (b *Bucket) liquidationByBucket() { println("执行清算逻辑需卖出的币数量:", b.bucketSumRead()) b.bucketSumWrite(0) // 先变更状态 //异步执行-清算逻辑待实现.... 注意 无论清算多少 都要把数量清除0,为了避免复杂 //始终保证 bucket 数量等于 每一个价位里边币数量 //如何10个币 清算了7个 那么 记录,重试逻辑都要放到 清算流程里边 } func doDBOrderInfo(orderId string) { println("执行数据库订单状态变更逻辑订单ID:", orderId) } func AddBucket(order *OrderInfo) { if addressCoin != order.addressCoin { return } quotient := order.TripPrice / bucketSize // 商: 60 remainder := order.TripPrice % bucketSize //余数 key := quotient * bucketSize var bucket *Bucket if existing, ok := buckets[key]; ok { bucket = existing } else { //不存在 initBucket(key) bucket = buckets[key] } bucket.bucketSumWrite(order.Count) // 插入链表头部 bucket.insertPriceList(remainder, order) } func initBucket(key int) { bucketsMu.Lock() //二次判断,避免重复创建 _, ok := buckets[key] if !ok { bucket := &Bucket{ priceList: [bucketSize]*OrderInfo{}, } buckets[key] = bucket } bucketsMu.Unlock() } func (b *Bucket) bucketSumWrite(count uint) { b.rwmu.Lock() b.sum += count b.rwmu.Unlock() } func (b *Bucket) bucketSumRead() uint { b.rwmu.RLock() defer b.rwmu.RUnlock() return b.sum } /** *remainder 如果线程 remainder 相同 则加锁互斥 ,不同则并发执行 */ func (b *Bucket) insertPriceList(remainder int, order *OrderInfo) { lock, _ := b.lockMap.LoadOrStore(remainder, &sync.Mutex{}) slotLock := lock.(*sync.Mutex) slotLock.Lock() // 在链表头部插入新订单 order.next = b.priceList[remainder] b.priceList[remainder] = order slotLock.Unlock() } /** * 锁方案二 */ func (b *Bucket) insertPriceListTow(remainder int, order *OrderInfo) { //哈希分片 黄金比例(φ ≈ 1.6180339887)更均匀 zoneId := remainder * 0x9e3779b9 % topLevelLocks lock := &zoneLocks[zoneId] lock.Lock() // 在链表头部插入新订单 order.next = b.priceList[remainder] b.priceList[remainder] = order lock.Unlock() } func GetBuckets() map[int]*Bucket { return buckets // 或者返回副本防止外部修改 }