Golang Go语言实现的高性能分布式锁服务,每秒可处理83万加锁和解锁请求

发布于 1周前 作者 sinazl 来自 Go语言

Golang Go语言实现的高性能分布式锁服务,每秒可处理83万加锁和解锁请求
之前遇到在下单扣费之类的场景需要分布式锁,后来就自己做了一个,优化一段时间,感觉性能还行啊,i5 8g 机器单机每秒可以完成 83 万加锁解锁请求,不得不说写一个好的 benchmark 也很难啊。

项目地址:

https://github.com/snower/slock

除了分布式锁同步场景外,还实现了分布式 Event,分布式 Semaphore,在消息中心、秒杀枪库存、限流都可以比较方便使用了。

多核性能也不错,可以用到多核,单机测试中,带宽沾满千兆,go 的性能还是好啊。


更多关于Golang Go语言实现的高性能分布式锁服务,每秒可处理83万加锁和解锁请求的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

43 回复

单机分布式锁?

更多关于Golang Go语言实现的高性能分布式锁服务,每秒可处理83万加锁和解锁请求的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


单机分布式锁?

#1
#2 单机 83 万加锁解锁,但是网络服务啊,不是单机用的
比如 web 场景,多台机器需要同步操作库存扣费啥的

楼主是不是不知道啥是分布式锁…

#4 有什么区别么?重点是不局限必须在同一台机器,而保证原子,无论怎么最终还是需要一个中心来确认

#4 而且也只是小服务,主要就是简单,快,针对 web 场景需要同步或是限流之类使用完全没问题啊

有。。。而且肯定不是一个中心来确认

楼主放弃了 CAP 中的 C,然后搞了个毫无实用价值的东西

#7 那可能你是没理解,我这需要的是同步,不是一致性,Paxos 之类的协议都解决的是一致性问题,并不是解决同步问题
一致性有很多协议可以解决,但是同步无论什么协议,最终都需要一个中心来确认吧
而且在需要同步的场景中,那么应该是很快速资源消耗很低的方式实现才是
在简单场景中,很多时候完全可以依赖同步很简单解决一致性问题,但是同步并不是完全用了解决一致性问题的

搞错了 放弃了 A

#10 这解决的是同步问题,并不是数据库场景中的一致性问题

那要是中心突然下线了怎么办(。)

高可用都保证不了, 这个分布式锁谁敢用?

#14 同步问题中不是特别怕中心挂的情况吧

一般来说同步场景都是某一刻同步,比如 a 和 b 在前一刻用 1 中心同步,那么 c 和 d 为啥不能在下一刻用 2 备用中心同步呢,其中产生的一致性问题应该仍然还是由数据库事物或者其他一致性协议来保证

总的来说,分布式锁其中一个场景应该是想要解决的问题应该是我们在很多时候使用一致性结果来同步的极大资源消耗问题,比如很明显的秒杀场景中,是否还有库存这个状态

其他的比如扫码登陆时,是否已经扫码不也是一个同步问题么

#15 本来就是小工具啊,解决小微场景中某些用锁可以很方便解决的同步问题,并没有说在大型场景中可以很成熟使用

讲个笑话,paxos、raft 没解决同步的问题 😹

#15 不过最近也在考虑也行可以加入 binlog 和集群模式看看,也只是探讨,在很多小微场景确实高可用不是特别突出,简单快速解决问题也挺好不是

#18 paxos、raft 解决的是一致性问题吧

如果不用高可用,和 redis 单机锁性能相比何如?应该也没啥优势吧。

你说这是高性能锁服务就好了,那么大家还能讨论一下。

亲,这边建议您了解一下二(三)步提交、raft log 是什么呢

#21 首先 redis 锁没有 wait。。都是延时重试

#22 对对对,就是这个意思

楼主的代码实践的还不错,但一般来说,秒杀场景首先要求高可用,可以参考淘宝的秒杀系统设计的一些文章。

如果不是走 tcp,有啥意义

#23 我知道啊,这难道不是用一致性来解决同步问题么,所以核心还是一致性啊
这里不是主要讲数据同步,更多是即时状态同步

#27 走 tcp 啊,不是单机的库,啥意思?

你做的是“给分布式系统使用的锁服务”,而从你的描述中,大家理解的是“锁服务,这个服务本身是分布式的”。你始终还没有理解到这个区别。

一行测试都没有

变量名不符合惯例

目录结构不符合惯例,主程序没法 go get 下载

不知道标准库的 binary 包,协议处理过于罗嗦

go vet 发现一处大错,复制了 sync.Mutex

总而言之,正确性都未能保证,就不要奢谈性能了

这个单点问题有点严重

#31 玩一下,要啥测试啊,麻烦死了
协议没有用 binary 包,这是故意的,binary 包内部用了反射,性能很差
至于正确性,正确运行就是正确性

#30 那可能是有歧义,没说给分布式系统用的锁,你说的对,锁服务


那假设 a,b,c,d 都在抢一个锁,a 在写入前中心下线,b,c,d 请求锁,这时候换到 node 2,写在了 a 前面怎么办?(。)
"分布式"标签都在了,没有办法冗余不妥吧…

没有测试,就说明你没有尽最大努力去保证正确。连复制 sync.Mutex 这种错误都出现了,基本可以说是垃圾代码。嫌麻烦不写测试,却不嫌麻烦不用 binary 包,不知所谓。

不应该是 P 吗?分区可用性

./slock.go:118:33: assignment copies lock value to free_result_command_lock: sync.Mutex

go vet 报的这个错,表示你以为上了锁的地方,实际没有上锁,因为你复制了 sync.Mutex 而不是用同一个。
我不知道你哪里来的自信,没有测试也敢说“正确运行”

不明白没有一致性的分布式锁有什么应用场景

#35
#39
首先我们认为能够使用外部锁同步的,应该是极其短时且大量相关性不高事件,所以冲突概率不高,其次就算冲突,底层应该还有事物或是 raft 这样的一致性协议保证最终一致性,所以不会造成太大问题,我想已经有很多论文证明过通过一个外部锁解决一致性问题是不可能的,更别说通过外部锁解决外部系统一致性问题更不可能,所以这里同样无法解决

但是即使如此,外部锁仍有其意义
在大型系统中,raft 这样的协议解决冲突非常复杂消耗资源,更别说微服务场景中,一致性的产生更加复杂,如果外部锁某些时候确实可以消减一部分的冲突,对系统性能改善或许是有意义的,更别说在平滑系统负载,抗冲击都是有一定的意义

而在大量的中小型系统中,几乎都是短时任务的场景下,本身系统负载就低,遇到奔溃的几率本身就微乎其微,在复杂度开发周期成本考量下,我想这只是一个工程抉择问题,而且大量单机 redis 场景下,过于考虑高可用其实意义不大吧

从其他来说,操作系统提供的锁,除了 Lock 还有 Event 和 Semaphore 的吧,以往很多时候我们都用轮询、订阅或是队列来解决这两个问题了,但是在简单场景中,这确实有些复杂,能购用更简单的 Event 和 Semaphore 语义来解决这个问题又有什么不好呢

总的来说,这其实是一个工程问题,不是学术,更不是一个可以通用的解决方案,在工程中,我们有更多考量,过往积累,实现周期复杂度,成本,维护性等等,所以是否有用还是看整体系统方案,比如云,难道没有单点问题,不会有崩溃不一致问题么,我想事实不可能,但是我们综合考量,确实是最好的

只是个方案,大家仁者见仁,智者见智就好了,这不是一个通用解决方案,也不是一个学士问题

#38 好吧,我对 go vet 不太熟,这地方也不是核心锁,所以没注意到了,现在学习到了,已经修改过来了,感谢

和分布式锁没有半点关系.
哦不对,有 1/4 的关系,都是锁。

关于您提到的Golang(Go语言)实现的高性能分布式锁服务,每秒能处理83万加锁和解锁请求这一成就,确实令人印象深刻。这里有几个关键点可以帮助进一步理解和优化此类服务:

  1. 高并发处理:Go语言以其高效的并发模型著称,特别是goroutine和channel的使用,使得实现高并发服务变得相对简单。每秒83万请求的处理能力,很大程度上得益于Go的并发处理机制。

  2. 分布式锁实现:分布式锁的实现通常依赖于分布式协调服务(如etcd、ZooKeeper)或数据库(如Redis)。选择合适的底层存储和高效的锁算法(如Redlock)对性能至关重要。

  3. 性能优化:为了达到如此高的处理能力,可能需要对网络IO、内存使用、锁粒度等方面进行优化。例如,使用高效的序列化/反序列化库、减少锁持有时间、优化锁分配策略等。

  4. 监控与调试:在高并发环境下,系统的稳定性至关重要。建议实施全面的监控和日志记录,以便及时发现并解决问题。

  5. 扩展性:随着业务增长,分布式锁服务的负载也会增加。因此,服务的可扩展性设计(如水平扩展、分片)也是不可忽视的。

总之,实现高性能的分布式锁服务是一个复杂的任务,需要综合考虑并发处理、锁算法、性能优化、监控和扩展性等多个方面。您的成果已经证明了Go语言在高性能服务开发中的潜力,期待您在未来继续优化和拓展这一服务。

回到顶部