在go语言种实现微秒生成服务示例代码
Go  /  管理员 发布于 6个月前   171
微秒生成服务使用场景:比如实现一个聊天室,拉取历史消息时,排序采用微秒时间进行,
得保证每条消息的微秒值不一样的功能。
代码示例:
package main
import (
"encoding/json"
"flag"
"github.com/valyala/fasthttp"
"log"
"sync"
"sync/atomic"
"time"
)
var collection *Collection
func init() {
collection = NewCollection()
}
func main() {
addr := flag.String("addr", "0.0.0.0:7788", "listen host")
flag.Parse()
s := &fasthttp.Server{
Handler: requestHandler,
Logger: NullLogger{},
}
log.Println("listen http" + "://" + *addr)
err := s.ListenAndServe(*addr)
if err != nil {
log.Fatalln(err)
}
}
func requestHandler(ctx *fasthttp.RequestCtx) {
//业务key
key := string(ctx.QueryArgs().Peek("key"))
//需要得到的微秒个数
incr := int64(ctx.QueryArgs().GetUintOrZero("incr"))
var ret Ret
if key == "" || incr == 0 {
ret = Ret{Code: 1, Message: "invalid argument", Data: 0}
} else {
//客户端拿到data后循环incr次,每次自增1,即可展开得到所有的微秒
ret = Ret{Code: 0, Message: "success", Data: collection.Get(key).Get(incr) - incr}
}
ctx.SetContentType("application/json; charset=UTF-8")
_, _ = ctx.Write(ret.Encode())
}
// NullLogger 空日志
type NullLogger struct {
}
func (r NullLogger) Printf(string, ...any) {
}
// Ret 返回结构
type Ret struct {
Code int `json:"code"`
Message string `json:"message"`
Data int64 `json:"data"`
}
func (r Ret) Encode() []byte {
ret, _ := json.Marshal(r)
return ret
}
// Micro 微秒对象
type Micro struct {
incr *int64
}
func NewMicro() *Micro {
var incr int64
micro := &Micro{
incr: &incr,
}
micro.Reset(time.Now())
return micro
}
func (r *Micro) Get(num int64) int64 {
return atomic.AddInt64(r.incr, num)
}
func (r *Micro) Reset(t time.Time) {
atomic.StoreInt64(r.incr, t.Unix()*1000000)
}
// Collection 所有微秒服务的集合
type Collection struct {
data map[string]*Micro
mutex *sync.RWMutex
}
func NewCollection() *Collection {
c := &Collection{data: map[string]*Micro{}, mutex: &sync.RWMutex{}}
//每隔1秒刷新集合中的所有变量的值
go func(collection *Collection) {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
t := <-ticker.C
c.Reset(t)
}
}(c)
return c
}
func (r *Collection) Get(key string) *Micro {
r.mutex.RLock()
micro, ok := r.data[key]
r.mutex.RUnlock()
if ok {
return micro
}
r.mutex.Lock()
micro, ok = r.data[key]
if ok {
r.mutex.Unlock()
return micro
}
micro = NewMicro()
r.data[key] = micro
r.mutex.Unlock()
return micro
}
func (r *Collection) Reset(t time.Time) {
r.mutex.RLock()
for _, v := range r.data {
v.Reset(t)
}
r.mutex.RUnlock()
}
有兴趣的可以自行测试。
123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..路人 在
php中使用hyperf框架调用讯飞星火大模型实现国内版chatgpt功能示例中评论 教程很详细,如果加个前端chatgpt对话页面就完美了..Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号