go 简单实现分布式锁

简介: 单一执行,通过分布式锁实现

有多个客户端请求服务端,业务规定,某个任务只能单一执行

例如:有a,b,c,d 4个客户端同时访问服务端,都竞争任务执行资格,谁竞争到了这个资格,这个任务就由它执行,其它人即使执行也是无效的,如果它出故障了,服务端判断一定时间任务没有执行,就会释放这个资格,其它客户端就可以继续竞争这个任务执行资格了。

如何实现这种业务场景呢?

代码例子

packagemainimport (
"fmt""github.com/gin-gonic/gin""sync""time")
typeFstruct {
NamestringTint64}
varfFvarmsync.Mutexfuncmain() {
//起一个go协程去检查单一任务是否离线,10秒gofunc() {
for {
iff.Name!=""&&time.Now().Unix()-f.T>10 {
m.Lock()
f.Name=""m.Unlock()
            } else {
fmt.Println("目前锁的持有者是:", f.Name)
            }
time.Sleep(1*time.Second)
        }
    }()
r :=gin.Default()
r.GET("/ping", task)
r.GET("/hello", hello)
r.Run() // listen and serve on 0.0.0.0:8080}
funchello(c*gin.Context) {
c.JSON(200, gin.H{
"message": "hello,world",
    })
}
functask(c*gin.Context) {
ifc.Query("name") !="" {
iff.Name=="" {
m.Lock()
f.Name=c.Query("name")
f.T=time.Now().Unix()
m.Unlock()
c.JSON(200, gin.H{
"message": "get lock ok",
            })
        } else {
ifc.Query("name") ==f.Name {
//更新心跳时间f.T=time.Now().Unix()
c.JSON(200, gin.H{
"message": "单一任务执行者",
                })
            } else {
c.JSON(200, gin.H{
"message": "不需要额外的任务执行者",
                })
            }
        }
    } else {
c.JSON(400, gin.H{
"message": "miss  name query",
        })
    }
}


执行效果

jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee
{"message":"get lock ok"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=cc
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee
{"message":"单一任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee
{"message":"单一任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"get lock ok"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"单一任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=bb
{"message":"单一任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee
{"message":"不需要额外的任务执行者"}
jiangyd:fenbu jiangyd$ curl http://127.0.0.1:8080/ping?name=ee
{"message":"不需要额外的任务执行者"}


应用日志

目前锁的持有者是: 
目前锁的持有者是: 
目前锁的持有者是: 
[GIN] 2021/11/18 - 14:38:11 | 200 |     166.817µs |       127.0.0.1 | GET      "/ping?name=ee"
目前锁的持有者是: ee
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:13 | 200 |      132.71µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: ee
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:16 | 200 |     156.544µs |       127.0.0.1 | GET      "/ping?name=cc"
目前锁的持有者是: ee
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:18 | 200 |      60.798µs |       127.0.0.1 | GET      "/ping?name=ee"
目前锁的持有者是: ee
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:19 | 200 |      57.979µs |       127.0.0.1 | GET      "/ping?name=ee"
目前锁的持有者是: ee
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:21 | 200 |      59.946µs |       127.0.0.1 | GET      "/ping?name=bb"
[GIN] 2021/11/18 - 14:38:22 | 200 |      53.904µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:23 | 200 |      45.606µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:23 | 200 |      46.552µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:24 | 200 |       49.45µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:25 | 200 |      76.116µs |       127.0.0.1 | GET      "/ping?name=bb"
[GIN] 2021/11/18 - 14:38:26 | 200 |      105.55µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:27 | 200 |      79.018µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:27 | 200 |      66.346µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:28 | 200 |      76.468µs |       127.0.0.1 | GET      "/ping?name=bb"
[GIN] 2021/11/18 - 14:38:29 | 200 |      50.744µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: ee
[GIN] 2021/11/18 - 14:38:30 | 200 |      96.843µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: 
[GIN] 2021/11/18 - 14:38:31 | 200 |      109.12µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: bb
目前锁的持有者是: bb
目前锁的持有者是: bb
[GIN] 2021/11/18 - 14:38:34 | 200 |     140.095µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: bb
[GIN] 2021/11/18 - 14:38:35 | 200 |      52.475µs |       127.0.0.1 | GET      "/ping?name=bb"
目前锁的持有者是: bb
目前锁的持有者是: bb
目前锁的持有者是: bb
目前锁的持有者是: bb
[GIN] 2021/11/18 - 14:38:39 | 200 |      57.742µs |       127.0.0.1 | GET      "/ping?name=ee"
目前锁的持有者是: bb
[GIN] 2021/11/18 - 14:38:40 | 200 |      61.668µs |       127.0.0.1 | GET      "/ping?name=ee"
[GIN] 2021/11/18 - 14:38:41 | 200 |      46.113µs |       127.0.0.1 | GET      "/ping?name=ee"
目前锁的持有者是: bb
目前锁的持有者是: bb
目前锁的持有者是: bb
目前锁的持有者是: bb
目前锁的持有者是: bb
目前锁的持有者是: 
目前锁的持有者是: 


这样就可以达到要求了。

相关文章
|
4月前
|
消息中间件 Go
rabbitMQ go语言简单实现
rabbitMQ go语言简单实现
37 0
|
存储 负载均衡 中间件
Go 简单实现多租户设计
在 SaaS 系统中多租户是一个很重要的架构,在服务上仅需运行一个软件实例就能够支持每个租户的功能,它们之间的数据互相隔离。就比如 Gitee ,每个用户或组织都拥有自己的空间。它们自己的数据仅在自己的空间内流通,彼此之间互不影响。多租户其实就是一种软件设计结构。 所以。租户模型其实就是分离数据的方式: • 单租户:一个应用一个数据库。其实就是应用分离,数据分离。 • 多租户:一个应用多个数据库。就是同一个应用不同数据库。
640 0
|
Go
go语言简单实现加载ini文件
go语言简单实现加载ini文件
107 0
go语言简单实现加载ini文件
|
8天前
|
Go
go语言中的数据类型
go语言中的数据类型
11 0
|
14天前
|
Go 开发者
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
|
14天前
|
安全 Go
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
|
14天前
|
存储 缓存 安全
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
|
14天前
|
Go
使用Go语言发邮件
使用Go语言发邮件
17 2
|
26天前
|
缓存 安全 Java
Go语言小细节
Go语言小细节
36 0
|
14天前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)