find me on twitter: @plantegg
知识星球:https://t.zsxq.com/0cSFEUh2J
Github: 欢迎star
关注基础知识,一次把问题搞清楚,从案例出发深挖相关知识。
以前觉得自己一看就懂,实际是一问就打鼓,一用就糊涂。所以现在开始记录并总结再联系案例,一般是先把零散知识记录下来(看到过),慢慢地相关知识积累更多,直到碰到实践案例或是有点领悟到于是发现这块知识可以整理成一篇系统些的文章(基本快懂了)。
“技术变化太快,容易过时”,我的看法是网络知识、操作系统、计算机原理等核心概念知识的寿命会比你的职业生涯还长。这些都是40岁之后还会还会很有用
如何在工作中学习 所有方法我都记录在这篇文章中了,希望对你能有所帮助。
所有新文章从这里可以看到,即使再简单的一篇总结我可以持续总结三五年,有新的发现、感悟都是直接在原文上增减,不会发表新的文章。
为什么写博客而不是公众号,我见过20年前的互联网,深度依赖搜索引擎,所以还是喜欢博客。另外技术类文章更适合电脑阅读(随时摘录、实验)
大家抱着美好和雄赳赳的目标来到这个知识星球,开始的时候兴奋地以为找到了银弹(其实银弹是有的,在文章最后),经过一段时间后大概率发现没什么变化,然后就回到了以前的老路子上,我觉得关键问题是你没获取到星球的精华,所以这篇我打算反复再唠叨一下
虽然我们现在通过这篇《知识效率 工程效率》知道了两者的差别, 但是还是需要记住通过积累可以将我们的学习能力从工程效率升级到知识效率(厚积薄发),大部分时候没有做到薄发,是因为你以为理解了、积累了实际没理解
尽力寻找每个领域的核心知识点,核心知识点的定义就是通过一两个这样的知识点能撬动对整个领域的理解,也就是常说的纲挈目张
比如网络领域里:一个网络包是怎么流转的+抓包。假如你理解网络包的流转后再去看LVS 负载均衡的原理你就发现只需要看一次你就能很好掌握LVS各个负载均衡的本质,而在这之前你反复看反复忘。掌握了这个知识点基本就可以通关整个领域,剩下的只是无招胜有招碰到一个挨个积累的问题了。
比如CPU领域理解超线程+IPC+会用perf和内存延时,理解超线程的本质是为什么一个核能干两个核的工作(这和操作系统的分时多任务背后原理是想通的),那是因为我们的程序没法吃满流水线(也就是没法用完一个核的计算能力,用IPC去衡量),没吃满闲置的时候就可以虚拟给另外一个进程用,比如CPU 跑起来最高IPC都能到4,但是无论你找一个Java还是MySQL 去看他们的IPC基本都在1以内,纯计算场景的IPC会高一点,IPC 可以到4但只跑到1的话也就是只用满了25%的能力,那当然可以再虚出来一个超线程提高效率。IPC 之所以低就是因为内存延时大,这么多年CPU的处理能力一直按摩尔定律在提升但是内存延时没有怎么提升,导致基本上我们常见的业务场景(Nginx/MySQL/Redis 等)都是CPU在等从内存取数据(所以搞了L1、L2、L3一堆cache)。
发散一下或者说留个作业你去看看NUMA 的原理或者说本质就是为了让CPU知道就近分配读取内存以提升效率。
你看整本计算机组成原理+性能的本质都在这一个知识点的范围内进行延伸和突破。
如果你发现一个核心知识点也欢迎写成博客文章分享出来
我的经验只是大概20%左右的程序员会去耐心读别人的日志、报错信息,大部分摊摊手求助、放弃了
日志是最好的学习机会,我知道别人的日志写得很烂,但是你要能耐心多琢磨一点就会比别人更专业一点
抓包、perf的使用这些平时要多积累,这点没有捷径,一个好的工程师肯定有一堆好的锤子、瑞士军刀、工具包的。在你掌握了知识点后要转化为工作效率,就得多积累这些工具,很多次我们碰到一个好的问题没分析出来是因为我们这种没有门槛的积累不够导致放弃了
比如需要抓包确认下,不会,一看tcpdump 一堆参数头疼放弃;比如想要知道长连接还是短连接,或者自己设置的长连接有没有生效,不会用netstat -o 这个参数去确认等;比如要下载个源码自己make/install 中间报了几个错误不仔细看放弃;
反过来回到我们所说的工程效率,就是靠这些工具帮你实现可视、可以触摸,网络之所以大多数同学在大学都学过但是最后基本学懂,就是因为这些网络的东东你只看理论很难立即,但是让你抓过一次包分析下就会恍然大悟——这就是关键门槛你能跨过去
在星球里我更希望你带走一个好的习惯而不是一个具体知识点,虽然星球里的具体知识点、案例胜过很多教材,但他们总有过时、用不上的时候,唯有好的习惯可以跟随你,帮你实现无招胜有招
放低身段,不要高估自己的能力(认为自己是知识效率),放低后你要怎么做呢:记笔记、记笔记、记笔记
只要是你在学习就要或者看书、看资料的时候觉得自己有点通透了,赶紧记录下来,因为大概率一个星期你就忘了,半年你就完全不记得自己以前看过一次了,我好多次看到一篇好文章就感叹自己学到了,兴奋地拉到文章最后想去评论下,结果发现居然有了自己的评论在下面 :)
动手,看到后理解了,也记了笔记,其实最好还是要自己去重现,记下自己看到的现象和理解,动手又会有一堆门槛,搭环境、客观则、怎么验证等等,这个时候我前面说的可观测性里面积累的一大堆工具可以让你如有神助、重现起来效率就是比别人高
最后笔记记完还没完,笔记基本是零散的,你反复积累后到了一定的时机就是要把他们总结汇总成一篇完整度较高的博客文章,这里当然有自己的虚荣心在这里,但更多的是为了自己查询方便,有了新的理解或者使用姿势我经常更新补充10年前的博客文章,不会写一篇新的,这个补充知识让我的知识结构更完善,不是为了多发一篇博文,我现在解决问题、使用工具基本要靠翻自己的博客文章照着操作
往往我们喜欢求快,以为自己一看就懂;求多以为自己越看的多越厉害
看这篇置顶:https://t.zsxq.com/14Yel6KBg
对公司的业务、一个软件的运转流程都要尽量做到理解
比如学MySQL 要尽量知道从一条SQL 怎么进来,进行哪些处理后得到了查询结果;比如前面讲过的一个网络包是怎么到达对端的;比如你们公司的请求是怎么从客户端到达服务端(中间经过了LVS、Nginx吗),服务端又是那些服务得依赖和调用,有没有Redis、MQ、Database,最后数据又是怎么返回的,我知道这在一个公司很难(屎山很复杂),但目前没有更好的方法让你快速掌握并立足
为什么出现问题后总有一两个人很快能猜出来问题可能在哪个环节,这一部分是经验但更多的是对系统的了解,你都不知道有Redis存在一旦出错了你肯定猜不到Redis这里来
可以看看我之前说的实习生的故事,完全真实哈:
讲一个我碰到的实习生的事情
北邮毕业直接后直接到我司实习
特点:英语好、动手能力强、爱琢磨,除了程序、电脑没有其它爱好 :)
实习期间因为英语好把我司文档很快就翻烂了,对产品、业务逻辑的理解基本是顶尖的
实习期间很快成为所有老员工的红人,都离不开他,搭环境、了解业务流程
因为别人的习惯都是盯着自己眼前的这一趴,只有他对业务非常熟悉
实习后很快就转正了,又3年后transfer 去了美国总部
连女朋友都是老员工给牵线的,最后领证一起去了美国。为啥老员工这么热情,是大家真心喜欢他
再看看张一鸣自述的第一年的工作:
我前面所说的我也没做太好,希望大家能做得更好,我第一次感受无招胜有招就是故事一里面,到故事二过去差不多10年,这10年里我一直在琢磨怎么才能无招胜有招,也有在积累,但是花了10年肯定效率不算高,所以在星球里我希望通过我的经验帮你们缩短一些时间
上面讲再多如果你只是看看那根本还是没用,买再多的课也没用,关键是看触动后能否有点改变。你可以从里面试着挑几个你认为容易操作,比如记笔记、比如不要等着时间流投喂,或者有感触的试试先改变或者遵循下看看能不能获得一些变化进而形成正向循环
或者从评论里开始说说你星球这一年真正有哪些改变、学到了啥、你的感悟,不方便的也可以微信我私聊一下
这篇就当成整个星球学习的一个总结吧
]]>因为长期打球,导致手肘部分疼痛难耐,2024年1月开始进行了长时间的休息期,中间2024的2月是春节,所以总共修了快2个月,还不见好,于是去医院,其实医院给的治疗方案也不好,但是医师告诉了我一个关键词这个病叫:网球肘
知道关键字后就开始了自我寻求治疗方案的过程,记下来供参考,到2024年3月14号,最近两周多次打球验证我的网球肘基本好了,所以说一下治疗过程
网球肘的核心是肌肉过劳发炎了,所以关键是如何消炎
一定要用:氟比洛芬凝胶贴膏 ,而且每天两贴尽量不要断,期间通过大拇指使劲按压疼痛部分来感受验证的减轻,一般连续贴3-5天会有明显的效果,如果无效请去医院
口服消炎药也可以试试,我估计针对性不强(瞎猜的,希望你试试后来告诉我)。至于体外冲击波可以尝试尝试,我个人的经验觉得还不足以证明其有效
后面的可以不用看了
网球肘已经有几个月了,开始我没在意以为就是肌肉劳累,休息休息就会好,直到过年的时候我真正歇了一个多月,过完年偶尔一用力居然又开是疼,让我计划去医院看看,之前自己在社区医院开过几盒:氟比洛芬凝胶贴膏
(家中请常备这个药,膏药里的神奇)
【适应症】
下列疾病及症状的镇痛、消炎:
骨关节炎、肩周炎、肌腱及腱鞘炎、腱鞘周围炎、肱骨外上髁炎 ( 网球肘 )、肌肉痛、外伤所致肿胀、疼痛
过年期间自己也偶尔贴一下,但是效果不明显(应该是没有连续贴导致的效果不好)。
这次去医院正规想看看,但是大医院挂不上号,于是去了一个小医院(社区医院推荐的,说这家别的不行,刚好看运动医学还不错),到医院大夫一听就笑着问我知不知道有一种病叫:网球肘。这是我第一次听说这个病,大夫用大拇指按压我的伤口附近,确实非常疼,结合我经常打球基本确诊。
然后给我开了两次体外冲击波物理治疗,当场治疗了一次,过程中很痛,打完的当时再按压就不疼了,但是过几个小时还是照旧(这也在医师的预料中),给我开了两次这个治疗,我只去了一次
体外冲击波疗法(extracorporeal shock wave therapy, ESWT)是一种非侵入性、安全、有效治疗多种疾病的方法,在临床多个学科中得到了广泛应用,但临床应用不规范、治疗关键技术不一致、治疗方案不统一、培训体系不健全等问题严重制约了ESWT的临床推广应用。
回到家我就开始了对“网球肘”的学习,中间找到这篇最关键的经验贴【你一定要看】,我把这里面最有价值的引用一下:
比较对症的治疗方法是,内服 洛索洛芬钠片,外贴 氟比洛芬凝胶贴膏(商标是泽普思),尤其要注意用量和时机
洛索洛芬钠片——我这次没吃这个
氟比洛芬凝胶贴膏——这点最重要,我不再像以前一样偶尔贴,而是连续一周每天两贴
按照上面的做法,经过5天后我的网球肘真的神奇地好了,中间还阳了3天(所以第二次冲击波治疗我也没去)
我的判断是网球肘消炎很重要,应该还是氟比洛芬凝胶贴膏起了关键作用,但是要注意:连续贴一周,每天两贴
至于冲击波是否有效果,我目前觉得可能有效果,但是证据还不够
知道这个病的名字很重要,这样就有了搜索关键字,看别人描述相对来说我这次不算严重
知道名字后,我在淘宝上购买了 UpToDate 临床顾问论文库的账号(收录了几乎所有的医学论文,但是只对收费会员开放),专业点说如果你好好研究 UpToDate,再结合自身状况可以得到比很多专业医师更专业的治疗
但是这次查到的治疗方案都是普通的消炎、镇痛(对乙氨基酚)等,但是不妨碍你下次可以继续到这里查,一般买个3天的账号才几块钱
另外也推荐大家看默沙东手册(完全免费,有网页和app版本):
自己按压疼痛的地方确认在什么地方,结合平时的运动和习惯,是否恢复也可以通过按压和发力来确认
非甾体抗炎药(non-steroidal anti-inflammatory drugs,NSAIDs)又称非类固醇抗炎药,简称非甾体类,是一类具有解热镇痛效果的药物,在施用较高剂量时也具有消炎作用。
NSAID 包括布洛芬(Advil、Motrin IB 等)、萘普生纳(Aleve、Anaprox DS 等)、双氯芬酸钠和塞来昔布(Celebrex)
非甾体抗炎药中,属阿司匹林、伊布洛芬、甲芬那酸、萘普生最为著名,在绝大多数国家都可作为非处方药销售[4]。
对乙酰氨基酚因其抗炎作用微弱,而通常不被归为非甾体抗炎药,它主要通过抑制分布在中枢神经系统的环氧合酶-2,以减少前列腺素的生成,从而缓解疼痛,但由于环氧合酶-2在周边组织中数量较少,因此作用微弱
抗炎治疗 — 尽管抗炎治疗多年来都是肘部肌腱病的主要疗法,但支持性证据仅来自成功个案和极少数研究。在医学界对肌腱病有了科学认识之后,抗炎疗法对肘部肌腱病和其他慢性退行性肌腱病的作用也出现了争议。抗炎治疗包括冰敷、NSAID、离子透入疗法和注射糖皮质激素。对于LET,冰敷联合离心力量及柔韧性训练并未优于单纯离心力量训练[51]。(参见上文‘病理生理学’)
体外震波治疗和其他电物理疗法 — 声波已用于治疗慢性LET。总体而言,支持体外震波治疗(extracorporeal shock wave therapy, ESWT)和其他“电物理”疗法的证据并不令人信服,所以我们不予以推荐[82]。该操作通常会令患者不适,但有些研究显示ESWT有一定益处[83],但也有许多研究未发现ESWT有益[84,85]。
“网球肘 ”(TenniS Elbow)又名肱骨外上髁炎 (1ateralepicondylitis),以网球运动 员发病率高 而得名
广义 的网球肘可分 为具有不同临床特点的四个类型 :
自付二:对有自付的药品、检查费收取自费部分;比如药品:10%或50%;检查费:8%;材料费:30%;
自付一:根据下图,报销比例是90%,也就是你还要出总医药费的90%;但是要注意总医药费要减掉自付二的部分
举例:一张发票开了一盒泰诺(酚麻美敏片) 13.47块(乙类清单 10%自付),还有一盒没有无自付的头孢 5.17块,共18.64
最后发票显示自付二:1.35 就是13.4710% ——这个10%是因为该药有部分自费,自付一:1.73 是 (18.64-(13.4710%))*10% ——这个10%就是达到起付线1800后报销90%
如果你没有达到起付线,就是100%自付,那么不存在自付二,付款金额全部显示为自付一
]]>这是一道BAT 的面试题,针对的是应届生,其实我觉得这种题目也适合所有面试人,比刷算法题、八股文要有用、实际多了
给你几天时间自己在家可以借助任何资源用测试工具Sysbench 完成一次MySQL数据的性能测试,并编写测试报告(自行搭建数据库)
sysbench压MySQL常用有只读、读写、只写、update等6个场景
这个候选人把他的结果发给我看了,我看完一惊要坏事,这个结果估计要不及格了
他用 sysbench 跑了一下只读、读写、只写等场景然后截图就没有了!
(如上图,大概就是6/7个这样的截图就没有了!)
我看到这个结果是很震惊的,你希望面试官挨个去看截图?最起码要有测试结果表格当做结论汇总吧。
如果你不知道怎么做可以先去搜一下别人做的测试报告,你可以按照别人的测试流程完全走一遍,基本算是模仿,要有结论的话也能得60分。
每个场景增加1/8/16/32等并发,然后按照6个场景不同并发做成一个表格,并观察rt、cpu的指标最后汇总形成图表、给出结论分析,比如拐点在哪里、为什么
我觉得这个面试题好就好在这里的分析可以无穷展开,适合新手也适合多年的老手,任何结论理由你都可以写上去,只要有理有据有分析
给自己出一个拟题,比如对比5.7和8.0的性能差异,8.0相对5.7在哪些场景有优化、优劣势,比如这个测试报告
比如官方说的8.0在全局锁、pagesize等方面有些有优化,那么就针对性地设置场景来测试这些功能。
比如这是如上链接测试报告中间有数据图表:
最后有结论和分析:
之所以有80分是因为超出面试官的期待,给出了一个更高级的结论,面试官肯定很愿意约你过去谈谈
也许有,但是不好说,80分那个就是优秀很好了,挖掘能力强的应届生会搞出来(肯定没有这么细致和周到,但是有几个关键点的结论就够80分了),再想出彩一点可以根据这个我的星球案例 https://plantegg.github.io/2021/05/14/%E5%8D%81%E5%B9%B4%E5%90%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%98%E6%98%AF%E4%B8%8D%E6%95%A2%E6%8B%A5%E6%8A%B1NUMA/ 去搞几台物理机开关NUMA 验证一下,然后给一个对性能影响结果的测试数据报告
给出不同的MySQL参数在不同Intel 芯片下性能的差异报告:
这种结论抛出去肯定会让面试官惊到,并对你刮目相看,至少说明你能在某个点上可以钻研很深,到哪里都要的是火车头,而不是普通工程师。
从一个简单的面试题就可以看出应试人员的主观能动性,最起码你要会抄,先去抄别人的测试报告,然后验证一遍然后思考清楚每一个数据的原因(面试大概率会问)
但是大部分工程师都想临时抱佛脚,其实面试官可能会知道你不懂,但是希望看到给你几天你的深度挖掘和学习能力
最后可以从一个问题深挖、总结能力上能看出来候选人的天花板上限,而我们大部分时候都是凑合可以、又不是不能用,逼着自己向前精进一步总是很难的。
]]>我的星球介绍
这篇是关于我星球里的内容、目标以及如何达到这个目标的一些概述
本星球致力深度分析各种程序员领域疑难案例,通过案例带动对基础核心知识的理解,同时强化动手能力
一年星球没法让大家称为顶尖程序员(我自己都不是),只是希望用我的方法、知识、经验、案例作为你的垫脚石,帮助你快速、早日成为一个基本合格的程序员。
在星球一年的时间你能学到什么(跟着做一定可以学会的):
如果你发现看文章、做实验有些障碍,我特意录制了视频做演示(如果你基础好,看文章就能看懂并把实验做完,其实没必要看视频):https://articles.zsxq.com/id_blqwkgux7i0a.html
视频内容目前已经完成了:
我在星球内一直强调视频不是高效的学习方法,因为你没有办法仔细思索、随时前后反复看等等,看完视频容易形成学懂了的错觉实际很快就忘了,但是我录完这些视频看大家的反馈我发现视频也有优点那就是:很直观、门槛低等,但是一定要注意一个错觉:以为看视频看懂了。但实际就是看视频看完了忘得比看文章快多了,所以看完视频一定要再去实验一下,实验所需要的素材基本都在星球内有了,代码等我都放在了github上
有些技能不好描述,或者说是一些暗知识,我们尽量去讨论这些技能的逻辑,同时对一些特别有效的工具、知识会重点突破,这些恰恰是我希望你们最终能掌握的:
知识总是学不完的,况且大多时候我们有了知识也解决不了问题,所以我们更注重能力的训练,比如这个提问:https://t.zsxq.com/0cfBnpmLw
如果你发现这个节奏你跟不上,那么就先去看视频,然后再按这个节奏来,如果还不行可以再去看视频,如果视频看不懂可以到微信群里讨论或者就视频里的哪个点提问,如果觉得看懂了,但是还是没法独立实验,那可以这个看懂了还是错觉,或者是基础缺的太多了
请先浏览星球专栏里的必看资源以及学习方法,做到做会而不是看会。另外每个主题后面的留言也很有价值
本星球大部分理论指导部分请看视频:https://t.zsxq.com/0dF2WvzEF (5-10节共90分钟),视频中的理论要和案例结合
星球选用的案例尽量典型普适性强,代表基础组件基本原理等知识。
分析手段尽量通用,分析过程一定要逻辑合理每个疑问都能回答清晰。
搞清楚一个案例基本能横扫一个领域,其次在一个案例后再带3/5个相关小案例可以帮你丰富场景,多角度理解
基于以上目标一年内选择了如下4个案例:
详细描述请看这里:https://t.zsxq.com/0cyPswpVB
慢就是快,做会而不是看会,无招胜有招
慢就是快指的是不要贪多,而是要彻底搞懂一个问题、一个知识点,让这个点成为一个支柱长成体系,贪多往往啥都没有掌握
做会而不是看会:程序员是工程类(也有科学家,但我们CRUD boy肯定不是),尤其像网络包、CPU流水线都是看不到无法感受,所以建议你去抓包、去做实验体会、触摸到每个包就能够更好地理解,所以星球强调做案例
无招胜有招:尽量找我普适性强的技能,比如ping ping神功,比如抓包,比如Google搜索,你会反复看到我的案例中使用这些技能
多和以前的学习方式对比,学了一大堆几个月后全忘了,学了很多不会解决问题,学了很多但要靠反复刷。你不应该继续像以前一样忙忙碌碌但是收获很小
最好能有自己的总结输出,比如博客文章,写文章是一次最好的总结,不一定要发出来,也不一定一次写完美了,我经常修改7、8年前的文章,因为随着经验的丰富有了更深入、不同的理解,这时不要写一篇新的,我都是在原来的基础上修改、扩充,这才是体系建设
这是大学刚毕业几个月的新同学写的博客:https://yishenggong.com/2023/05/06/why-does-my-network-speed-drop-cn/
https://yishenggong.com/2023/05/22/is-20m-of-rows-still-a-valid-soft-limit-of-mysql-table-in-2023/ 你可以比较他加入星球前后的博客文章(20230315 加入星球), 第二篇是英文版上了hacker news前三
我观察到的学员成长好习惯:
欢迎大家提问,越具体越好
比如这个问题就很具体、很好: https://t.zsxq.com/0enzptS47 (千万不要微信上问,回答了也没有价值)
我自己一个人写写出来的东西难免自嗨,但是如果是你碰到的实际业务问题我觉得就更有代表性一些
提问肯定尽力要把问题描述具体,好重现,典型的就是之前 aws 流量降速导致MySQL QPS下降,提问的同学做得特别好的就是把这个问题自己反复分析后发现是网络流量被限速了,然后问题就很容易描述和重现,最后一大帮人帮忙分析问题,最后的结果大家都很开心学到了东西。问题在这里:https://articles.zsxq.com/id_iq5a872u8sux.html
你要是通过星球里的方法帮你解决了实际问题这是星球的最终目的,我当然最开心,如果你提了一个你工作中的问题大家一起帮你分析、讨论并最终解决了这就是最好的N对1的私教训练——觉得适合你的能力提升
我有时候绞尽脑汁写了文章然后大家不关心,有时候一个普通问题似乎大家都很嗨,我也喜欢能让你们很嗨的问题(即使我不懂也可以一起讨论)
必看(一定要看的,我尽量控制必看的少)、实战案例(年度计划一定要分享和搞清楚的案例)、动手实验(做会一直是本星球的重要原则)、学习方法(磨刀不误砍柴工),剩下的就是按类别分比较好理解
星主自我介绍:https://t.zsxq.com/0c33AXrCi
或者在推特找我:https://twitter.com/plantegg
个人博客:https://plantegg.github.io/2022/01/01/%E4%B8%89%E4%B8%AA%E6%95%85%E4%BA%8B/
博客存放在github,图多的文章会慢一些,可以刷新几次。
建议大家多用PC版星球( https://wx.zsxq.com ),第一次记住密码后也很方便,主要是打字看图更合适些
画图工具和素材:https://t.zsxq.com/0enaoOUBp
知识星球:https://t.zsxq.com/0cSFEUh2J 或者看看星球的介绍:https://plantegg.github.io/2023/05/10/%E7%A8%8B%E5%BA%8F%E5%91%98%E6%A1%88%E4%BE%8B%E6%98%9F%E7%90%83%E4%BB%8B%E7%BB%8D/
]]>基本逻辑:保险是保意外的,你想赚钱就去买房子、股票、基金、做生意(不是说这几年哈)。消费型的保险(比如人身意外伤害险、车险都算)才是保意外,以小博大,当然也是保的小概率。
任何一个保险扣除运营费用就是返还率,相互宝运营费用10%-8%,大多人没概念,这是极低了,没有营销成本,10%用在理赔的时候调查考证。但是一个理财型的保险20-30% 给一线销售,这就是为什么这些保险人反复、耐心跟你讲要买保险,为你服务,当然这是成本,值不值你自己考虑;这还没完,还有上级、经理、公司的运营工资等,要不保险公司凭什么养那么多领导家属;所以这是保险公司核心收入来源,也必然导致了价格奇高。
理赔很复杂,没事的时候当然好,真要理赔各种你没想到的事前告知,你连我这几百字都不愿意看,保险公司那条款你就更不愿意看了。所以我推荐意外险,死了就陪那种简单些,越复杂的你越搞不懂。卖保险的人是不会跟你说那么清晰的,实际上他自己都搞不清楚,真到了出险才是真正的考验!
肯定是给创造家里主要收入来源那人,保险其实是给活人的福利,你给小朋友买,妈妈挂了,他惨不惨?收入一下子也没了,保险能给他生活费、学费?
如果给妈妈买,你看至少保额还可以供他几年。现在的父母觉得自己有爱、爱娃,当然是给小朋友买,所以我说是错的
你别拿有钱人人都买来扛哈。
重疾险本来是挺好的,出险直接给钱,是医保外的补充,正如我上面所说赔付率太低了,你还不如把保费存起来,赌概率。
这个自己想想
保险大家都需要,都希望有,但是保险行业是最需要革命和精简的,比银行还夸张,所以我不会花太多钱补贴这帮蛀得太厉害的蛀虫
昨天晚上Review个税到很晚,终于找不回来70%,这里确实有需要补税的地方;但是还有一些抵扣给我漏了;
我这次多算主要有一个2022年的bug,这个bug导致当时要退我几万税(系统自动自己算Bug),我大喜装糊涂,各种配合税务局提交资料,最后税务局人工Review的时候发现了这个bug,当然钱也不会退我,不过打电话跟我解释了,我也装糊涂就过去了
结果今年这Bug确实修复了,但是他娘的修复过头了,导致我多补70%的税,现在我只需要补30%,开心多了,这30% 是预期内的
毕竟我从2019年对个税申报太熟悉了,如图是我研究后的一些经验
几个省税的点:
1)大部分情况下奖金、工资分开计税税更少,有极小概率合并计税缴税少(比如工资低奖金高、比如奖金落在盲区的话合,因为利用了工资税扣减数不用除12)
2) 目前奖金、工资可以合并也可以单独计税,二选一,默认单独计税——不懂就在个税app上申报的时候两种都试试,哪种缴税少就用哪种
3) 股票比年终奖少扣税,同样100万,股票收入到手比年终奖多了17万(因为股票税没有盲区)
最后附送一个案例(如图),100万年终奖和100万股票收入的差别,同时100万年终奖跟工资合并计税税更少; 同时如果100万年终奖采用合并计税也比单独计税拿到手要多
目前一个人有机会将税率做得比较低,就是把收入分成3份:工资、将近、股票,算下来几乎可以按综合年入的30%以内缴税(高管个税有其它优惠我粉丝都是屌丝就不展开了,很多高管缴税可能比你少——比如去成都、天津,现在多了海南)
另外因为2023年8月才出通知提高23年的附加抵扣额度,所以今年几乎每个人都要退税,如果没有退就好好Review以下,已经提交了的还可以重新退回来重新算;2022年、2021年算错了的现在还可以申请要回来! 现在打开个税APP 去Review,如果有找补回来记得给我发红包。如果你今年退税了辛苦评论区说下让我开心开心
]]>方便大家对不同的CPU混个脸熟,有个整体概念。本来发布在知识星球,但是知识星球上格式看起来太影响阅读效率了,所以特意拿出来发到博客上
简单查看CPU我一般用 lscpu(默认自带) 命令,或者用复杂点的工具:hwloc 工具安装:
|
|
安装后生成结构图片命令:
|
|
生成字符结构,不要图片:
|
|
后面展示的都算是整体机构,所以还会附带有内存怎么接(一个多少条,每条多大,一个Numa node插了几个物理内存条),这些我博客上都有,就不展开了。一般都是对称的(每个node、socket对称,不对称肯定发挥不出来好性能)
大概是Intel 2012年的主流服务器CPU
|
|
intel 还有一个自带的工具:cpuid-topo 可以看结构,以下是其中一个Socket的展示
购买的AMD版权设计等搞出来国产的 x86 架构
|
|
L1、L2太大了,好吓人,这么大不符合逻辑(太贵,没必要)
|
|
index0/index1 分别代表啥?
海光为啥搞了8个Node,请看:https://plantegg.github.io/2021/03/08/%E6%B5%B7%E5%85%89CPU/
图片可以看高清大图
对应的字符结构
|
|
以上是海光的7260,还有一个CPU是海光 7280:
|
|
作业:7260和7280的区别是?为什么搞了这两个差异很小的CPU?
|
|
还记得7260是3个物理核共享一个8M的L3吧,计算机的世界大多是1、2、4、8,看到3我就觉得有些别扭。评论区告诉我为什么会搞出3个核这样一个奇葩设计?(星球图解专栏里有答案)
整机256核,一路128超线程,单CPU 64个物理核,很猛了
|
|
这台机器改下BIOS设置
白色Channel 那里可以选择Auto/Die/Channel/Socket, 选择Socket后得到如下Node 结构:
|
|
鲲鹏是ARM架构,一般都没有超线程,因为指令简单流水线较流畅,搞超线程收益不大
|
|
图形化查看(打开大图,和前面的intel 对着看)
思考:看如上鲲鹏机器的结构你应该知道网卡、硬盘怎么插放的了吧,然后想就近搞点优化也是可以的
飞腾的解读留给大家当作业
|
|
飞腾的核有点多,我省略了一些
|
|
当练习看看,随便看看
|
|
希望通过具体又不同的CPU案例展示,让你对CPU的结构有一些整体认识
请问:Hygon C86 7260 这块CPU每个Die的L2、L3分别是多大?
请思考,最近10年CPU的性能没啥大的进不了(如下图红色部分,每年3%),但是这么多年工艺还在进步,集成的晶体管数量
//这张图每一本计算机体系结构的教材都有引用(没有的话这教材可以扔了),你知道我博客里哪篇文章放了这图吗?从这个图你还能解析出来哪些东西?
]]>最近网上看到很多讨论搞副业和远程工作的,我也说点自己的经验+看法
当然这完全是出于个人认知肯定不是完全对的、也不一定适合你,看看当个参考,经验重在真实
年轻人最好的副业就是做好本职工作,深耕多积累自己的专业方向,只有当你在主业上再也无法精进的时候可以考虑跳槽或者副业, 搞副业相对适合大多年纪大的人,他们触碰到了自己的天花板,可以折腾玩玩等等
我搞过很多副业,多到我不好意思说出来。low到檫玻璃,大到开厂、买船,但是你看就是没去折腾抄房子(这些年只有炒房子的这个副业赚钱最稳、最快)。我也特别关心别人的副业、主业,熟的会打破砂锅问到底,所以下面说的只保证真实
通过SEO接了一个国外一个订单,交给长三角的工厂代工,赚了几十万,一次性,几乎没有成本
当时帮一个做工厂的朋友做网站,域名空间都是我掏钱(要给我我没好意思要,本身不值钱),让留个邮箱厂长没有,后来留的我的。
然后来了几个咨询的介绍给厂里了,最后成了两个客户。但是有一个韩国客户(采购是广州一个提篮子的公司),去厂里谈了几次细节谈不好,我就出马给把细节、打样、交货谈好了。
最后做好后发货直接到韩国,发一次运费几万块(到付),其中有一批压坏了点那个区的顺丰经理过来道歉、给定做包装箱……
缺点是做完就没有了,那个产品不具有持续性,如果可以持续我应该能继续搞,另外借着这个客户去厂里跑得多,也发展了一些其他客户利润太薄加上后来真个行情不好就实在做不下去了,产品烂大街没人要了,珠三角那个生产模仿能力都太强了
之前介绍给厂里的两个客户,厂里自己对接的,其中一个厂里赚了一些钱,另外一个飞单好几十万,人家直接注销公司赖账的玩法,所以你看风险很多。不过要是去接这个单就不会出现这种情况,你最后尾款飞几千万把块我是有预期的,整个一个订单一分钱都没拿到简直就是傻子做生意,也纵容了坏人
比如很多人靠白嫖样品吃饭,我的策略是:样品、打样都要收钱,但是正式下单就抵扣货款,这么做能淘汰90%的虚假用户,节省自己的时间。比如便宜样品可以免费但是邮费到付、你亲自上门当然可以送几个。
做星球的话10万粉丝算是凑合,百万粉丝洒洒水啦,几万粉丝很痛苦
知识星球不适合IT技术类,他们有平台的流量,全靠自己运营;相对来说极客时间、慕课之类的能有平台给你导流;
星球的优点是入门门槛低
开星球的时候就承诺过了,要公布数据,当时也有一部分原因是对运营一个星球的数据有着好奇
9个月的星球运营500多成员,一年收入大几万,这还只是第一年,主要靠我的推特3万多粉丝里面划拉人员过去,第二年就不会有这么多成员了,因为你不可能一年再涨2万新粉丝
我的粉丝转化率是2%,算是还不错的了,所以如果你有10万粉丝大概能有1000-2000铁粉,那差不多一年能靠这些有个20来万的收入,所以算还凑合,可以简单养家。
上点我的星球运营真实数据,先看最重要的收入数据
星球刚开通前三个月收入最高,把一年的收入都提前拿走了,我这虽然才9个月,后面三个月也不用看了,几乎可以忽略:
运营效果,来估算转化率
我的星球讲究干货,宁缺毋滥,所以也没有其他星球常用的运维手段:作业、打卡(我恨死打卡这种傻逼行为了)
续费的话,我的星球是本月15号开通续费,我也没发通知,居然有人续费了,我猜应该是平台自动通知的:
这个门槛最低,你看到好的产品复制链接,到淘宝联盟上做下链接转换:https://pub.alimama.com/?forward=http%3A%2F%2Fpub.alimama.com%2Fportal%2Feffect%2Forder%2FoverviewOrder%2Fpage%2Findex.htm#!/index?curValue=nav_0&forward=
到处发然后就能拿佣金了,目前国内个人带货扛把子就是个程序员,还是个高中毕业考不上大学找个培训班入行的程序员,会用Delphi写个群发工具,然后管理一堆微信、QQ群;让别人去帮他带货他能提成,这个段位又高级了一层
只靠自己的朋友圈肯定是不行的,起步得是百万粉丝才行,或者你有渠道总能搞到好的货品
给你们贴个我2023年10月的带货数据,当个参考,就是在3万粉丝的推特上带的货,转换率肯定是很惨的,为这131块的佣金你可以搜搜我发了多少推:
这个工作完全可以远程——算是你们理想中的远程工作吗?但是这个市场必然只能容纳很少的人,搞好了是可以发财的 :)
如果你口才好、煽动力强不去搞自播带货都对不住自己
副业就是副业,要不怎么不叫主业呢?真搞好了、容易搞好必然有更多的人进来把他从副业做成主业!
先把主业搞好,尤其是年轻人。副业超过主业的毕竟是极少极少,还有点运气和背景成分
投入小(钱、时间都算)可以轻度参与混点经验,但不要抱太高期望
比如我就做过统计:
拉了一下记账软件上历年的数据,古早年代没记账就没有了,最近几年收入的话95%以上都是工资性收入,投资大概率是亏钱的,房租能有点、外快能有点,放到整体几乎可以忽略
开支的话也他妈主要是买房+房贷,如果不考虑首付+提前还贷倒是占比不夸张,日常开支真用不了多少钱,万幸几乎没有医疗开支
主业确定没法精进、跳槽之类的,这时可以考虑下副业,当然如果你碰到了副业的“好机会” 也可以尝试一下
先试试做做博客、公众号,看自己能运营到多少粉丝,你平时上网刷口水文章也是打发,然后试试带货
程序员方向基本不来钱,虽然这些行业很赚钱,但是这里也聚集了相对聪明人,你能搞他们也能搞相对更红海一些
可以跳出技术方向或者横向关联的方向多动动脑子,门槛低竞争就必然大,比如教英语和教程序员肯定英语的市场大多了
组织活动,比如组织大家打羽毛球、滑雪,羽毛球需要水平差不多的、人多一点才好玩,一般去场馆8折拿下场地,然后大家AA费用,赚这2折的差价,一次一般能赚80块,一周多组织几次,搞得好的话一个月也有2000块,关键是顺便自己打打球,真当副业的话也很香!再要多赚也很难,不过可续性很强
上次从黄牛手里买了个医院的专家号,2000块,你以为他们有渠道?其实他们建个微信群,找一堆有闲缺钱的人,接到需求了就到群里喊一嗓子,谁有本事抢到了从2000块里分几百,这种专家号根据难易程度从几百块到几千块,真是市场化了
当然还有一些灰产黑产大家就不要碰了我也不说了,大家耗子尾汁,赚钱是应该的但是要合法
写得很零散,没有什么详细的分析和套路,就是罗列事实和数据,你可以根据自己的情况来分析考虑
你要有什么好建议和经验欢迎在推特上 @plantegg 给我留言、私信,特别好的我会收集到博客上,这篇博客我会持续更新……
最后放个我星球的广告:
]]>视频版本50分钟,不含问答,建议看文字版,这是视频: https://weibo.com/6033438343/Nxw2Fj2oN?pagetype=profilefeed
到处都是私域、卖货、视频等,好的文字不多了,这篇对应视频的文字版找起来不容易,所以特意在我的博客上备一份(我的博客极少极少极少发别人的东西),也希望你备份一下。
王强是新东方合伙人,口才一流、演讲技能一流,当脱口秀看吧。
我就只能羡慕这种智商一流的人,这人智商在北大里估计都是前10%,而你我是北大都考不上的,所以他说的方法你就看看好了,不适合你,但值得你从中间提炼适合你的不分,读经典拿书,读不懂就不要像他一样死磕,找些浅显的、增加你经验的书先看看,回头再来读经典
但大多时候我们都不知道哪些是经典,对别人是经典对你还是经典吗?
这人是个程序员,学了C 和CPP,对你有点参考意义
在我的知识星球就一直强调:不要跟着信息流跑,多去看最早发表的东西(多年沉淀的干货等等)
下面是正文,扯淡栩栩如生,那不是重点。我就不给大家划重点了,都是重点:) ,文字版来自这里:https://book.douban.com/review/10286767/
王强:谢谢小平。因为小平在读书上花的时间比较少,因为我都替他读了,他只问我结论是什么,他的知识并没有落后,而我视力在衰减。当然老俞,当年我引他进入读黄色小说的境界,至今老俞还不肯自拔,他是黄种人的代表,所以他成功了。作为人生,我今年51岁,我和老俞同年同月生,不是同一天,也不是同一个地方,因为老俞比我大一周,小平比我大六岁,是我的兄长,当年克强同志是北大团委书记,他直接受克强同志领导的北大团委文化部部长,我是直接受徐小平同志掌管的第一任北大学生艺术团团长,我当时管的是英达、英壮这样的人。而俞敏洪是北大最有特权的艺术团的观众,因为经常拉幕的时候缺一个人,我们说老俞能不能帮帮忙,老俞说能让我看吗,我说当然。所以从此老俞锻炼了强大拉幕能力。所以任何细节不要忽略,都是人生。
我今天想跟大家分享为什么读书在人的生命成长中非常重要。我这个题目叫”读书毁了我”,很多读者没看到这本书的内容就开始评论,说我是标题党,撒狗血。我说不是我撒,因为当年我的很多文章结集的时候徐晓,她是中国最伟大的女编辑之一,被称为京城四大美编,美女编辑。当年我说马云怎么有领袖魅力,他有领子有袖子,但没有领袖魅力,走到街上城管一定第一个扑向他,因为连人长的都不一样,像是从外星回来的,而俞敏洪长的就跟季羡林一样,就像去外星的人。小平虽然是天使,但是从体重来说,给他四双翅膀他也飞不起来。所以人啊,当你不知道要做什么事情,当你做的事情不能带给社会意义的时候,当你做的事情的意义不能给人的生命产生共鸣的时候,你的存在实际上是被人忽略的。
我现在自豪的是,我现在经常回忆,北大这个地方怎么产生企业家?因为我是内蒙古来的,我以为是学术的殿堂,清华可能产生企业家,因为他们搞科技,高科技,北大当年我们就是精神自由的三角地,都是自焚的地方,它只是结束肉体的地方,让灵魂再生的地方,从来不是做什么上市,这些好象与北大没关,但是人生经历这么多年,我发现北大为什么产生这样的人。
我就拿32楼举例,我们住的16楼没了,当时我和老俞作为北大年轻教师住在16楼,但是拿32楼文科男科楼讲,当时北大英文系来说,我们住在二层,这些年一过,发现诞生一个伟大的企业,那就是在教育界的俞敏洪为代表的新东方。再往第三层,我忽然发现当年有一个来自山西的青年,天天在水房里光着上半身,一盆冷水浇下来,唱着夜里寻他千百度,你在哪呢,天天念百度两个字,因为他是北大图书馆系的,后来诞生了百度李彦宏,当时哪能想到,因为从任何知识储备,他不能做企业,他不仅是学图书馆系,而且专业简直离成功太远,他是古典文献编目专业,清朝以后的事他都不管了,他直接奔甲骨文去了。所以他天天念where are you,那时一下雨雨水就没过膝盖,当时找不到了,where are you,搜索就开始了。
再往上走,四层楼住着北大中文系的,当年都是产生愤怒诗人,连名字都是愤怒的不得了,黄怒波。这么多年刮目相看,他要买下冰岛,他成为了中坤集团的创始人。更匪夷所思的是,北大中文系的女生楼里出来一个长相非常平和的人,她充满着激情,最后由于自己解决终身的情感问题,她就是后来创造了世纪佳人。这些人,是中文系的、图书馆系、英文系,这些与金融、融资、管理完全没关,但是我后来想怎么会出现这么一些奇特的企业,由这些人做的,我就想到北大给了一个东西,就是怎么样塑造你生命的东西,那是对知识的渴望、饥饿,超过了性本身。当年我们对性的渴望,但是校规非常严格,同性只能找同性。但是我们还没有得到同性方面的启蒙,当时洗澡堂,一个水龙头下,十个男生光溜溜的彼此互帮互学,那一个水龙头下十个手,像董存瑞炸碉堡的感觉。
但是我们就这么过来的,为什么我发现北大这个氛围是崇尚超越世俗吸引力的更伟大的东西,那就是对知识的诉求。我不知道你们现在读书状况什么样,整个八十年代北大最神圣的地方两个地方,一个是厕所,一个是图书馆,图书馆从早上六点,如果你不能到达写着邓小平题字的北京大学图书馆下面排队,你这一天与图书馆的座位已经无缘了,所以大部分人凌晨四点就起来了,然后带着一个冷馒头,从厨房吃剩下的或者从同学那偷来的,俞敏洪经常偷我馒头。然后借一堆书放在这里,睡也睡在桌子前面。所以当年读书氛围非常好,如果市场上出现一本书,你如果去晚了根本的得不到。我在中文系选了中国现代文学史,第一次讲到围城,我赶快到北大图书馆,没下课我就去了,但是没想到没了,结果等到快毕业的时候我才借到这本书,这就是当年北大的状况。而正是这样,读经典,读那些能够改变我们生命轨迹的那些书籍,成了北大人最后离开校门走到世界,不管你走到哪个领域,最后比别人走的稍微远一点的保证,因为那些书不是字,它也是生命,而这些生命比起你自己的生命来说,它能引领你的生命,它能型塑你的生命,所以我说这个世界上只有两种文字,一类文字是文字垃圾,(Informed )随处可得;但是有一类是非常好的,(Form you )就是它能够把你变成完全不同的另一个。所以我这个书题目叫读书毁了我,当年起的时候,徐晓给我提的题目,说这个题目在她心中好多年。她说你这个文字挺适合这个,我说”读书毁了我”,这个东西大家看到以后会非常奇怪,怎么会毁了你吗?她说毁就跟北京人说的,一团泥逐渐成型,就成了崭新的东西。我想如果毁用在这个意义上,它必须能够彻底摧毁你旧我,过去的我,狭隘封闭的我,然后诞生一个崭新的、开阔的、阳光的我,那读书就全部有了意义,这也就是当年北大为什么那些人天天想到的不是世俗的追求,但是到了世俗里一看,稍微一动他就得到了所谓世俗追求的东西呢?我觉得这是北大给了我们吸取信息的能力,分析问题能力,所以我今天想跟大家分析分析读书。
我当年在新东方接受采访的时候,我说要读书只读一流的书,做人只做一流的人。为什么这么说?因为现在信息充斥的海洋里,我们人生有幸,但是我们要读的接受的信息太多了,如何辨别书?什么东西该读呢?跟大家分享一下我读书的选择,第一,畅销书我坚决不读,不是我牛,看不起畅销,因为我知道我生命有限,已经51岁了,再向苍天借30年,我已经80岁了,所以我还有30年读书的时间,我只能读人类历史上没被大浪淘沙过的东西,所以我现在读书越来越往前读,中国的典籍越读越遇到先秦,西方也顶多读到二十世纪中叶,因为我觉得那个时候的人,他们创作文字,他们的文字是他生命的写照。比如说现在翻译小说,坦率的讲,我只选择那些真正的以生命完成一部译作的大家们的作品,哪怕这个作品并不时髦。比如说《悲惨世界》,李丹翻译,本来他可以成为另一个徐悲鸿,但是他们放弃了,几十年如一日,文革如此惨烈,李丹最后剩几卷没有翻,他的太太继续翻,这本著作我是一读再读。像朱生豪翻了27本莎士比亚的剧,但是你现在再读任何一本,哪能找到朱生豪当年用汉字表现出的莎士比亚。所以我常常更小平说,有一天我们一定要拍朱生豪的电影,这个电影叫做《莎士比亚在中国》,如果没有朱生豪,全世界四分之一的人不会第一时间知道还有莎士比亚,所以莎士比亚的墓地应该旁边有一个朱生豪的碑,多么伟大,四分之一的人口是通过朱生豪第一时间知道的英国还有一个莎士比亚。
所以我觉得读一流的书就要衡量,这个作家进入书前的状态是什么?他是为了满足市场的需求,所谓市场的利益,还是他倾其鲜血、生命和经历融入的东西呢?坦率的讲,我在北大整整呆了十年,做了四年学生,当了六年老师,离开的时候是英语系的讲师,当然我的宿命也从此定了,只能讲,没当教授,坐不下来,更没有博导那个肌肉。但是我作为见证,俞敏洪、小平他们当年都是如饥似渴的在读书,尽管领域不同。老俞主管肉体,小平是超越肉体和灵魂的东西。当年小平是我们当中第一个出国的,我记得那天下着毛毛细雨,小平当年住在北大小院,32楼前面的一个小院,最早北大出版社的地方,他住在那里,因为他是团委干部,所以有四合院的那种感觉。那说要离开了,要到美国,然后到加拿大去追求他的音乐梦,我就知道,他当时为凑足他的机票,他珍藏了作为任何一个学生很难想象的格罗夫音乐辞典,到处拍卖,他希望获得飞到美国的机票。他终于卖出了,用一半的钱请我在西门一个火锅店吃了火锅,最后大家挥泪离别,从此我步上小平的后尘,我也要到国外去,老俞也想步我们的后尘,但是国外暂时不需要他。
为什么读经典能够改变我们呢?文学的功能是什么呢?在我看,文学的功能就像我在序里说的,如果一个真正有力量的文字,它一定是能够对我们的审美产生奇异的再造,它对我们对真的追求有奇异的启示,它对我们对善的追求有如饥似渴的充电的感觉,所以我们对人类最高的价值,真的、善的和美的就会变成我们的血液,一旦人身体里有这三样东西,你在社会上走向现实中,你就不会轻易的被世俗的所谓流行的价值、暂时的价值,甚至非常糟糕的价值轻易扭转。我的这个读书基因从这开始,从我中学,我分两个阶段,一个是中学,一个是北大。我之所以能进北大,一半我认为是老天眷顾了我,因为大家知道,我是第三届大学生,小平是第一届,克强是78级,克强比你低一级,但现在比你高很多级,这就是人生最后不一样的东西。所以人生,体重太大,最后他也走不太远,所以大家现在要减肥。
高中我是来自内蒙古,我们那个学校在当地有一个叫包头的地方,都不算是优秀学校,但是为什么我能够走进北大呢?我忽然怀念起我当时在高中遇到的一批中国我认为最顶级的老师,为什么这些老师会到包头呢?感谢文化大革命,全是右派,一个一个发配到包头,结果被我遇上了,他们教会我全部的东西都是以他们各自的方式告诉我,真的、善的、美的,一定是从那些流传在人类时间长河里面没被淘汰的文字中,存在那里。你如果不断的在这样的文字中熏陶的时候,当你离开这些文字的时候,这些文字就变成了你的世界,所以从单词word到world中间只差一个字l,这个L,这就是文字、阅读和真正人生世界的完全最简单的逻辑关系。如果你读到的不是真文字,你遇到的不是真语言,你最后见到的一定是虚幻的世界,不是真实的世界。这也是为什么读书真正要对你产生作用,会产生什么呢?它一定要和你真正的生命融汇在一起,而几千百年来,没有被淘汰的著作,因为一代代人如果都这么选择的话,你一定要相信人类的选择,而不是现在市场的选择,更不是广告词的选择。所以这是非常关键的,我在序言里提到,去年我写了一篇文章,其中谈到葡萄牙诗人佩索阿,其中有一个诗写的是小河和村庄的关系,点清了我心目中文字怎么和你生命世界在一起,它必须对你生命产生极强的冲击,这个书才值得读,或者你真正领悟这本书,所以他的诗也是我从英文翻译过来的,他说,塔古斯河美过我村庄的那条小河,但是塔古斯河又美不过流进我村庄的小河,因为塔古斯河不是流经我村庄的小河。太美了,为什么?文字如果不属于你的村庄,它不能流穿你的灵魂,这个书不值得一读,而真正传统的经典有穿透生命力的这种力量。
我回到高中,我怎么认识到什么是一流的书呢?随便举个例子,我感谢文化大革命,把这些有文化的人推到内蒙古这个没文化的地方,教我古典文学的王传真老师,现在这些老师全都去世了,包括我大学的老师,大部分都已经不在了。但是这些高中老师教我古典文学的王传真老师,我第一次上他课的时候忽然发现什么叫大师,王老师告诉我们去新华书店买《古文观止》,中华书局第一版的。然后他说,你们要听懂我的课,这个假期必须做一件事,买来这个课本,他不讲,他拿出一套油印印出来的厚厚一叠古文,标点全部隐去了,他说你们这个假期玩完了以后,你就去读读我这个自己刻印出来的东西,然后按照你全部的理解,使出你全部的工具来给这些文章,按照你的理解给它们加以标点,我们在没有走进古文的世界,这个东西既刺激也似乎不可能,但是我为了下学期听懂王传真老师的课,我从我爸箱子里翻出他爸给他留下的当年最老版的辞海,我开始一个一个的,每天以十个字的速度往前运行,整整三个月我没干别的,因为越往前走越觉得这里深不可测,但是我的梦想是一定要听到王老师的讲解,因为这是他对我们唯一要求。结果就乱标点,但是我一天以十个字的功夫不断的往前进,最后50篇文章被我标点了。等到王老师到我面前给我面试的时候,他随便说了几句,我基本背出来之后,他说了两点,第一,你的标点全错了。第二,孺子可教,因为你全标了,就是你这个努力,我觉得可以。其实当老师,有的时候非常充满智慧,我们的胡校长胡适,胡适不判作文的,他没有时间,他有时间要搞新文化运动,作业算什么。但是据说,上作文的课每次都能给出学生成绩,后来据他的学生回忆,胡适判作业那是胡判,他今天晚上吃完饭,收了几十份作业,你写了文章,他开始把桌椅放在离靠门半米远的地方,泡一杯清茶,然后扔作业,哪个扔的最远最高分,为什么?写的多,不管你写的怎么样,你下了苦功。别人一扔不远,零分,写的不多。扔的远,够份量,一百分,胡判定就要开始出来。
而且我当时,我怎么走到英文这个道路上,一流的书上来直接读《古文观止》就可以了,看似很艰难,但是读完全部启蒙的古文书,我再读人教的那些太简单了,因为你的制高点不一样,一流书、二流书、三流书区别在这。比如英文,老俞就没有遇到我这样的老师,今天还说着印度人非常理解的英语,但是到了美国就崩溃了,因为他是印度籍的移民。我这个英文老师学俄语,英文不太懂。但是这个老师一片真诚,他知道该给学生什么样重要的价值,怎么让英文走进你的生命。上了他第一堂课,他觉得我的两个眼睛不断的盯着他,两耳竖着,像狼犬一样,他说你真心想学英文吧?我说当然,上您的课厕所都忘了。他说王强你到我办公室。当天下午在他办公室他说了一句话,他说从此你要上我的课。我说老师我就想学英文。他说我教不了正经的英文,我的底子我自己知道,你要想学真正的英文,我给你想办法,你就不用上我的课。第二天下午4点,下了自习,他把我叫到他办公室,从黑皮兜里掏出旧报纸包的东西,把慢慢打开,一打开,我一看,是一个断了一角的黑色的绞盘,唱盘,叫LP,大唱盘,你们现在连CD都不用了,那个大唱盘这么大,他说王强你要跟这个学,这是什么呢?这是我从废品站几年前搜集到的东西,它是BBC英国广播公司出的一套经典英文教材,从明天起,每天下午四点你只要答应我一件事,不要回家,来跟我学。后来我就非常兴奋,第二天我拿到这个光盘以后就跟着他,他把我领到学校的广播间,那时候他把团旗往窗户上一盖,门外面挂着闲人莫进,正在录音。然后他用当年我们中学唯一的手摇唱机,跪在地上,他一边给我摇,一边让我赶快重复,而且说你这个课本永远在我手里,等到你全部的课本能够背答入流的时候,你就成就了。结果他做了一件事,每个礼拜都这样,最后倒背如流的时候,他把这页撕掉了,所以我这个课本越学越少,最后只剩下封底的时候,他说王强你可以毕业了。我忽然意识到,我离开了文字的课本,但这些东西全在我身上,所以等到我到北大,作为英语系的学生第一年入的时候,在我们班50个人中,只有我说的着流畅的英语。为什么?他们不知道来自一个内蒙古包头的,别说英语,汉语都不沾边际的,说蒙古话的人,能说如此好的英语。其实我没有学任何东西,就是破唱盘和破唱机,一摇、一摇,摇过了一两百页的篇幅,这些篇幅被老师扔进垃圾堆的时候,我发现他让一流的英文教材完全引入到我的灵魂中,我感谢他。
教我历史的老师让我有了进北大的冲动,为什么?他是南京大学太平天国专业毕业的,学了五年,最后被打到包头,他讲历史,我听的如痴如醉。这个老师爱流鼻涕,历史长河,源源不断。而且这些老师,我不仅跟他们学读书,我从他们做人也学到了品性,就是一个字-真,最崇尚的就是真。这个老师非常有意思,他看我非常好学,他希望我每个礼拜三天到他家,那时候肉是供应的,那时候我已经是中学学生,老师为了让我安心在他家读历史著作,在他的引导下从《左传》开始,一篇一篇给我解释,每个月他家四个人,一人二两肉的份额,炒完以后只是我俩来分享,所以我非常歉疚。他说王强你要学好知识,肉体先要活着,他说我觉得你是可培养的,他展示了一流思想和一流文字真正的胶合。他上课非常有特点,从来不备课,这样一个顶级的老师,在我们学校从来没评过优秀老师,所以优秀是靠你真正生命才能支撑的。而且这个老师从来不服学校的规矩,从来不备课,他觉得跟其他老师没法备课。我记得每天早上九点都是历史课,大冬天穿着棉袄,历史书插在裤腰上,带着历史的温暖就进来了,而且第一个动作就是背向我们,掏历史,那是他的故事,他对知识如此娴熟,书没有打开一页,因为历史都在他的心里。而且他讲任何一个孤零零的事件都要放到更大的范围,讲完五四运动,他一定看看亚洲在干什么,欧洲在干什么,全世界在干什么,我们通过上中国史已经连通了世界,从此我才知道原来读懂中国史必须放在世界历史的框架中才可能。这样的老师简直让我叹为观止,就是他一句话让我升起了北大梦。他说我这个岁数这辈子实现一个梦想没戏了,什么梦想呢?他说我是学历史出身的,但是我对历史上的宏观描述,社会主义、共产主义的发展描述我有疑问,什么是社会主义,什么是共产主义呢?当时国内翻译说,社会主义是各尽所能,按劳分配的社会,这里各尽所能,但是按照你能够多做多得,能够给你分配你应该得的东西,这是社会主义分配原则。共产主义当时分析说,各尽所能,按需分配,他说同学们,作为我一个学历史的人,我的历史意识告诉我这个翻译不精准,如果共产主义和社会主义,一个按劳分配,一个按需分配,都存在”分配”的话,这两个社会没有区别,按照我的理解,那个时候人类精神极为发达,那个世界应该是各尽所能各取所需的时代,你自己决定你贡献什么,你拿回什么,这才是他向往的共产主义,和社会主义你需要我给你,不需要我不给你,这个没有什么本质区别他。他们说你们将来如果报答我作为你们的师恩,你们如果想学外语的话,读读马克思的原典,告诉我这个是不是对。八十年代的时候,所有发达国家,最后管理这个国家的都是学文的,学文的人可以看到全部,甚至看到没有存在的东西。所以你们学文的人应该比学理的更加聪明。后来我带着这个准备报考北大中文系,因为当时我的作文非常好,他说王强你千万别报北大中文系,你的中文已经完全达到了自学成才的程度,你将来要毙掉所有北大中文系的学生,你只需要一个东西,比他们多学一种语言,就这句话让我改了志愿,变成了英文系,因为老师告诉我,你看世界要多一种语言,你的世界就会宽广一下。
就是这样,我最后终于改换了志愿,到了北大英文系。我到校第一件事就是搞清楚,马克思论断是不是我的老师想像的,正好朱光潜先生翻完经济学手稿我一看与我老师的论断一字不差,社会主义分配原则是各尽所能按劳分配,共产主义一定会达到人类精神高度发达和自由,然后各尽所能,各取所需,我告诉我老师消息的时候,他说你真是我的学生。就是这样一个老师,他让我知道,历史你要读懂要站在什么高度。
再讲一个例子,教数学的老师,南开大学数学系毕业,我当时非常讨厌数学,我喜欢文,我们班一大半学生学不懂数学,但是只有这个老师的课上没有人上厕所,为什么?他对数学知识的了如指掌,比如他讲几何,他只带三只粉笔,从来不带教具,他要画个圆,先点圆心,往后一站,再往上一扑,动作一点都不停,你下课以后发现这个圆在哪衔接的不知道。他说画40几度角,他画完以后,很多学生下来拿两角尺去量非常准。所以后来上他这个班的学生,连不喜欢数学都要盯着他,因为觉得这是艺术课,结果这个班最后90%多的人都进了理科大学。当时令我难忘的是,八十年代,那时候我记得是考大学前一年,出来一个陈景润,数学家,非常伟大,突然光明日报第一版发了《哥德巴赫猜想》,当天下午我平生第一次知道有讲座的形式,说让大家带着板凳到操场上听讲座,讲《哥德巴赫猜想》,前面部分讲什么是哥德巴赫猜想,第二部由讲汉语的老师讲这个报告文学为什么是优秀的报告文学。结果我们坐着小板凳,太阳底下,第一次听什么叫偶数等等,听完以后没听明白,但是觉得陈景润很伟大,后来我的数学尽管是考文科的,那年我还考了59分。我们那年,80年和你进清华是同样一个卷子,77分就可以被清华大学数学系录取,我们59分,我们这是参考分,但是俞敏洪参考分0分,太悲惨了,一点没参考价值。
就是那个东西把我引到数论,所以在中学时我就读华罗庚、王袁的这些论著,懵懵懂懂,试图要读点爱因斯坦的著作,而且读了徐池报告文学我知道优秀报告文学是这样产生的,以后我也写了无数的小的报告文学,结果没有一处发表,所以到了北大之后我一直想写诗,我的诗集叫《野性的14行》,俞敏洪最后也写诗,他是北大最后一个没有自焚的未遂诗人。我们当年带着这个,知道了各个领域,要想走进这个领域,必须站在最高的地方,当时至少最优秀的地方我才能一览众山小。
到了北大更不得了,因为我们见到的那些人,都是大家见不到的那些大师级的人物。比如我是英语系的,英语系所有泰斗都是直接教过我们的,像李副宁(音)先生,不论刮风下雨,李先生的裤脚总是捻上来,一尘不染,他总是提前五分钟走进教室,也是把新概念往上一放就侃侃而谈,上第一个星期我们忽然觉得,每次上完课李先生这四块黑板没有擦过一个字,但是他写满了,在往下一周忽然发现,每当李先生写到这的时候,我们能推算出什么时候下课铃响起来,这真是大师,所以我说我将来当老师一定要当李先生这样的老师,他是中国英语教学的泰斗,像当年朱光潜老师,操着一口安徽桐城话讲什么是美学,尽管我们听不懂,他的桐城话非常难懂,但是就是在这样的情况下,我们看着朱先生最后完成了他的一步一步伟大译作,在他生命走到90多岁的时候,还每天馋着拐棍颤颤巍巍的到北大图书馆完成他的最后一部译作《新科学》。
这些老师给我们震撼如此之大,所以我们一下子扑到了北大的读书氛围中。他们给我们开了全部的书单,都是人类历史上经典的东西,因为他们说过,如果你没窥探过人类过去的最高的封边的时候,你就不知道你现在站到的地方究竟离海平面多高。所以当时所有教授都跟我们说,要读那些真正经过时间考验而不被淘汰的东西。所以在北大我的读书激情一下子被点燃起来,当然俞敏洪也被我的激情点燃起来了,但是俞敏洪呢,他当时基础稍微弱一点,有一次他得了肺结核,他住在西边享受那个传染病院,我去看他,他说王班长,我是他的班长,他是我帮助的同学,我们班四年始终保持倒数第一的同学,底子非常厚,这种人一站起来非常稳的,你想连续四年保持不变,倒数第一,太难。他说王班长,你从北大寄给一本莎士比亚的14行诗怎么样?我记得我回去以后给他写了长长的信,大概50多页,最后结论说,老俞读书要从基本功抓起,你一年以后我再替你借莎士比亚14行,至今老俞没读过14行,但是他用人生写出了15行。所以这就是当年我们在北大读书的氛围,就是读这些经典,人类熟悉的,甚至很多人追求时髦不屑一读的东西,对我们的生命,对我们的审美,对我们对真理的理解和渴望,对我们对语言和世界的关系,以及型塑生命的力量有了直接的感觉,就是这样一步一步推着我们走到今天。无论我在北大当年教书的时候,还是到了美国,还是从美国回来,我的读书的这个激情,选择所谓一流书的概念一直伴随着我,所以我认为我人生最大捷径就是花了时间非常痛苦啃了一流的书。举个例子,当年我到了美国,我改行,我不学英美文学,因为我发现到了美国来错地方,不能在美国生存,我学了十年的英文,在美国一点用没有,我不能教美国人英文来生存,那是李阳要做的事。我知道在美国生存要有一个技能,就改成计算机,但是学计算机谈何容易,计算机在八十年代是第一代计算机时代,主机,主机两个特点,体积庞大,造价昂贵,一台上百万,当时直属教育部重点院校才拨一台,安放在北大的南北阁。那个时候特别羡慕计算机系的,因为只有计算机系当年在北大四年,他们有一方面特权是任何系没法超过的,就是洗澡,到洗澡堂,计算机系人优惠洗澡,为什么?他们要消毒。为什么消毒?因为计算机如此昂贵,发展初期人们搞不清楚计算机病毒是怎么出来的。这个也应该拍成电影,北大当年就两个澡堂,一男一女,我们当时分的非常清楚。老头老太太管的非常严,比你们现在门卫森严多了,不仅要有洗澡票,还要有学生证,两证具全才能进去,而且还要看哪个系。你说哪系的?中文系的,明天再来,今天比较紧张。那个人回去了,一看哪个系的?计算机系的,赶快进去,今天你们是专场。另外一个,刚打了篮球,老师我必须洗,晚上要跟女朋友约会。老师说拿出学生证,考古系的,捣什么乱,明天也不要来,他们只有校庆的时候才能来,这才代表北大的历史。所以当时我觉得世界上两个东西我没见过,一个是上帝,一个是计算机,我到了美国学了计算机,我崩溃了,但是我想到老师教我的读书,为什么崩溃?因为到了纽约州立大学,录取我很容易,我记得第一堂课让我崩溃,第一堂课上微积分,十年我没摸过数学,上来我就危机了,就分裂了,而且讲课的是印度籍的老师,我想当时在北大练听力怎么没练过这个东西呢?所以同学们,学习不一定标准就是最实用的,我崩溃了。而且这个老师头上缠了发黑的白布,我听的越来越崩溃,我多少次想冲上去问他,你也是人,我也是人,咱们俩怎么这么难沟通。后来我想到,什么叫君子,该动手的时候不动手,该出手的时候不出手。
我想,我作为北大六年老师,我也没白练啊,我赶快到书店拿下计算机两本一流的著作,学西语言,上面有几百种西语言,但是我找到薄薄的不到两百页的著作,我不断的在读,不断的读,又不像我北大读经典一样,这本书我最后读的基本上找不到页玛的时候,我忽然发现我对C语言找到奇特的理解,我知道它为什么诞生,它优越在哪,它比较其他的语言,比如纯粹的学术语言,比较机器的语言,它好在哪。后来我学C++语言的时候我又找到了发明C++语言写的东西,看似非常精简,因为在他来说都不是问题,仍然不到两百页的书,我苦读整整一年,最后忽然我对这之间的世界完全了如指掌,最后我是我们班被老师评价为优秀的学生,当你熟悉一种语言的思维方式的时候,你很难跳到其他世界,因为是完全不同的,他是解决C不能解决的问题,而我由于掌握全部一流的平台,我非常正确的走进了两条道路,而且走的非常正确,老师给我非常高的评价,这就导致了我后来在纽约州立大学,尽管第一学期几乎想要抹去自己,我常常说这哪能听懂,尤其是印度籍教授。我经常利用上厕所的时间跑到操场上想,上帝,你把我微积分了吧。但是这两本一流的著作,让我走进真正这两个语言思维的精髓,我后来一下在这两个中间,一旦跳跃,我就变成超越所有本科学生天天在市场上抓关于C++这个介绍、那个介绍,读十本书也没有摸到真正C++核心的东西,所以我的读书基因在美国又一次拯救了我,使我经过两年半的艰难困苦的努力获得了纽约州立大学数学系机系的科学硕士学位,是我们班第一个走进美国一家伟大的软件公司,叫做贝尔传讯公司,我完成了我的转折,后来才有了95年一天深夜,老俞一番鬼魅的电话打到了我家,我做了人生的选择,才有了三个合伙人的雏形。
这就是我跟大家分享的,读书要读一流的书,做人要做一流的人。谢谢大家。
主持人:感谢王强老师分享的读书经历,下面进入提问环节。
提问:王强老师刚才说读书要读一流的书,做人要做一流的人,在您看来什么样的人才是一流的人?
王强:第一,真诚。第二,有激情。第三,开放,对什么都容易吸收。第四,阳光,你如果自己自焚,你也让别人照亮。第五,要有梦想,而且为了梦想不断往前走。第六,在大是大非面前,一定要有原则,而原则高于一切,善的就是善的,恶的就是恶的,所以我们做新东方,我就是按照这样的东西走到今天,也面对老俞基本是这样,所以我在老俞面前随时就拍桌子,因为只要偏离任何原则的东西,所以新东方的人给我一个外号。
徐小平:说王强老师叫做脆弱如钢,俞敏洪老师叫坚强如芦苇,我叫芦苇钢。王老师说的第一词叫真诚,有这样一个细节,俞敏洪拿着书说,你有一天会让我嫉妒的。当时我在加拿大学完英文硕士,做一个私人老师,非常不成功,回到新东方的时候老俞说了一句话,老俞说小平,你很快就让我嫉妒的,他把对朋友的一种赞美、认同表达出来。我们三个人在一起的时候真的是坦诚相见的,虽然我们从来没有在一起洗过澡,大家心里有什么东西说出来,所以新东方历史上所谓的争吵,恰恰使新东方成为伟大企业的真髓所在,有什么说出来。所以在合伙人里面,俞敏洪说过一句话,他说我们来美国之前,我们不是真吵,我们是不同观点、不同角度的交锋,是思想的汇集,所以你们今后做人要学会这种东西,就是真诚、沟通、交流。
提问:我今天注意到俞敏洪发了一篇博客,特别澄清电影和新东方之间的差别,一再想撇清这中间的关系,我想听听您怎么说,您在单口相声当中总是把他当成一个捧哏,不断的调侃。
王强:他现在也是这样,老俞看完这个电影说,这个主人公离我比较远吧,怎么没有雄起的时候,我说这个电影最大的意义就在这,连这样的人都能成功,别人更能成功。
徐小平:这个电影,第一他没有参与,事实上是这样的,2011连的3月份,韩三平找我,要拍摄一般部关于中国梦的电影,然后我找俞老师,我说我来写,我在新东方一直负责新东方的宣传公关、企业形象、品牌建设、营销,当时老俞说千万不要写,后来我告诉韩三平我们不写了,他说不行,你不写我们就找别人写,你不写我们就把新东方写的很坏。事实上后来我用两个礼拜拿出那个剧本,但是既然俞敏洪不想写,就写了海归回国创业的故事,海归回国和两个朋友创办了英语学校,是一个爱情故事,后来陈导说新东方会不会告我们,我说这个片子如果出来不符合我们之间的价值观、我们的友谊观,我根本不跟你合作,一部电影算什么。一直到了11年的年底,他来找我,我是3月份写出来的,剧本出来以后,我把我的剧本寄给王老师和俞老师,我提供了最初在新东方的素材,我的剧本给你们看,我要经得起友谊的审查,而陈导的剧本要经得起市场的审查。等到最后电影出来以后,俞老师看完以后觉得我这么伟大的人物怎么写的这么窝囊。这就是电影的目的,如果你这样窝囊的人都能够做到这么成功,对当代青年是有意义的嘛。所以俞老师也就一如既往忍气吞声的接受了这个片子。
提问:您刚才说一流的书,您给我们推荐一些一流的书。
王强:一流的书很多的,但是确实很难,因为我也特别怕推荐这个书,如果读完以后跟你生命确实没有交际的话,确实浪费时间。比如对于西方文明史的理解,至少有几部著作大家一定要读,从文艺复兴时代就是博格哈特的《意大利文艺复兴史文化史》,但是荷兰大史学家写的《中世纪的秋天》,读完这两部作品你对中世纪文艺复兴的本质有非常好的了解。到了《历史的研究》,汉语翻了一卷的结本,这个是作者花了三十多年的时间,用五千多页的篇幅研究各个存在的文明形态,研究他们怎么繁荣消亡的,最后得出两个东西,所有文明符合两个东西,如何面对挑战和回应,所以读完这几个东西,从中世纪到文艺复兴,再到二十世纪人的历史,有了非常宏观的东西,按照他们所指引的方向再往近读。
提问:我想问王强老师一个问题,我感觉王洋的角色是最温情的,最初他似乎是愤青,你在创业中是否也扮演这样的角色?
王强:我在三人创业中更接近邓超的角色,前一部分挺像我的,小平这个角色也是相反,在新东方我称之为小平是最有远见人,新东方所有历史大发展第一启动者就是小平同志。但是小平的性格,我过于钢,我是直接和老俞yes or no,小平有一点像王洋那样的,你这拍两下,那拍两下。
提问:在合伙创业过程中难免冲突的时候,每个人应该怎么做?
徐小平:制度,议事规则。
提问:是什么让你们最终要合伙的?是因为个人感情吗?
徐小平:有一个学生转了我们三个人的照片,说他们三个人搞鸡搞了三十年。我想简单说,创业一开始,合伙人往往是互补,互相需要。如果能坚持到最后靠的是什么呢?共同的价值观。什么是价值观?什么东西最重要,当两个东西摆在一起,什么最重要,比如你爱上一个人,你妈妈说他不行,我们不喜欢,你为此让你爸爸妈妈难受,还是你追求你的真爱,这就是价值观。比如说新东方的价值观是什么,就是新东方这个品牌,我们对同学的吸引力,包含我们对学生的承诺,我们相信这个东西有价值,比起我多一个点、少一个点,一个点新东方能值五千美元,但是我们共同的把这个品牌做好做大,你的东西才用不完。所以新东方有非常杰出的人,他不认同这个品牌,他就离开了。但是我跟王强、俞敏洪,我们在最痛苦的时候都知道这个品牌是我们共同的价值观,新东方要把中国最优秀的人才,让他们看到另外一个世界,最终能够把中国这个世界变得和最美好的世界一样美好,我们完成这个历史使命。
提问:我也是非常喜欢读书的,在看很多作品的时候本来就非常晦涩难懂,你刚才说你读很难懂的书的时候还反复读,我想问是什么样的心态让你读不懂还可以反复读。
王强:书写出来的文字两种,有力量和没有力量。书有两种,一类是硬性的书,一类是软性的书,黑格尔、康德、尼采、柏拉图这些都是硬书,硬书你要想从中获得养分,唯有一个捷径,就是不断的读,因为你不可能靠一遍,畅销书一遍不用读完你就理解了,这些畅销书和那些真正书籍的区别。所以当你一遍一遍进入的时候……
]]>这篇关于time_zone 的总结写得非常好Time_zone ,建议先读完做个基础知识的打底
存储类型 | 存储值示例 | 解释 | 适用场景 |
---|---|---|---|
Datetime | YYYY-MM-DD HH:MM:SS | 时间日期类型。DB时区切换它的值不时区相关常见名词解释变, 但时区切换后代表的时间信息已改变. | 使用简单、直观、方便。适用于无需考虑时区的业务场景,例如国内业务 |
Timestamp | 名词1547077063000 | 解释以UTC时间戳来保存, DB时区切换它代表的时间信息值不会变,但是会随着连接会话的时区变化而变化。 内部以4个字节储存, 最大值可表示到2037年. | 适用于客户端需要支持多时区自适应的场景,因精度有限,不推荐使用 |
Date | GMTYYYY-MM-DD | 全称Greenwich Mean Time 格林威治(也称:格林尼治)时间,也叫世界时(Universal Time),也叫世界标准时间。是指位于英国伦敦郊区的【皇家格林尼治天文台】的标准时间,是本初子午线上的地方时,是0时区的区时。GMT格林威治时间可认为是以前的标准时间日期类型,不包含时间信息 | 不关注时区只需要显示日期的场景 |
Varchar | UTCYYYY-MM-DD HH:MM:SS | 全称Coodinated Universal Time 协调世界时,又称世界统一时间、世界标准时间、国际协调时间。它是以原子时(物质的原子内部发射的电磁振荡频率为基准的时间计量系统)作为计量单位的时间,计算结果极其严谨和精密。它比GMT时间更来得精准,误差值必须保持在0.9秒以内,倘若大于0.9秒就会通过闰秒来”解决”。UTC时间是现在使用的世界时间标准字符串类型,可以用时间字符串来表示日期时间类型,格式可自定义,如果用ISO标准时间格式存储,则可以包含时区信息:yyyy-MM-dd’T’HH:mm:ss.SSS+HH:MM | 自定义存储日期时间格式,可包含时区信息,适用于只需要显示时间的场景,不方便计算 |
Bigint | DST1547077063000 | Daylight Saving Time的简称,又称“日光节约时制”和“夏令时间”,也叫夏时制。表示为了节约能源,人为规定时间的意思。在这一制度实行期间所采用的统一时间称为“夏令时间”,在欧洲和北美用得比较多数字类型,可以存储时间戳,表示某个时刻,稳定性最好 | 存储某个时刻,可以表达时间的确定性,存储/网络传输稳定性最好 |
名词 | 解释 |
---|---|
GMT | 全称Greenwich Mean Time 格林威治(也称:格林尼治)时间,也叫世界时(Universal Time),也叫世界标准时间。是指位于英国伦敦郊区的【皇家格林尼治天文台】的标准时间,是本初子午线上的地方时,是0时区的区时。GMT格林威治时间可认为是以前的标准时间 |
UTC | 全称Coodinated Universal Time 协调世界时,又称世界统一时间、世界标准时间、国际协调时间。它是以原子时(物质的原子内部发射的电磁振荡频率为基准的时间计量系统)作为计量单位的时间,计算结果极其严谨和精密。它比GMT时间更来得精准,误差值必须保持在0.9秒以内,倘若大于0.9秒就会通过闰秒来”解决”。UTC时间是现在使用的世界时间标准 |
DST | Daylight Saving Time的简称,又称“日光节约时制”和“夏令时间”,也叫夏时制。表示为了节约能源,人为规定时间的意思。在这一制度实行期间所采用的统一时间称为“夏令时间”,在欧洲和北美用得比较多 |
PDT | 全称Pacific Daylight Time太平洋夏季时间,也称夏令时。每年的3月份第二个星期日凌晨2点开始至11月份第一个星期日凌晨2点结束,第一天23个小时。「北美的西海岸太平洋沿岸地区,大城市有:温哥华,西雅图,旧金山,洛杉矶,拉斯×××,圣迭戈,萨克拉门托,波特兰等」 |
PST | 全称Pacific Standard Time太平洋标准时间,也称冬令时。从11月份第一个星期日凌晨2点开始至次年3月份第二个星期日凌晨2点结束,第一天25个小时。 |
CST | CST可视为中国、古巴的标准时间或美国、澳大利亚的中部时间CST可以表示如下4个不同的时区的缩写:中国标准时间:China Standard Time UT+8:00古巴标准时间:Cuba Standard Time UT-4:00美国中部时间:Central Standard Time (USA) UT-6:00澳大利亚中部时间:Central Standard Time (Australia) UT+9:30因此具体含义需要根据上下文环境确定具体含义。在中国就表示东八区”北京时间” |
UTC+08:00 | 基于UTC标准时间的时区偏移量,可表示东八区。UTC±[hh]:[mm]形式表示某个时区的区时,由UTC和偏移量组成。UTC+08:00就表示东八区时区的本地时间 = 世界协调时间UTC + 时区偏移量(+8h) |
ISO | 在时间日期上它全称是ISO 8601,是一种日期/时间表示方法的规范。规定了一种明确的、国际上都能理解的日历和时钟格式。在Java语言中常见格式:●ISO.DATE:yyyy-MM-dd, e.g. “2023-02-03”●ISO.TIME:HH:mm:ss.SSSXXX, e.g. “10:30:00.000-11:00”●ISO.DATE_TIME:yyyy-MM-dd’T’HH:mm:ss.SSSXXX, e.g. “2022-10-31T01:30:00.000-05:00”. |
时间戳 | 时间戳一般指的UNIX时间,或类UNIX系统(比如Linux、MacOS等)使用的时间表示方式。定义为:从UTC时间的1970-1-1 0:0:0起到现在的总秒数(秒是毫秒、微妙、纳秒的总称),可简单理解为某个时刻 |
一般MySQL都会设置 time_zone 为 system,方便MySQL部署在不同的国家、时区也都能很好兼容,这是很合理的设置。
如果我们的查询中有一个列类型是 timestamp 的话,意味着:
timestamp 数据类型会存储当时 session的时区信息,读取时会根据当前 session 的时区进行转换;而 datetime 数据类型插入的是什么值,再读取就是什么值,不受时区影响。也可以理解为已经存储的数据是不会变的,只是 timestamp 类型数据在读取时会根据时区转换
如果MySQL 读取 timestamp 字段时,需要做时区转换,当 time_zone 设置为 system 时,意味着MySQL 要去follow OS系统时区,也就是把读到的timestamp 根据OS系统时区进行转换,这个转换调用OS 的glibc 的时区函数来获取 Linux OS 的时区,在这个函数中会加 mutex 锁,当并发高时,会出现 mutex 竞争激烈,每次只有一个线程获得锁,释放锁时会唤醒所有等锁线程,但最终只有一个能获取,于是一下子导致系统 sys飙高、上下文切换飙高。每读取一行带 timestamp 字段时,都会通过这个 glibc 的时区函数导致锁竞争特别激烈最终 QPS 拉胯厉害。
想一想,你一个SQL查1万行,10个并发这点流量其实一点都不过分,但是这里需要10*1万次转换,锁争抢就激烈了。
分析参考这个: https://opensource.actionsky.com/20191112-mysql/
perf 以及火焰图如下:
在中国可以将 time_zone=’+8:00’ 将 time_zone 固定死,不再需要follow OS 时区,所以也不需要调用glibc 获取系统时区,避免了前面所说的锁竞争
这个经验来自无数次线上故障复盘,因为 time_zone 设置为 system 是个默认行为,所以要全部改过来还真不容易,给了我们就业机会 :)
当然学习总是希望交叉起来,既有深度又有宽度你才能掌握更好,所以请趁热打铁:
东八区CST 被JDBC 驱动错误识别成了美国的中央时间,官方修复
在我们 99块钱的 ECS 启动一个MySQL 的Docker 容器(配置简单,换MySQL版本对比也方便)
|
|
my.cnf配置文件
|
|
先创建一个Database ren,然后在里面再创建一个表t,如下:
|
|
插入一条数据:
|
|
现在我们基本得到了一个100万行的测试表,接下来就要实验验证,同时开30个并发来查 ts列(timestamp, 要做时区转换) VS 查 dt 列(不需要做时区转换),对比他们的效率:
|
|
可以清楚地看到 查ts 需要20秒左右,查 dt 需要4秒左右,差了5倍,结合我们前面的理论讲解,肯定可以想到这是在做时区转换有额外的开销,其实这还好只是开销大了几倍,有没有一种可能因为glibc 加锁导致整个系统雪崩了?大家可以试试能否搞出雪崩的场景来
Perf 安装和使用命令:
|
|
比如用 perf top 可以看到查 timestamp 才有如下图前两行的 futex_wait_setup/libc-2.28 的wcscoll_l , 对比一下查 datetime 是完全看不到这些内核、libc的消耗的:
停下来花点时间来分析他们的性能差异,多结合理论表述这篇,另外反过来想想如果你不知道这个原因,但是你看到这个现象(timestamp 和 datetime 性能差5倍的时候),你怎么来分析是为什么?
找个核数多的机器做同样的测试,比如以下数据是在96核机器上完成,让锁竞争更激烈,实际是把问题更加明显化
从 top 也可以看到CPU 都花在了sys(内核态系统调用)上,这明显是不符合逻辑的。同时也可以看到96个核基本都跑满,整个MySQLD 进程的CPU 消耗接近 9600%,又回到了我们常说的CPU 有使用没有效率,不过站在CPU的角度是有效率的,这个效率都是在做锁相关的事情,但是站在业务角度是没有效率的:
在这么明显的不正常情况下可以进一步通过 perf record 来采集调用关系,通过调用关系来回溯是哪个函数导致的锁争抢从而找到问题
从这里也可以看到这个问题在不同核数下表现完全不一样,如果只是一个核很少的实例那么看起来问题还没那么明显,只是慢了,但是到了96核下这个SQL 反而全崩了,这个SQL 完全查不出结果(CPU 都在sy 上干抢锁的内耗上,能查出才怪),核数越多这个问题就越严重,也即内耗越严重,如果有业务流量源源不断地进来就类似雪崩了:
|
|
这几个算是你可以接着做的一些小任务
借着 MySQL 的时区转换我们把这个问题重现了,让我们通过实际测试来验证这个差异,下次我相信你会对这个问题印象深刻的
当然我们做这个实验不是为了证明这个问题,这个知识点本身价值不是特别大,而是希望你能学到:
希望能看到你们更多的不同实验现象和分析
]]>有人告诉我localhost和127.0.0.1的区别是localhost 不经过网卡,把我惊到了,因为我还真不知道这个知识点,于是去特别去验证了一下,这是个错误的理解,localhost会解析成127.0.0.1 然后接下来的流程和127.0.0.1 一模一样
我用Google搜了下标题,果然得到如下图:
红框里是排第一、第四的文章,都大言不惭地说localhost不经过网卡、不收防火墙网管限制等。
我也看了下第二、第三的文章,这两篇都是说在MySQL命令行中连 localhost 的时候,MySQL命令行会判断 localhost 这个字符串然后不走DNS 解析流程(走的话就肯定解析成了127.0.0.1),因为是本地连接,可以绕过OS 的内核栈用MySQLD 启动的时候生成的 unix-socket 管道直接连上MySQLD,这样效率更高。
错误信息大概就是在MySQL这个特殊场景下演变而来的,英文搜索就没有这个错误污染信息
但这不是我要说的重点,我想说的是自己动手去求证!这一直都是我们星球里强调的能力和目标,我把这条发到Twitter上后有无数的傻逼跑出来质疑或者一知半解不去验证就丢一个结论,这是我最痛恨的。比如:
Localhost 写死了在 /etc/hosts(那我就要问,你清空/etc/hosts localhost还能工作吗?)
Localhost 不走网卡(但凡抓个包就知道走了,我估计他们抓了,抓的是eth0. 这里有个小小的歧义 loopback 本地回环网卡算不算网卡)
所以我特意再写篇文章再验证下各种质疑,并让大家看看是怎么验证的,我希望你们可以跟着验证一遍而不是只要知道个结论
Localhost 会按dns解析流程进行解析,然后和127.0.0.1 一样。在特殊的程序中比如MySQL 命令行会对localhost提前做特别处理。
完整的区别见这篇英文(Google 英文第一篇就是)总结:
Ping localhost,然后 tcpdump -i any(抓所有网卡)icmp (精确点只抓ping包),可以明显抓到网络包,所以肯定经过网卡
如图是我在centos、微软azure(应该是个ubuntu)、macos下做的测试:
如下图,ping的时候即使没有 /etc/hosts 也可以把localhost 解析成127.0.0.1,为什么呢?所以接着我就 nslookup 看一下是哪个 DNS server做的这事,最后我用114.114.114.114 这个公网的DNS 做了解析,就不认识localhost了,说明去掉 /etc/hosts 之后 会把localhost 发给dns server解析,标准的dns(比如114.114.114.114,8.8.8.8) 都不会返回127.0.0.1 ,但是有些特定实现的为了省事帮你解析到127.0.0.1了
这个问题来自这个评论:https://twitter.com/InnerHack/status/1700012845302436087 所以我去验证了一下,特别强调这个数据意义不大,但是你们可以学会用strace,命令:
|
|
然后你得到如下图,从strace时间戳你可以看到 localhost 解析成127.0.0.1 的过程,再后面就是ping 127.0.0.1(这里也说明了前面的结论,两者是一样的,就是多了域名解析)
域名解析的时候,先去找/etc/hosts 没找到再去找 /etc/resolv.conf 拿dns server ip然后把localhost发给这个dns server 解析,tcpdump抓包如下,红框是dns server返回的结果:
唯有动手能解释一切,不要空逼逼(不是说你们,是说Twitter上那帮人,我是被他们留言多了逼着写了这篇)
我是欢迎一切有理有据的质疑,事实文中很多信息来源于别人的质疑,然后我去验证
然后好多验证手段你们可以学学,比如nslookup/tcpdump/strace 等。
我给的文章链接也可以仔细读读,能学到很多东西,每一次进步都来自你深挖、展开能力。
]]>10年前写的,重新发一下
先通过 top 查看整个CPU资源使用情况;
通过top -Hp pid查看java进程的每一个线程占用CPU的情况;
如果有一个线程占用CPU过高,有两种可能:
没有内存了,Java垃圾回收线程不停地运行尝试回收内存,但是每次无法收回,确认:
jstat -gcutil pid 1s 观察10多秒钟就能发现了,看是不是内存使用率接近100%了
类似于死循环(hash冲突攻击),就是一个线程一直占用一个核的所有CPU资源(其实一个线程总是占用一个核超过50%的资源都是不太正常的),解决:
用我的checkPerf脚本,定位这个线程具体执行的任务(能具体到某一行),对应看代码解决。
如果有很多线程,每个线程占用的CPU都不多(基本都在10%以下),那基本是正常的,只是程序并发确实很高。
如果死锁:
jstack -l pid 多执行几次,统计一下stack中总是在等待哪些锁,可以对锁id进行排序统计(sort uniq grep)
上面列出来的都是明显的瓶颈,最可怕的是哪里都没有明显的瓶颈,哪里都要偷一点点CPU资源走,这是可以试试JProfiler这样更专业一点的工具,同时要配合自己对业务的了解来解决。
一旦触发频繁地抛出异常,CPU占用率会急剧地上升(抛异常比正常情况下会慢2个数量级)主要是由于:Throwable的构造函数中会调用native的fillInStackTrace(),这个方法就会构造整个异常栈了。
Java内存的问题,如果有内存泄露(就是执行完fgc/old gc后不能回收的内存不断地增加):
怎么确认没有内存了:
jps -lmv pid 先确认你的参数,也就是你给JVM分配了多大的堆(-Xmx 比如1G); 然后jstat -gcutil pid 1s 看看GC运行情况,如果(O/E 两列基本接近100%的话就是内存不够了)
内存不够分两种:一种是真的不够,就是你们的系统很庞大需要1G以上的内存,而你只分配了1G,这个没什么好说的,增大内存,物理内存不够就投钱买;
第二一种是你们的代码写的烂,有内存泄露,这样的话分配多少内存都不够,得找出是否有内存泄露,看接下的解决方案
快速解决:jmap -histo:live pid 来统计所有对象的个数(String/char/Integer/HashEntry 这样的对象很多很正常,主要是盯着你们公司的包名下的那些对象)
每隔一分钟执行一次上面的命令,执行5次以上,看看你们公司报名下的对象数量哪个在一直增加,那基本上就是这个对象引起了泄露;
用课堂上的工具HouseMD(java -Xbootclasspath/a:/usr/java/jdk1.6.0_29/lib/tools.jar -jar housemd-assembly-0.2.2.jar pid)来动态监控创建这个对象的地方(一般来说很多时候创建了这些对象把他们丢到一个HashMap然后就不管了),分析一下有没有释放!
>trace -s -d ClassName
上面的方法实在没法定位就用: jmap -dump:live,format=b,file=heap.bin pid 导出整个内存(耗时间,需要很大的内存的机器才能对这个导出文件进行分析,会将JVM锁住一段时间)
在Eclipse的插件EMA中打开这个文件(2G的物理文件需要4G以上的内存,5G以上的需要将近20G的内存来分析了)
盯着你们公司报名的那些对象,看看引用关系,谁拿着这些对象没释放(是否是必要的),可以一直追查的RootReference
大部分情况下是磁盘IO的问题(索引没建好、查询太复杂);
索引问题的话分析慢查询日志,explain 他们挨个解决。
偶尔也有数据库CPU不够的情况,如果并发高CPU不够很正常,如果并发不高,那很可能就是group by/order by/random之类的操作严重消耗了数据库的CPU
|
|
总结一下数据库问题就只有这三招:show full processlist/分析慢查询日志/explain(然后建好联合索引)
补充一个数据库连接数不够的问题,很多人碰到了,不知道怎么解决:
这篇算是对抓包定位原因在哪里的落地篇,没什么高深的技术,都是很low但是你一定可以照着操作的,算是星球内必须学会和带走的内容
一次业务请求包含160个拖数据的SQL查询,通过160个连接,发给160个Database,但是过几分钟后总有报错。几分钟抓包文件10G左右,网络包几百万个,怎么找到报错的那个?
几个麻烦的地方
分析技巧和步骤:
切完后的包,切完后的文件会加时间戳,时间戳可以和报错时间对应:
|
|
搜reset/fin 找到第一个断开的连接,第一个断开的连接才是罪魁祸首:
知识点:
MySQL 协议是一来一回,也就是client发查询然后等查询结果全部返回,然后再发下一个
按协议在一个SQL查询的数据传输完毕前client不能再发任何请求,MySQL Server负责一直发送查询结果直到发送完毕。
如下两个截图是从42909.pcap文件中过滤到的抓包从握手到断开的全过程,图1过滤条件:tcp.srcport eq 42909 and tcp.len>0 (42909是客户端,9913是MySQL端口),可以看到客户端 login(连数据库肯定得要user、password认证),然后是client查了MySQL的一堆服务端参数(下图第二行),再然后是client设置了几个参数(set 那些)。关键的是倒数第二行client发了一个SQL给MySQL需要拉取大量数据(建立连接17.98秒的时候),然后是数据传数据过程,第190秒的时候client发了 Quit断开连接
上图因为加了过滤条件,只看client端并去掉ack后的所有包,没看到全貌,这个过程9913的MySQL 服务端又做了啥呢?因为太长前面漫长的传数据就不截图了,只看最后连接的断开。
但是下图红框所示的地方可以看到MySQL Server 传着传着居然带了个 fin 包在里面,表示MySQL Server要断开连接了,无奈Client只能也发送quit 断开连接。红框告诉我们一个无比有力的证据MySQL Server 在不应该断开的地方断开了连接,问题在 MySQL Server 端
就抓包结论来看是 MySQL 在不应该断开的时候发送了 fin 主动断开连接,可能是MySQL的bug
题外话,这个包证据抓了有一周了,但是MySQL研发同学始终绕来绕去(比如我的代码没记录下这个SQL就是没收到,我的代码没问题——熟悉的味道)跟我打了一周太极(异地),我一查发现我和他老板认识且在一层楼,赶紧面对面找他老板讲清楚这个问题,且签字画押承认是MySQL的问题,然后继续推进排查,最终结果是为啥我跟你们一起期待吧,有了结果我再来update。
找个MySQL,然后开始抓包,用mysql-client连一下MySQL Server随便发几个SQL,然后看看一来一回的响应
如果哪怕在星球一年你只要好好掌握这一篇用到的技能也能帮助你在日常工作中互相扯皮的时候快速给出精准定位和分析,值回星球票价,加油
比如这个案例我同时打开了5/6个wireshark分析不同的流、整体搜索等
这些技巧不只是用在MySQL 上,其它微服务、redis等涉及网络调用场景的扯皮的地方都可以用
capinfos rsb2.cap
tshark -q -n -r rsb2.cap -z “conv,ip” 分析流量总况
tshark -q -n -r rsb2.cap -z “conv,tcp” 分析每一个连接的流量、rtt、响应时间、丢包率、重传率等等
editcap -c 100000 ./rsb2.cap rsb00.cap //把大文件rsb2.cap按每个文件100000个package切成小文件
存放在这里:
|
|
最后回答一下上一篇中提到的流模式下 net_write_timeout 报错
如下图,JDBC 在 streaming 模式下,不断读取下一行,如果这个过程只要报错抛出的异常就是 StreamingNotifiable 异常
错误信息定义如下,这个报错误导太严重,从以上JDBC 代码可以看到只要读取下一行报错了就会报调大 net_write_timeout 错误,但是实际原因却是连接异常断开,和 timeout 没有一点关系,你看久经考验的 JDBC 代码也不是那么完善还得你会 Debug
|
|
这个报错误导了排查分析方向,不知道坑了多少人了!当然如果MySQL 因为net_write_timeout 超时断开连接当然应该报如上错误,但是 JDBC 搞不清楚MySQL 为啥断开,就瞎猜是 timeout 了,然后只要是连接异常读数据错误(包含断开)就报这个错误。希望你们不要被坑
记住这个坑人的报错堆栈:
|
|
不过你要仔细看的话,它还是有caused by,如下,但是绝大部分工程师看到这个堆栈会忽视,上面都有 net_write_timeout 我还管个屁 Can not read response from server, 不过要是结合抓包的话就能理解:at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3186) 这个根本的原因是 JDBC 从服务端读取数据的时候报错了
|
|
最后希望你没被绕晕,再去看看上一篇中推荐的流模式原理,把代码和网络应用层完美地结合起来
完整堆栈也可以参考网络上别人碰到的:https://github.com/brettwooldridge/HikariCP/issues/1771
下次在你们的业务代码里如果出现查询结果太大导致JVM OOM的话你可以站出来说把拉取数据改成 流 模式会有奇效 :) , 当然随之而来的是会有 net_write_timeout 报错,嗯,你的机会来了,业务技术上按照你的指引发展,出了问题你能顶得上
]]>追着RT 跑,不断加压力,到瓶颈前随着并发的增加RT很稳定。
但是你要对你的RT怎么来的,包含哪些环节的消耗,这样才不会出错。
如下图左边是QPS不停地增加,每一次台阶(增加20%流量)都是一次加压过程,右边是对应的 RT,可以看到在绿线阶段几乎是平稳的,直到最后的红色箭头 RT略微有一点点提升,但是整体也还好,说明基本没到瓶颈
当然这个图是经过长时间调优的结果,来之不易,是理想的期望系统状态,但在这之前是长时间的痛苦分析和瓶颈在哪里的定位过程。
凡是复杂的实际业务总是有很多干扰项出现在你的理论图上,你得很好地识别他们
概念说明:
黑色=Database=被依赖业务=物理
蓝色=Tomcat=上游业务=逻辑
上游响应时间=下游业务响应时间+网络时间+上游自身处理耗时
响应时间=RT=耗时监控
tcprt:从内核网络取Database的响应时间
实际很魔幻的是同样流量有时候压测很稳定,有时候又不稳定,性能上不去(稳定时可能是压测数据、没有触发Database雪崩之类的问题),所以导致问题
所有压测过程中肯定是没有任何资源上的瓶颈(CPU、内存、网络带宽、磁盘等等)
如图,蓝线表示Tomcat,黑线表示Database被调用方,可以看到每次黑色 RT上升QPS下跌很猛(符合预期),奇怪的是黑色RT很快降下来后蓝色RT还会维持较高一段时间,监控频率每5秒采集一次,以下所有监控图时间范围是一样的,但采集频率不一样
(图1)
上图的两个 RT 监控数据都是Tomcat的业务代码记录下来的,比如Database的响应时间就包含网络+Database的处理时间
如下图通过网络监控看响应时间(tcprt 阿里云文档,从OS 内核中取到网络包的响应时间),蓝线表示Tomcat,紫线表示Database,监控力度每1分钟采集一次,有被平均
以上两个监控图的矛盾点:如果从网络层面记录的Database RT 可以看到上升幅度不明显,但是Tomcat 的RT上升很明显,但是Tomcat记录的RT则又是Database 上升明显。
tcprt和tomcat业务进程记录的 Database rt差异,tcprt记录到的是RDS/Database的响应时间+网络时间,tomcat在这个基础上还要加入自己进程调出处理时间,比如tomcat进程取到数据库连接的时候连接需要排队等待1秒钟(后面有分析),那么这个一秒钟对tcprt来说是不会记录进去的,但是客户端感知到的这次调用是1秒以上。当然业务记录的Database 还可以更精准,比如在连接池Druid(或者其它连接池的实现)内取记录,但是无论如何从业务进程到OS内核这里的差距总是存在的。
可以很清楚看到 QPS 下降是因为 RT上升,那么究竟是Database的RT上升导致的还是Tomcat的RT上升导致的。
但是我们从监控图也能看到Database RT降下来后Tomcat RT还维持高水位,所以有点迷惑了。
继续看另外案例
两次压测监控数据,左右两个图标是同一时间的QPS和RT,蓝线表示Tomcat,黑线表示Database被调用方
从两个图来看,随着并发加高(QPS加高) 黑色RT增加明显,但是跑着跑着降下去了,可以理解成突发流量导致黑色RT增加,但是很快黑色RT稳住了阵脚,降回去了,但是蓝色 RT没降,所以表面看起来是蓝色(Tomcat)处理能力到了瓶颈
上图时间点内核监控的tcprt,可以看到还是Database 处理耗时增加,和上图的黑色RT下降根本不匹配,上图黑色RT最后在2.96ms,下图内核监控到的Database的tcprt在8.49,差异矛盾点
第三次压测图
从第一个图来看,随着并发加高(QPS加高) 黑色RT增加明显,蓝色 RT去掉黑色部分也有增加,并且黑色、蓝色都没降回去,看起来主要是黑色(Database)处理能力到了瓶颈
纠结的时候就在Tomcat上抓包确认一下,如下图黑色 Database服务端口是5493,可以看到Tomcat 发request总是很快,但是Database 响应都是几十毫秒(下图红色框),和监控一致。其实监控可以说明问题,但是我担心业务记录时间不准,以及建连接时间都考虑在内,所以想抓包微观上印证一下,这种项目牵扯到很多人你搞错了方向丢人不说,大家合作联调浪费很大,所以必须稳!
如果说问题在Database上,那为什么会有Database RT忽上忽下,Database RT降下去了Tomcat RT不降?我们要继续分析一下 Tomcat RT以及Database RT是怎么记录和实现的
问题解决后的原因分析以及数据整理
这个时候我们再把Tomcat部分的业务调用和RT记录再细化一下,如下图:
作为Tomcat和Database的连接点、枢纽点搞清楚Druid的逻辑对理解Tomcat和Database之间的问题的理解很关键。
比如以下要说的三个Druid 错误状态如果你不放到一起比较,看到这个错误你最多反应就是连接池不够了,什么原因不知道。但是如果放到一次比较一次后你以后对详细错误提示会积极敏感,进而发现第四、第五种错误提示
这就是综合比较、总结的好处。
Druid 最核心的类是 DruidDataSource,连接的构建,入池,获取,收缩,销毁,以及核心监控数据都在这个类维护
连接池初始化流程:初始化驱动实例 -> 加锁 -> 初始化属性 -> 初始化过滤器 -> 校验参数 -> 创建初始化连接并校验后加入池中 -> 创建logStatsThread、createConnectionThread和destroyConnectionThread -> 注册MBean,用于支持JMX -> 如果设置了keepAlive,通知createConnectionThread创建连接对象 -> 解锁
获取连接排队是基本不消耗CPU,下图右上角是获取失败的日志打堆栈消耗,可以看到异常非常多。
Druid最大连接数默认是30,多次调大,30->60->120->160,一直调下去对调大能解决问题都没有信心了,总是报错
maxWaitThreadCount 30, current wait Thread count 0
调大到160后的报错堆栈,对应源码 这个报错说明报错时已经有160个线程在等连接了,别等了,先快速报错返回吧
|
|
以下两个Druid 报错这次压测没有出现但是可以放一起比较一下,其它项目场景经常出现
Druid类似报错,明显是等了5秒最大等待时间还没有获取到连接:
红色错误信息表示等了5006毫秒(设置的5000毫秒超时)还没有取到连接,所以超时了,然后抛出错误堆栈。
红色信息还提示我们当前连接池最大10,目前 active 0, 说明不是连接池满了取不到,而是连接池里一直是空的。
看到这个错误不能说明数据库、访问数据库有啥问题,只能说明Druid 连接池取不到连接,要继续分析Druid创建连接的线程栈。或者比如Druid 参数设置不合理,可以把min、init、max 连接数设置为相同的值,避免压力高峰期再去创建连接。
Druid通过另外一个task(thread)异步给连接池补充连接,也就是这里可能是Druid创建连接失败,比如密码错误、比如连不上数据库,比如创建的thread卡死了、报其他异常了
Druid创建 连接 和业务取连接是两个线程,所以业务取连接报错是看不到创建连接报错的堆栈和原因的
借出连接为0(active 0),creating也是0,没有新连接正在创建。
分析方法:
原因
Druid中有个计数器createTaskCount,用来记录每个连接池当前正在创建连接的任务数,默认不能超过3。Druid中,在keepAlive=true的情况下,这个计数器有bug,存在加了但没减的情况,导致这个值涨到3之后没有减回去,从而无法提交新的创建连接任务。
注意,进入这个状态后的连接池,是无法自动恢复的。Druid升级到1.1.24可以修复这个问题。
因为数据量太大,一台Database存放不下,自然会分片,或者说单表几千万之后也是建议分片。
分片逻辑是取业务id最后两位的字符去取string hashcode,再对16个Database分片
|
|
补充个小八卦
为什么取某几位尾数来求模?比如很多业务按user_id拆分片,然后希望这个用户的所有订单拆分也落在一个分片内。于是他们想到的办法是在订单id最后几位上追加进去下单人的user_id后几位,对订单拆分会取订单id后几位hash,这样同一个用户肯定到同一个分片
这样查询某个用户的所有订单时(高频需求)就只需要查一个分片,否则就要扫描所有分片。
掏出你的某宝、某东看看你的订单后几位
分片后的数据,明显两头的多中间的少,这必然导致后面的 Database 负载不均衡:
Java源码:
问题的根本原因?
多个Database中的某几个瓶颈,为什么会这样见数据分布部分的分析
为什么Database RT监控能降下来?
业务Tomcat 帮Database拦截了流量,一旦Database响应慢 Druid 连接就会不够,请求都堵在Tomcat中,导致Tomcat RT升高(包含等待连接时间)——替人堵了枪眼,很好,Tomcat crash总比 Database crash要好,但是业务要清楚这是替人挨枪子,该往哪里去查瓶颈。
比如加流量20%,开始Database RT升高,很快连接不可用,可能有接近20%的流量被Tomcat拦截,这个时候Database RT能稳定,也有可能拦截的不够多,这个时候Database RT还是很高,但Tomcat RT更高,进入一种平衡状态
为什么有时候压测能过?
应该是数据分布比较巧,刚好压测流里面的数据分布没那么不均衡,没触发数据库雪崩
]]>我们之前说过根因分析第一就是要追着 RT跑,随着并发的增加哪里RT增加快哪里就是瓶颈,这是我们的基本原则,但总有一些例外,我们今天想说说例外
如下图,应用是多个Tomcat集群,Tomcat节点可以随意增加,后端是一组DB集群,有几百个Database实例,每一次业务请求都会对应多个Database查询
开始的时候客户端压2个Tomcat集群,QPS 700,Tomcat节点CPU 90%,Database每个节点CPU 20%左右,于是增加1个Tomcat 节点这个时候QPS 还是700,Tomcat的RT增加了50%,Tomcat CPU 降低到60%,继续增加Tomcat 节点 RT、QPS保持稳定,CPU使用率下降。
所以这里要搞清楚哪里是瓶颈,如果Tomcat是瓶颈加Tomcat节点为什么没有效果。如果Database是瓶颈但是增加Tomcat节点的时候Database 的RT有一点点增加,远远没有到增加50%的RT 程度
首先最容易想到的是Tomcat 和 Database之间的网络、网关、LVS 等资源到了瓶颈,但是经过排查分析这些环节都排除了,另外也排除了Tomcat到Database的连接池、Database的磁盘等瓶颈,另外Tomcat 访问Database全是查询,没有事务。
看起来事情比想象的复杂,于是进行了如下压测:
先用一个压力端压3个Tomcat中的2个,QPS 跑到700,然后新开一个压力端压第三个Tomcat(新开压力端是排查压力机的问题,新开Tomcat是想排除Tomcat 的问题),如果Tomcat是瓶颈的话QPS应该上去,或者说后端没有问题的话那两个Tomcat 的700 QPS得保持基本稳定不变或略微下降才对。
实际上第二个压力端跑起来后,前两个Tomcat的QPS 铛就掉下去了,总QPS 保持稳定不变,也就是随着Tomcat给后端并发压力的增加后端肯定给了一个负反馈给那两Tomcat,导致那两Tomcat QPS掉下去了。这个负反馈明显得是Database的RT在增加,但是从监控来看Database的RT 从0.6增加到了0.8,但是Tomcat 的RT 增加更快从19.7增加到了29.8.
单独压DB,DB的QPS能高5倍,CPU 也可以跑到100%。看起来单压都没问题,一组合就不行了
绕过Tomcat 用相同的SQL 压Database QPS 一下子就能上去,Database 的CPU 也跑到了100%,但是只要走Tomcat 就会上不去。
打开Tomcat 日志将所有Database的响应时间拉出来分析,发现随着并发的增加 100 ms的响应也多了很多,实际上这些查询都是1ms就应该返回
当压力增加的时候MySQL端等锁导致的 RT 抖动或者说长尾越来越多,虽然没有数据库的写,但是查询的时候优化器也需要统计行数等数据来为查询优化器做选择依据,这个统计动作会触发加锁排队(极短),但是因为这一代Intel CPU指令的变化导致这个锁被放大了10 被,所以最终Tomcat 端看到的长尾就多了
绕过后的压测场景没有业务逻辑,每次请求就是一条SQL,虽然有抖动但是对平均RT拉升不明显。
业务逻辑是一次请求会发256条SQL,等这256条SQL全部返回来了业务请求才会返回!请反复读这句话3遍再往下看
如果256条SQL 中有一条花了100 ms返回那么整个业务逻辑的RT 就是100ms,假设1%的概率一条SQL是100ms,99%的SQL 是 1ms,你可以先停下来算一算这种业务模型下的平均RT是多少
关于这个抖动对整体rt的影响计算:
注:假设正常查询rt 1ms,逻辑平均rt=(1-power(1-抖动概率,物理查询次数))抖动大小+(power(1-抖动概率,物理查询次数))1ms
当前场景下,逻辑QPS:物理QPS=1:256,假如每次查询有1%的物理(RDS)rt抖动到100ms,则会导致逻辑平均rt恶化到92.44ms.
在一次逻辑查询里,只有所有物理查询都不抖整体才是不抖,RT正常;如果有一个或多个物理查询抖了,那么逻辑RT就是抖动RT。
所以一次逻辑查询不抖的概率是: power(1-抖动概率, 物理查询次数)
反过来想这256条SQL都不碰上抖动这次业务请求才会1ms返回(概率极低),否则就是256ms返回
倒不是出于原因分析,这个原因几年前就分析清楚了,但是这个场景:一次业务请求会涉及多次SQL、Redis、MQ的调用,只要其中有一个有短板、抖动这次业务请求就慢了。这简直太常见了
但难在别人的抖动很低被平均掉了,但是业务(Tomcat) 就要替别人背锅了,因为别人的RT 几乎没有增加或者加很少,但是Tomcat RT增加很明显,瓶颈当然看着像是在Tomcat 上。背锅吧也不可怕可怕的是你增加Tomcat 节点也不能解决问题,这才是你要从这个案例里学到的。
如果你的Tomcat 调后端因为短板(抖动)导致压力打不到后端,因为抖动导致Tomcat不能快速返回
和本文无关但是可以放一起综合来看上下游互相影响的复杂性
以前认为事务不提交的主要代价是行锁持有时间变长(这确实是个问题),今天见识到了新代价,事务不提交会导致事务活跃链表变长,增加copy readview的代价,进而导致DB的RT 增高,实际导致DB RT高的根本原因是DB前面的业务早到了瓶颈,来不及发送commit,导致DB端事务堆积严重。也就是业务瓶颈导致了后端DB RT高,只看RT就会被蒙蔽——怎么解决?可以抓包看commit发送慢
纠结好久要不要写这篇,因为原因非常坑爹,你们基本不会遇到,想了很久觉得思路还是有些价值,所以还是写一下,我尽量简单
继续上文 https://plantegg.github.io/2023/06/20/%E5%AE%9E%E6%88%98%E7%93%B6%E9%A2%88%E5%AE%9A%E4%BD%8D-%E6%88%91%E7%9A%84MySQL%E4%B8%BA%E4%BB%80%E4%B9%88%E5%8E%8B%E4%B8%8D%E4%B8%8A%E5%8E%BB/ ,纯读场景问题解决后,继续压纯写场景,比另外一套类似环境差了很多,大概是2折。
纯写肯定有预期:会有锁、磁盘瓶颈等问题
先看top,结果很明显CPU上不去,并且有一个单核长时间 100%,然后 top -Hp mysqld-pid 展开所有线程,果然一直有一个线程几乎一直 100%,这就太明显了,这个线程遇到了瓶颈,导致整体上不去。
top -Hp mysqld-pid 看到165935 线程一直几乎是 100% 的CPU 状态
所以接下来要搞清楚这个线程在忙什么,刷盘?抢锁?
如果是Java应用就简单了,直接jstack一看就很清楚了,但是MySQLD没这么容易,另外环境里没有 pstack也没法安装,所以这条路走不通。
但是大概率能猜出来和磁盘有点关系,于是iostat -x -d 看看磁盘情况,好家伙果然ioutil 100%,磁盘 IO TPS 好几万。如下nvme0n1是MySQLD 使用的SSD 数据盘,vdb 是OS 系统盘
|
|
通过 :iostat -x -d vdb nvme0n1 3 可以看到如下图
但这是不是正常情况不好说,于是找到家里同样的环境跑起来(没有单线程 100%问题,QPS 比问题环境高了 5倍),于是也看一下 iostat 做一个对比,对比发现 ioutil 很小,然后磁盘 IO TPS 才我问题环境的30%,在QPS 5倍,IO TPS才 30%的情况下傻子也能看出来这两场景肯定不一样。一个QPS触发的IO TPS差了 15倍了。
不啰嗦,将问题环境的sysbench 脚本复制到正常环境,这下问题重现了,再diff看看两个脚本果然被人改了。问题环境使用的sysbench是别人装的,经过分析后发现里面被改动过一些东西。
之所以一直没有怀疑 sysbench 的问题,也有之前测试只读场景的时候符合预期,所以忽视了sysbench的差异。
这让我想起贝尔实验室Ken Thompson’s “cc hack” 的八卦(有兴趣的同学可以自行查证一下):
当年在贝尔实验室,人们都用Unix系统,但是只有Ken可以绕过密码直接登录,让其他人百思不得其解。按理说整个Unix系统是开源的,很多人检查了系统代码,尤其是登录部分, 并没有发现任何漏洞或者后门。
Ken的同事们不断重新编译Unix, 但是Ken依旧如幽灵一般来去自如。
有人怀疑编译Unix的编译器里面有代码,但是当他们反复检查编译器源码,甚至重新编译c编译器后,依旧没有任何发现。
多年后,在Turing Award Lecture中,Ken终于道出了事情真相,登录源码和编译器源码都是干净的。事实上,这个幽灵般的木马在编译器的可执行文件中。
这里的思路是:单线程100%->磁盘IO TPS非常高->和正常环境对比(常用手段,也要运气好有两个环境可以对比)->一个QPS 对应的IO TPS差异巨大->压测脚本问题
这算是个坑爹的小问题,大家也不会碰到,比网络限速难查多了,网络限速那里我们有放之四海而皆准的 RT 逻辑+抓包,所以很好定位。但是查证分析过程我觉得有一定的参考性,所以记录下。
如果MySQLD能提供一个内部任何一个操作的时间就好了,实际很难实现。当然通过火焰图去看异常偏高的调用是另外一个方向。
跨网络我们有抓包很好界定,但是问题到进程内部的时候反而没了抓包这种一锤定影的工具了
]]>没有差异。等额本金=等额本息+每月提前还贷一点点()
因为每个月等额本金还款多,第一个月后欠本金少了,后面每个月都是这样,所还本金更多,最终总利息自然更少
其实可以用极限思维来分析他们的差异:假设等额本息和等额本金都借100万,周期一个月(没看错,一个月还清,极限假设),所以一个月后他们还钱一样多!所以这个时候没有任何区别;现在继续假设,假如还款周期是2个月,那么等额本金在第一个月还钱多,导致等额本金在第二个月的时候欠钱少了,到第二个月月底还清所有欠款的时候利息要少(本金少了)——这才是他们的差异,所以是没区别的。等额本金这两个月相当于欠了银行150万一个月(第一个月欠100万,第二个月欠50万) 应还利息就是150万 乘以 月利率;等额本息相当于欠了银行 151万(第一个月欠100万,第二个月51万,因为第一个月还钱的时候只还了49万本金),所以应还利息就是 151万 乘以 月利率;欠得多利息就多天经地义这里没有投机、没有人吃亏
再或者换个思路:第一个月借100万,月底都还清,此时利息一样多;然后再借出来99.X万,这时等额本金借得少这个X更小,所以从第二个月开始等额本金还的利息少,归根结底换利息少是因为借得少(即现实中的还本金多)
把上面的极限思维图形化就是下图中的灰色部分面积代表你的欠款(每个月的欠款累加),等额本息的方式欠得多,自然利息多:
同样贷款金额下等额本金总还款额少,也就是总利息少,所以给了很多人划得来的感觉,或者给人感觉利息便宜。其实这都是错的,解释如上第二个问题
利息每个月计算一次,这个月所欠本金*月利率。所以利息只和你欠钱多少有关(我们假设所有人的利率都一样)。每个月的月供,都是先还掉这个月的利息,多余的再还本金
等额本金因为每个月还掉的本金多,所以计算下来每个月的利息更少
同样贷款额+利率的话等额本金开始还款一定比等额本息要多一些,那么你可以把等额本金分成两块,一块和等额本息一样,多出来的部分你把他看成这个月额外做了一次提前还款。你提前还款了后面的总利息自然也会更少一些,然后每个月的等额本息也会减少,以此类推每个月都是这样额外做一次提前还款直到最后一个月。
总结:等额本金=等额本息+提前还贷
额本金开始还款一定比等额本息要多一些,可以把等额本金分成两块,一块和等额本息一样,多出来的部分把他看成这个月额外做了一次提前还款。提前还款后总利息也会更少一些,然后每个月的等额本息也会减少,以此类推每个月都是这样额外做一次提前还款直到最后一个月。
钱在你手里没法赚到比利息更高的收益的话(99%的人属于这种)提前还贷划得来,之所以以前不建议大家提前还贷,是因为以前普遍涨薪快、通胀厉害、房价涨得块,把钱留出来继续买二套、三套更赚钱。另外钱留在手里会有主动权和应急方便
不会,见第四条利息的计算方式。担心提前还贷的时候这比贷款把后面10年的利息收走了的是脑子不好使的人。但有些银行提前还贷会有违约金
从知识的第一性出发,他们都没理解第4条,受社会普遍意识影响都预先留下了错误经验。本质就是利息只和贷款额、利率有关。
没有
不会,你前6年只是还了前6年的利息,没为之后的6年多付一分利息
因为你欠的钱越来越少了,不是你提前还了利息,是你一直在还本金
大部分小贷公司的套路就是利用你每个月已经在还本金的差异,利息自然越来越少,然后计算一个大概5%的年息误导你,实际这种网购分期的实际利息要是他计算的2倍……好好想想
等额本金、本息都搞不清楚的人就不要去搞分期了,你的脑瓜子在这方面不好使。
聪明人只看第4条就能在大脑里得出所有结论,普通人除了要有第4条还需要去看每个月的还款额、还款额里面的本金、还款额里的利息等实践输入才能理解这个问题,这就是差异
https://zhuanlan.zhihu.com/p/161405128
要
划不划得来要看这笔钱在你手里能否获得比房贷利息更高的收入以及你对流动资金的需要。其实万一有个啥事也可以走消费贷啥的,现在利息都很低
一样的,你这个问题等价于我欠100万,老婆欠50万,所以我提前还贷比朋友合算吗?显然你两谁提前还贷合算只和你两的贷款利率是否有差别
等额本息和等额本金利率一样的,所以没有差别
错误!利率还是那个利率,跟你还剩10年和还剩5年没关系,提前还贷都是等价的。记住有闲钱就提前还
搞清楚每个月的利息怎么计算出来的 利息=欠款额*月利率,月供都是把本月利息还掉多出来的还本金,也就是每个月欠款额会变少
每个领域都有一些核心知识点代表着这些问题的本质,你只有把核心知识点或者说问题本质搞懂了才能化繁为简、不被忽悠!
那贷款这里的本质是什么?就是利息只和你每个月欠款以及利率有关!这简直是屁话,太简单了,但你不能理解他,就容易被套上等额本金、等额本息、提前还贷的外壳给忽悠了。
再或者说这里的本质就是:你去搞清楚每个月的还款是怎么计算的。月供=本月所欠X利率+本月还掉的本金 这是个核心公式,差别在每个月还掉的本金不一样!
就这样吧该懂的也该看懂了,看不懂的大概怎么样也看不懂!只能说是蠢,这些人肯定理科不好、逻辑不行,必定做不了程序员。
比如网上流传的如图总结的所有结论都是错的:
]]>环境两台云上相同 128C的EC2(有点豪),一台当压力机一台当服务器,用Sysbench测试MySQL纯读场景,不存在任何修改,也就几乎没有锁
|
|
EC2机器128核,故意只给MySQLD绑定了其中的24Core,网卡32队列
|
|
走同一交换机内网IP压MySQL跑不满CPU,跑压力和不跑压力时ping rtt 分别是 0.859/0.053(RTT 有增加–注意点), 此时TPS:119956.67 1000并发 RT 8.33
下图是压测时 htop 看到的MySQLD 所在EC2的 CPU使用情况,右边65-88是MySQLD进程(绿色表示us, 红色表示sys+si CPU)
用top查看详细的每个 core 使用(只展示MySQLD使用的24core ,top 然后按1–还可以试试2/3,有惊喜)
|
|
继续尝试用2000并发,TPS、CPU、ping rtt都和1000并发没有区别,当然按照我们以前QPS、RT理论2000并发的时候RT应该翻倍,实际确实是16.66,所以这里的问题就是翻倍的 RT哪里来的瓶颈就在哪里。
也试过用两个压力机每个压力机分别用1000并发同时压,QPS一样稳定——目的快速排除压力端、链路上有瓶颈。
写到这里RT 刚好翻倍16.66=8.33*2 数字精准得好像编故事一样,不得不贴一下原始数据证实一下:
1000 并发和2000并发时的ping RTT对比(ttl 64说明内网直达)
|
|
在抓保证明前推荐一个工具快速绕过抓包(原理也是通过pcap lib去分析网络包,tcpdump也会调用pcap lib)
监控tcprstat,从网络层抓包来对比两个并发下的RT:
|
|
也就是网卡层面确认了压不上去瓶颈不在MySQL 上,加并发后网卡的RT没变(网卡RT包含MySQLD RT),因为ping RTT 在1000和2000并发也没有差异,推测交换机不是瓶颈,大概率出网卡的虚拟层面
在客户端的机器上抓包,上面我们说过了1000并发的RT是8.33毫秒:
注意上图,我把RT排序了,明显看到5ms到17ms 中间没有这个RT范围的包,但是有很多25ms的RT,平均下来确实是8.33毫秒,留下一个疑问:RT分布不符合正态,而且中间有很大一段范围镂空了!这是不应该的。
同样我们再到MySQLD 所在机器抓包分析(注:正常路径先抓MySQLD上的包就行了):
同样是对RT 排序了,但是慢的RT都是对端发慢了(注意最右边的select, MySQL相应是 response),同样对这个抓包求平均时间就是tcprstat 看到的103微秒,也就是0.1毫秒。如下图红框是请求,请求的间隔是11毫米,绿框是响应,响应的间隔都是0.2ms不到
同样在2000并发时也对MySQLD所在网卡抓包对比,response 的RT 没有变化,从这里可以看出瓶颈点在sysbench 和 MySQLD 的网卡之间的链路上,似乎有限流、管控
到这里我们已经找到了有力的证据,RT是在离开MySQLD网卡后增加上去的,先验证下走走本机127.0.0.1快速压一把,让sysbench 跑在0-7 core上,这时可以看到MySQL跑满了CPU,下图左边1-8核是压力进程,右边65-88是业务进程,TPS:239969.91 1000并发 RT 4.16
htop状态:
各CPU 详细分析:
|
|
就以上sysbench VS MySQLD 的CPU 消耗来看,因为sysbench 处理逻辑简单,就是发SQL给MySQLD,所以 sysbench自身US很少,大部分都是调用OS的网络操作,而MySQLD有 60% CPU用于US,也就是自身业务逻辑,MySQLD收到SQL要做SQL解析,要去查找数据,这些都是用户态消耗,找到数据后走网络发给Sysbench,这部分是sy
到这里可以拿着证据去VIP通道(土豪+专业的客户得有VIP通道)找做网络管控的了,不会再有撕逼和甩锅
把所有请求RT 分布进行图形化,此时平均 RT 8.33,理论上是一个正态分布,下图是有限速时:
|
|
去掉限速后平均 RT 3.26(比下图中大概的中位数2.71大了不少) 完美正态
|
|
先测试一下网络下载时的ping:
|
|
有限速方向,尝试了BBR和cubic 拥塞算法:
|
|
跑tcpperf触发限速时的监控(上下两个窗口是同一台机器),红色是丢包率挺高的,绿色丢包就没了,应该是拥塞算法和限速管控达成了平衡
反过来限速被我去掉了(限速可以进出双向单独控制)
|
|
查看限速配置如下:
|
|
sysbench(主键查询-小包) 12万QPS 正好命中 txckpps:120,tcpperf (大包)稳定的105MB带宽命中txcmbps:844
去掉后长这样:
|
|
对这块网络管控感兴趣可以去了解一下 ovs 这个开源项目(open virtual switch)
实际结构如下:
放开所有网络控制后,1000并发压力 30万QPS,RT 3.28,此时从sysbench 以及空闲机器ping MySQLD机器的 RTT和没压力基本一致
top状态:
|
|
小思考:
我们中间尝试走本机127.0.0.1 压测时QPS 是24万,比跨机器压的 30万打了8折,想想为什么?网络延时消耗完全没影响?
简单可复制的证明办法:抓包,快速撕逼和分析
肯定有很多人想到:内存、磁盘、线程池、队列、网络等等原因,但是这些所有原因有一个共同的爹:RT,所有这些影响因素最后体现出来就是RT 高了,你CPU资源不够、内存慢最后总表现就是在客户端看来你的 RT 太高。
所以我们去掉这些复杂因素先在MySQLD所在EC2 的网卡上抓一个包看看RT,再对比一下1000/2000并发时抓包看到的 RT 有没有升高,如果有升高说明问题在MySQLD这端(含OS、MySQLD的问题),如果 RT 不变那么问题不在MySQLD这端,并且从EC2网卡出去都是很快的,那么问题只能是在路上或者客户端的sysbench自己慢了。
这是我们星球里说的无招胜有招–抓包大法,扯皮过程中我还没见过几个不认网络抓包的,也有那么一两个扯上是不是网卡驱动有问题,我的代码不会有问题
两个限速条件:pps 120k(每秒最多12万网络包),带宽 844mbps=105.5MB/s
Sysbench 查询都是小包,触发第一个条件,tcpperf触发第二个条件
ping ping神功失效了吗?也没有,我后来又测试了100、200并发,rtt 0.2ms和0.4ms,也就是说随着并发的增加rtt 增加到0.8ms后就不再增加了。上来1000并发已经到了天花板
|
|
by @橘橘球
从2018年开始,我们有个业务陆续接到反馈 Nginx 线上集群经常出现不响应或者偶发性的“超慢”请求。这种卡顿每天都有少量出现。而只有多个集群中的一个出现,其他压力更大的集群皆未出现。
业务结构比较简单:LVS->Nginx->后端,如图
一些观察到的现象:
并且已知,卡顿的原因是打开 reuseport 后,新进来的请求可以由内核 hash 派发给一个 Nginx woker ,避免了锁争抢以及惊群。但如果网络条件足够好,压力足够低,Nginx worker 一直来不及读完 receive buffer 中的内容时,就无法切换并处理其他的 request,于是在新请求的客户端会观测不间断的卡顿,而压力大的后端由于网络传输慢,经常卡顿,Nginx worker 反而有时间能处理别的请求。在调小 receive buffer 人为制造卡顿后该问题得以解决。
由于所述场景比较复杂,缺乏直接证据,打算通过构造一个较简单的环境来复现这个问题,并且在这个过程中抓包、观测Nginx worker的具体行为,验证这个假设。
在本次场景复现过程中,这两种连接都是短连接,每次请求开始前都需要三次握手建立连接,结束后都需要四次挥手销毁连接
Nginx使用了epoll模型,epoll 是多路复用的一种实现。在多路复用的场景下,一个task(process)会批量处理多个socket,哪个来了数据就去读那个。这就意味着要公平对待所有这些socket,不能阻塞在任何socket的”数据读”上,也就是说不能在阻塞模式下针对任何socket调用recv/recvfrom。
epoll 每次循环为O(1) 操作,循环前会得到一个就绪队列,其中包含所有已经准备好的 socket stream(有数据可读),不需要循环全部 socket stream 读取数据,在循环后会将被读取数据的 stream 重新放回睡眠队列。睡眠队列中的 socket stream 有数据可读时,再唤醒加入到 就绪队列中。
epoll 伪代码 (不包含唤醒、睡眠)
Nginx reuseport 选项解决惊群的问题:在 TCP 多进程/线程场景中(B 图),服务端如果所有新连接只保存在一个 listen socket 的全连接队列中,那么多个进程/线程去这个队列里获取(accept)新的连接,势必会出现多个进程/线程对一个公共资源的争抢,争抢过程中,大量资源的损耗,也就会发生惊群现象。
而开启reuseport后(C 图),有多个 listener 共同 bind/listen 相同的 IP/PORT,也就是说每个进程/线程有一个独立的 listener,相当于每个进程/线程独享一个 listener 的全连接队列,新的连接请求由内核hash分配,不需要多个进程/线程竞争某个公共资源,能充分利用多核,减少竞争的资源消耗,效率自然提高了。
但同时也是由于这个分配机制,避免了上下文切换,在服务压力不大,网络情况足够好的情况下,进程/线程更有可能专注于持续读取某个慢连接数据而忽视快连接建立的请求,从而造成快连接方卡顿。
worker_processes 2
listen 8000 reuseport
|
|
在server instance上放置一个 2GiB 大文件(0000000000000000.data)和一个 3MiB 小文件(server.pcap),并开启一个http server
|
|
在Nginx instance上安装、配置好Nginx,并启动Nginx (注意要绑核!)
|
|
启动慢连接client,开启4个下载进程并计时,测试脚本在此
ip maping:
快连接client端:下载同一个小文件的下载时长有快有慢,方差很大,完整日志在此
|
|
快连接client:无论耗时长短,抓包结果都显示存在不同程度卡顿,抓包文件在此 耗时长的下载过程
耗时短的下载过程
Nginx access.log 存在大量未下载完的200请求,和少量499请求,且499请求的耗时为0,access.log文件在此
卡顿的日志建立连接时长(utc)在0.3-0.4ms左右,超过1s的就出现499了
|
|
下载中途被关闭的连接(200),可以观测到Nginx server在客户端已经请求FIN并被ACK之后仍然在发送一些网络数据包,客户端非常迷惑,向Nginx发送RST
未和Nginx建立连接就被关闭的连接(499),可以观测到连接始终没有被建立,在等待1s后客户端超时,主动请求关连接
|
|
client runtime log: 耗时稳定在50-100ms,比无慢连接、纯跑快连接时要大一倍(25-50ms)
client 抓包结果:
Nginx access.log: 都发完了,而且发得很流畅,建立连接时间(utc)非常短
|
|
对于慢连接大文件下载时长略有影响:46s (无限制) vs 53s (有限制)
卡顿依然大量存在,但大多以连接能够建立但是下载不完的形式(200)出现,499较少,并且存在惊群现象,完整日志在此
client runtime log:存在卡顿,和benchmark没有区别
client抓包结果:存在卡顿,存在RST,和benchmark没有区别
access.log:卡顿的日志连接时间比benchmark略短,在0.2-0.3s左右,出现499的情况少了但是依然会有
存在惊群现象,以下是Nginx worker进程的cpu使用率和上下文切换频率对比
两者的cpu使用率和上下文切换频率差不多,但关闭reuseport后花在wait上的cpu时间明显增加(1.3-1.6% vs 2.8-2.9%),这就是惊群带来的性能损耗。原始文件:开启reuseport,关闭reuseport
惊群对于慢连接大文件下载时长略有影响:46s (开reuseport) vs 53s (关reuseport)
最初复现的场景是所有的instance都是t2.micro,但开2个慢连接进程时比较难复现,开4个进程又太容易触发限流,所以开始考虑用大一些又没那么容易限流的instance型号。考虑到aws是通过间歇掉包来限速的,慢连接进程数量并非越大越好,引发限速后反而会造成网络连接不畅,造成慢连接卡顿,使得快连接卡顿反而不容易观测。最后选择将慢连接全链路改成t3.micro,结果好复现多了.
可以观察到有一些access.log上499的连接,各种计时也是0,这其实是因为计时也是通过worker进行的,只有进行epoll和上下文切换才会在日志上打入时间信息,worker如果一直不进行切换,那么计时就会失真,就会看到日志上计时也是0的现象。
by @wych42
为了激励大家多动手少空想,我在推特发起了白嫖我的知识星球活动:
白嫖我星球的机会来了,总有人说贵、没有优惠券,这次直接来一个完全100%免费的机会,要求: 在MySQL的基础上重现某个线程池卡的现象,给出可复制的重现过程。就是因为某个线程池满了导致落到这个池里的查询一定都慢,否则都快。 不愿意出钱就动手吧
感谢推友王鱼翅同学,以下是他的教科书级的细致重现,你复制粘贴就能和他一样重现了
这个现象对应我们年度四大案例之一,如下图左下角
重现后请思考:
由 @wych42 重现
根据 USE 分析套路。看到服务端执行快,但是整体RT慢的现象,大概率是中间哪个位置有排队。根据文章里的描述,原因是在thread pool group中出现了排队。
排队的主要原因是服务端拒绝创建新的thread(worker),导致新进来的SQL需要等待前面的执行完成。那么就需要重点分析thread(worker)的创建过程和约束条件。根据文章和文档的说明,重点在thread_pool_size, thread_pool_oversubscribe, thread_pool_max_threads, thread_pool_stall_limit这几个参数上。
跟据文档分析和实际执行结果,这几个参数在MySQL不同的发型版中的行为逻辑是不尽相同的。核心差异在对创建新worker的限制条件上,后面复现也会根据两个发型版的特点分别执行。
To clarify, the thread_pool_oversubscribe system variable does not play any part in the creation of new worker threads. The thread_pool_oversubscribe system variable is only used to determine how many worker threads should remain active in a thread group, once a thread group is already oversubscribed due to stalls.
percona的行为更符合原文章里的说明:
并发向DB发起请求,观察客户端耗时,这些请求应当符合这些条件:
综合考虑使用 select sleep(2);
作为测试SQL。并发控制使用下面的golang代码实现。
再控制数据库服务端参数,运行同一个并发程序进行对比,mariadb和percona分析执行运行过程:
由上面分析可以,mariadb 中造成排队的约束是thread_pool_max_threads。
DB配置
|
|
执行SQL select sleep(2)
预期结果: 6个SQL执行的客户端观察耗时为2s;2个SQL为4s
若调整 thread_pool_max_threads=8,则8个SQL的执行客户端观察耗时都为2s
thread_pool_max_threads=6;concurrency=8
|
|
thread_pool_max_threads=8;concurrency=8
|
|
均符合预期。
由上面分析可以,percona中造成排队的约束是thread_pool_oversubscribe。
DB配置: thread_pool_max_threads设置一个较大的值,以排除影响。
|
|
执行SQL select sleep(2)
预期结果: 客户端观察到的耗时分四个批次输出,每个批次2个SQL,耗时分别为2s,4s,6s,8s.
若调整 thread_pool_oversubscribe=2,则三个批次输出,分别为3条SQL耗时均为2s,3条SQL耗时均为4s,2条SQL耗时均为6s
thread_pool_oversubscribe=1,concurrency=8
|
|
thread_pool_oversubscribe=2,concurrency=8
|
|
均符合预期。
现实场景中,很少会有大批量的2s在SQL在生产环境执行(限互联网业务),上述的分析过程能否在真实场景中验证呢?尝试用一个执行200ms的SQL来模拟下:
DB配置: thread_pool_max_threads设置一个较大的值,以排除影响。
|
|
执行SQL select sleep(0.2)
从执行结果中可以看到,只有第一条SQL按照预期的时间执行完成了。
从抓包结果中可以看到,所有SQL几乎是同时发出。观察最慢的一条SQL,但是从客户端发包到服务端响应包发出的耗时,与客户端观察到的耗时也能对应上。
可以验证上述分析过程。
|
|
配置两个线程池,在其中一个线程池上,通过select sleep()
较长时间模拟线程池被慢SQL或者大量任务堵塞的情况,具体配置方案如下:
操作步骤如下:
show processlist
语句获取到链接Id, 该链接会分配到 id%2 的线程池中。
|
|
select sleep(30)
,再到 id=410 的链接上执行 select 1
,预计 select 'slow'
会直接卡顿约30s再执行完成。select 'fast'
,都可以很快执行完成。执行结果:
2023-05-16T11:27:09.997916Z 406 [ERROR] [MY-000000] [Server] Threadpool could not create additional thread to handle queries, because the number of allowed threads was reached. Increasing ‘thread_pool_max_threads’ parameter can help in this situation. If ‘admin_port’ parameter is set, you can still connect to the database with superuser account (it must be TCP connection using admin_port as TCP port) and troubleshoot the situation. A likely cause of pool blocks are clients that lock resources for long time. ‘show processlist’ or ‘show engine innodb status’ can give additional hints.
抓包结果:
id=410 上的阻塞SQL,可以看到:
select 'slow'
原本应该很快返回结果,被卡住select sleep(30)
语句执行完成,空出的线程立刻执行了 select 'slow'
并返回结果id=405链接上的执行结果可以看到,每条语句执行都很快。
percona 的默认配置中,thread_pool_size=核心数,thread_pool_oversubscribe=3.假设在一台 16core 的服务器上运行percona,默认配置下最多可以有 16*(1+3)=64个worker同时接受请求。也就是最大可并行处理的SQL数量为 64 个。
假设同时有65个执行耗时为10ms的SQL到达服务端,理论上,会有一个进入排队。排查网络、解析等阶段,在客户端观察到的64个SQL执行耗时10ms,1个SQL执行耗时约20ms。这也会导致耗时监控中出现毛刺、耗时分布不符合正态分布。
反之,根据硬件配置、查询的量、耗时等特点,也可以推算合理的参数值。
看到文章时,基本确认问题根源在执行线程(worker)不够,导致排队,出于以下几点分析:
尝试复现时,要先启动一个DB实例,便查询文档该参数如何在配置文件中配置,查了MySQL的文档,似乎只在enterprise版本中才有该配置项,便转头去看mariadb的配置说明(这一步给走弯路埋下了伏笔)。
用docker在本地启动了mariadb实例(thread_pool_size=2 thread_pool_oversubscribe=1)
先尝试用 select sleep(30)
模拟阻塞,用 sysbench 模拟正常流量,结果失败:
select sleep(30)
查询的并发量,现象同上。又翻阅了一些文档,看到DB在调度时,对不同类型的SQL调度优先级会有所区别,类似sleep这种啥也不干的SQL,会不会被降低调度优先级,才导致了没有复现呢?(走上了弯路)
尝试人工制造慢查询:
复现结果仍不满意:
此时分析了下,整体耗时上升是人工制造的慢查询,占用了过多IO和CPU资源,影响了sysbench SQL执行的效率。
回头又仔细看了下 mariadb关于线程池的文档,注意到文档中提到 thread_pool_oversubscribe 不决定同时有多少线程池被创建出来并执行任务,这个行为逻辑与文章中作者引用的并不相同。
又去查看了另一个MySQL发行版 percona 的文档,对该配置的行为描述与文章中的相符,基本就确定前面复现失败的原因了。
确定了前面提到的复现思路:用有稳定服务端执行耗时、并且不消耗大量硬件资源的SQL,用可控的并发进行模拟流量,到具体执行时:
select sleep(N)
|
|
|
|
注:Mac M1启动percona时,需要在 docker run 后面添加 --platform linux/x86_64
参数。(percona 未提供arm架构的image)
https://lotabout.me/2023/Verification-of-Percona-Thread-Pool-Behavior/ 从源代码debug上来分析
]]>