我们最近正好遭遇了 fork-unsafe 的 localtime/localtime_r,在这里跟大家分享一下:
(一)背景
MyTopling 是基于 ToplingDB 的 MySQL,分叉自 MyRocks,ToplingDB 则分叉自 RocksDB,兼容 RocksDB 接口,从而 MyTopling 可以复用 MyRocks 的大部分成果。
ToplingDB 早已开源,MyTopling 也将于近期开源。
(二)现象:分布式 Compact 超时
大家可以先参考《 MyTopling 分布式 Compact(一):从多线程到多进程》,然后接着看:在我们的测试中,MyTopling 的分布式 Compact Worker 一直有一个问题:经常跑着跑着,Compact Worker 就假死了,这个问题之前在多线程模型中也偶尔出现,当时经过痛苦的排错定位,最后发现是 NFS (客户端) 超时引起的,这个概率虽然很低,但有时会严重到接近卡死。既然是 NFS 问题,所以我们除了骂娘也无能为力,不过好在 Compact Worker 是无状态计算,这个问题反映到 DB 端只是一个分布式 Compact 任务超时,换一个结点重试即可。后来在多进程模型中,碰到假死我们就直接重启进程。直到昨天晚上,我忽然意识到,以前多线程的时候,假死的频率很低,而现在多进程,跑上几个小时,几乎必然假死……
(三)重新分析
在多线程模型下,Debug 比较容易,直接挂上 gdb 就行,但是在多进程模型下,每个 Compact Job 都会 fork 出一个子进程,并且这个子进程很快就执行结束了。所以我们 Debug 的时候,将其设为多线程模型,因为不管是多进程还是多线程,代码都是复用的,当然用更省力的方式 Debug。但是现在我们是要定位为何多进程时假死的概率要高出这么多,那就必须按多进程 Debug……把 Compact Worker 集群限制到仅一个结点,打高压力,跑了六个多小时,假死得凉凉的!开始用 gdb 逐个查看进程,然后惊奇地发现,所有的 Compact Job 进程都卡在
__tz_convert中:
而我们的 StrDateTimeNow 并没有调用
__tz_convert,然后发现,__tz_convert 是在 localtime 函数中调用的……显而易见,__lll_lock_wait_private 是等在 mutex 上了,定位到这里,一下就知道原因了,几乎所有的最佳实践都强烈反对混用多线程和多进程,而我们这里的父进程偏偏就是多线程,于是在 fork 子进程时,意外就发生了,在同一时刻,发生了两件事情:
-
父进程的
线程 1 在 __tz_convert 中拿到了 mutex lock
父进程的
线程 2 执行 fork 产生子进程 A
因为 fork 在语义上是父进程的一个拷贝,所以在子进程 A 中,__tz_convert 中的那个 mutex 是处于 lock 状态的。在父进程中, 线程 1 在 __tz_convert 中拿到 mutex lock,干完事情就会 unlock,然而子进程 A 中却并没有父进程中的 线程 1,所以那个 mutex 就永远处于 lock 状态……
(四)解决问题
骂 glibc 的娘是必不可少的:有无数种方法可以避免 localtime 这样的函数使用全局锁,但它偏不!骂娘归骂娘,问题是必须要解决的,稍微搜索一下就发现,不止我们碰到了该问题(关键词 localtime "fork"),我们复用了 redis 的解决方案,稍作修改之后,一并给上游 RocksDB 发了个 Pull Request #10652。
(五)讨论
最佳实践都说不要混用多进程与多线程,但是现实世界不是乌托邦,面对某些问题,我们必须采取非常手段,自然也就容易掉坑。就这个坑而言,glibc 甚至 posix 标准有义务把它填平,最低限度,也得提供一个内部无锁的 localtime 版本。最后,大家可以讨论一下:这到底是个 Bug,还是个 Feature 呢?
编辑推荐:
- 多线程fork,子进程执行哪些函数是安全的?03-01
- 详谈 MySQL 8.0 原子 DDL 原理03-01
- 《MySQL 8.x从入门到精通(视频教学版)》简介03-01
- MySQL 5.7配置SSL连接03-01
- 一句SQL,我的数据库crash了03-01
- 创业是走向破产的最佳途径03-01
- windows下安装golang的mysql驱动03-01
- ordered_commit流程梳理03-01
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- 多线程fork,子进程执行哪些函数是安全的?
多线程fork,子进程执行哪些函数是安全的?
26-03-01 - 详谈 MySQL 8.0 原子 DDL 原理
详谈 MySQL 8.0 原子 DDL 原理
26-03-01 - 《MySQL 8.x从入门到精通(视频教学版)》简介
《MySQL 8.x从入门到精通(视频教学版)》简介
26-03-01 - 一句SQL,我的数据库crash了
一句SQL,我的数据库crash了
26-03-01 - 创业是走向破产的最佳途径
创业是走向破产的最佳途径
26-03-01 - ordered_commit流程梳理
ordered_commit流程梳理
26-03-01 - 对话MySQL之父Monty:代码要写到100岁
对话MySQL之父Monty:代码要写到100岁
26-03-01 - Mysql数据库增删改查
Mysql数据库增删改查
26-03-01 - mysqldump备份单库、部分库、全库、及排除部分库
mysqldump备份单库、部分库、全库、及排除部分库
26-03-01 - MySQL数据库部署及初始化相关
MySQL数据库部署及初始化相关
26-03-01
