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

2019-03-12 18:33:55 +08:00
 sujin190
之前遇到在下单扣费之类的场景需要分布式锁,后来就自己做了一个,优化一段时间,感觉性能还行啊,i5 8g 机器单机每秒可以完成 83 万加锁解锁请求,不得不说写一个好的 benchmark 也很难啊。

项目地址:

https://github.com/snower/slock

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

多核性能也不错,可以用到多核,单机测试中,带宽沾满千兆,go 的性能还是好啊。
6064 次点击
所在节点    Go 编程语言
42 条回复
lhx2008
2019-03-12 20:03:41 +08:00
如果不用高可用,和 redis 单机锁性能相比何如?应该也没啥优势吧。
aleung
2019-03-12 20:03:57 +08:00
你说这是高性能锁服务就好了,那么大家还能讨论一下。
wweir
2019-03-12 20:06:05 +08:00
@sujin190 亲,这边建议您了解一下二(三)步提交、raft log 是什么呢
sujin190
2019-03-12 20:08:46 +08:00
@lhx2008 #21 首先 redis 锁没有 wait。。都是延时重试
sujin190
2019-03-12 20:09:00 +08:00
@aleung #22 对对对,就是这个意思
kkeiko
2019-03-12 20:10:20 +08:00
楼主的代码实践的还不错,但一般来说,秒杀场景首先要求高可用,可以参考淘宝的秒杀系统设计的一些文章。
lhx2008
2019-03-12 20:10:21 +08:00
@sujin190 如果不是走 tcp,有啥意义
sujin190
2019-03-12 20:11:47 +08:00
@wweir #23 我知道啊,这难道不是用一致性来解决同步问题么,所以核心还是一致性啊
这里不是主要讲数据同步,更多是即时状态同步
sujin190
2019-03-12 20:13:22 +08:00
@lhx2008 #27 走 tcp 啊,不是单机的库,啥意思?
aleung
2019-03-12 20:28:46 +08:00
@sujin190 你做的是“给分布式系统使用的锁服务”,而从你的描述中,大家理解的是“锁服务,这个服务本身是分布式的”。你始终还没有理解到这个区别。
reus
2019-03-12 20:32:39 +08:00
一行测试都没有

变量名不符合惯例

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

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

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

总而言之,正确性都未能保证,就不要奢谈性能了
jay1002008
2019-03-12 20:44:58 +08:00
这个单点问题有点严重
sujin190
2019-03-12 21:29:19 +08:00
@reus #31 玩一下,要啥测试啊,麻烦死了
协议没有用 binary 包,这是故意的,binary 包内部用了反射,性能很差
至于正确性,正确运行就是正确性
sujin190
2019-03-12 21:31:09 +08:00
@aleung #30 那可能是有歧义,没说给分布式系统用的锁,你说的对,锁服务
wusatosi
2019-03-12 22:15:39 +08:00
@sujin190
那假设 a,b,c,d 都在抢一个锁,a 在写入前中心下线,b,c,d 请求锁,这时候换到 node 2,写在了 a 前面怎么办?(。)
"分布式"标签都在了,没有办法冗余不妥吧...
reus
2019-03-12 22:43:47 +08:00
@sujin190 没有测试,就说明你没有尽最大努力去保证正确。连复制 sync.Mutex 这种错误都出现了,基本可以说是垃圾代码。嫌麻烦不写测试,却不嫌麻烦不用 binary 包,不知所谓。
JohnSmith
2019-03-13 00:39:34 +08:00
@zealot0630 不应该是 P 吗?分区可用性
reus
2019-03-13 08:47:45 +08:00
./slock.go:118:33: assignment copies lock value to free_result_command_lock: sync.Mutex

go vet 报的这个错,表示你以为上了锁的地方,实际没有上锁,因为你复制了 sync.Mutex 而不是用同一个。
我不知道你哪里来的自信,没有测试也敢说“正确运行”
index90
2019-03-13 11:25:51 +08:00
不明白没有一致性的分布式锁有什么应用场景
sujin190
2019-03-13 23:48:28 +08:00
@wusatosi #35
@index90 #39
首先我们认为能够使用外部锁同步的,应该是极其短时且大量相关性不高事件,所以冲突概率不高,其次就算冲突,底层应该还有事物或是 raft 这样的一致性协议保证最终一致性,所以不会造成太大问题,我想已经有很多论文证明过通过一个外部锁解决一致性问题是不可能的,更别说通过外部锁解决外部系统一致性问题更不可能,所以这里同样无法解决

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

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

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

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

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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/543838

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX