






每次看到梁博晒图我又佩服又吃惊,应该没比我大几岁吧,可能结婚和没结婚的人操心的事不一样。我好多年没晒图了,给老粉们看看我现在的床照吧。哪天不给看了我再隐藏这条微博。[笑cry]

789月份A股做得比较差,没有严格采用短线交易策略,导致清仓次数大幅减少;重仓的几只科技股也没有守住,错过了暴涨的机会(比如阳光电源、德业股份、三花智控);哪怕储能行业疯涨,守了3个月的比亚迪也没啥起色。港美股的收益倒是不错,7月份预测蔚来股价翻倍,可惜中间手贱操作了一次又没补救回来。

好久没有买港股了,上周在港股买了2600股比亚迪,买入均价是107.2,早上下了109.9的清仓单,下午一看成交了,到手的收益只有5374港币,相当于买入卖出累计扣了1600左右的交易费,这个费用比炒美股贵了将近一倍,比A股贵数倍,炒港股做短线真的就是为国家打工!这就是我不太喜欢买港股的原因之一。
https://postimg.cc/gallery/ZRn4WtN



账号特殊,换不了别的券商,只能使用中国银行下属的中银国际买港美股,交易费确实非常高,所以今年在港美股的短线交易次数很少了。 昨晚随便操作了一下 mongodb 这只票,收益是480.7美金,结果扣了我差不多82美金(相当于580多人民币),到手收益才399美金。要是换成港股更贵,交易费预计要1300港币。
https://postimg.cc/gallery/W2WyBPN


1-6月份采用短线交易策略,清仓115次,平均持股时间是6天,所以收益很好;7-9月采用重仓少数几只股票的策略,清仓次数只有25次,平均持股时间超过20天,收益反而骤减。从概率上说,第二种策略是很不稳定的,根本就没法保证重仓的几只股票在几个月内会不会大涨,有可能卖了就大涨,一直守着的反而不涨。
https://postimg.cc/gallery/RH7XGWM


我总结了两条经过实践验证的炒股指导思想:
1. 如果采用短线交易策略,就尽可能提高清仓次数降低持股天数,不用在乎清仓后是否会大涨,这样的策略只追求稳,就是要快速赚到钱,不贪图多高的年收益率,能做到30%的年收益就很满足了;
2. 如果很看好一只票,买入后就尽量别去动,用长线思维去做,至少以一个季度为单位,每过一个季度再评估是否要继续持有。
我在第二条指导思想上犯了很多错,比如今年看好德业股份,在7月份时就重仓买进,守了两个月没见大涨,赚了几百块钱就清仓了,结果第三个月储能行业大爆发,若是按我原有的持仓成本算,德业股份涨了将近55%!
7月份在3.4-3.5的价位全仓买进蔚来,中间看到涨到5块时多次被砸下来8%-10%,有天晚上又涨到5块想投机一下,把股票全卖出,结果立马大幅拉升,这时不敢再追高买进,把自己的筹码全都便宜卖了,9月份更是涨到将近8块。真是个惨痛的教训,原本就是决定长线投资的,结果中间想投机赚几个点的差价,最后连芝麻都没捡到反而丟了西瓜
昨天在港股和A股把比亚迪的持仓本金从40多万大幅减仓到只剩3万多块钱了,守了100多天,看着月销量从同比微增到负增长,确实影响持股信心。关注了腾势品牌新的负责人,一点都不接地气,还不如上一任。20万以下的基本盘被吉利、零跑抢了不少蛋糕,比亚迪还是得在设计、颜值方面多下点功夫。
OLTP 关系数据库的并发控制,从理论到工程都做到头了,按代码调用链一遍一遍分析每一步,找不到优化空间了。
比如实现一条 insert 语句,从接收到一个网络数据包到写入硬盘,整条代码调用链只有在记录被写到内存 btree 的 leaf page 时需要加一个轻量级的 page 锁,这个锁实际上就是一条 CAS 指令,开销极小,就算执行 CAS 失败,当前线程也不会被挂起。所以对于 insert 语句的并发控制,还有比这更优的吗?
实现一条 update 语句更完美,整条代码调用链只需要加一个轻量级的行锁,锁的粒度更小,不用加 page 锁,这个轻量级的行锁也只是一条 CAS 指令。
实现一条不带 for update 的 select 语句,整条代码调用链就没有需要同步的地方,一跟畅通。
我问了一下豆包的 AI 编程: mysql 在实现 insert 语句时,整个代码调用链涉及哪些需要同步或加锁的地方?这是它给我的答案,我对 mysql 的代码实现不是太了解,如果答案没有太多错误,那我认为 mysql 的并发控制跟 lealone 对比确实差了几条街。

豆包的 AI 编程目前立马能实用的地方有两个:1. 节省培训新人的成本,对于现有的项目,新人借助它就能自己学习项目的设计和代码实现细节;2. 大中型软件项目的技术文档以前需要多人负责,现在借助 AI 编程可以生成大量技术文档,然后再手工改改,原先需要两个人的工作量用了 AI 后一个人就能做了。
迎面走来几个北方游客,其中一个妹子初看气质拉满,然后听到她跟其他人说了一大串方言,瞬间气质掉满地!听过很多地方的方言,只有女生说粤语是加分项。桂北的方言也一样,特别是全州、柳州话,硬邦邦的,稍微说大声点就以为要吵架。桂林男人说桂林话很多都爱带脏字,我平时基本上只说普通话。
这几天在追一部在央视一套播出的新剧:阵地,讲述1938-1944年全国各地一大批知名文化工作者聚集到桂林做文化抗战的真实故事,办报、办杂志、排话剧、桂剧改革……这段历史现在桂林本地很多年轻人都不知道,我也知之甚少,当时桂林城区人口翻了10+倍,达到五六十万的规模,现在桂林城区的人口也不过百万级。当时连李宗仁、白崇禧都想借机做大做强桂林,要跟重庆媲美,如今再想汇聚那么多名人已经不可能了。
蔚来现在的股价不高不低,我没有全仓了,毕竟从7月的底部上来涨了一倍多了,有人获益了就跑,有人看好就接盘,有分歧就有波动,我从10月份开始也拿一点钱做做短线,昨晚买了4000+股,今晚开盘就卖了,小赚1500多美金。虽然交易费超贵,但是看到做一次短线赚几千到一万人民币,一个月累计下来也挺可观。
https://postimg.cc/gallery/r8bW8Rf


回看豆包的这个回答依然觉得震撼,不但正确,文字组织也流畅,在没有任何文档的情况下,它是怎么做到只看代码就能像人类一样把代码的逻辑写成文字?如果它还能进一步推理出 lealone 这种实现可以保证连接从创建到处理网络数据包都不用加任何锁,那就太牛了,这才是我这个设计的精髓。
华为系的问界有一点是值得学习的,没有盲目推出新车型,老款M5/M7落后了依然会不断改进,所以直到现在依然只有4款车。不少车企就是采用“多生儿子好打架”的粗糙思想,卖不好就再出一款新车型,把消费者当小白鼠去试错,一个品牌接连试错搞砸了几款车,买了就是绝版,谁还敢轻易去买。
比亚迪王朝海洋两个系列的车型太多了,加上不断降价,会不自觉给人一种低端车的刻板印象,哪怕方程豹现在也是往便宜的方向靠。
有钱人买车也讲逼格的,开宝马跟开五菱能一样吗。比亚迪的高端品牌还没搞起来,就是缺了那个格调,不断降价让现有车主觉得被拉低了档次。
蔚来宁愿新开两个中低端子品牌,也要把高端品牌的底线坚守在30万,就算后续研发了新技术成本降下来了,也不要突破价格底线,可以提供更好的服务,让消费者觉得花这个钱值。
我一再强调炒股不是赌博,哪怕玩短线也要讲策略。你首先得了解行业趋势,什么都不想去了解就别玩股票。比如上半年我聊过很多次储能行业,多次买阳光电源、德业股份、宁德时代,就是看重它们的储能业务。只是我在A股定的策略就是短线交易,所以哪怕这3只票在9月份大涨了,我也没赚大钱,但趋势是对的。
我没有驾照不会开车,投资汽车行业6年,极少看车评人的视频,车圈博主只关注了三个(偏技术和数据类),关注最多的是车企官方账号或高管个人账号。雪球或股吧网友的言论一律视而不见,只重点看资讯。我在微博有关汽车行业的观点全都是自己的观察总结所思所想,并通过投资具体车企的股票去实践验证。
股票投资做得对不对不需要争论,亏钱了自会教你做人。就像7月份谈到蔚来和理想时,被理想股东或理想车主怒喷甚至骂脏话,我都懒得回怼。现在蔚来和理想的股价涨幅就摆在那,我的蔚来收益好得很,蔚来这6年给我赚了很多钱,所以无需再多言。
就像过去三天随便拿20-30万小钱玩玩蔚来的短线又赚了6.2%,我要不是自己手贱,蔚来的今年收益都有130%了,搞得现在只有60%多,争取后续多做几次短线把总收益提上去。
@zhh-4096
股票投资做得对不对不需要争论,亏钱了自会教你做人。就像7月份谈到蔚来和理想时,被理想股东或理想车主怒喷甚至骂脏话,我都懒得回怼。现在蔚来和理想的股价涨幅就摆在那,我的蔚来收益好得很,蔚来这6年给我赚了很多钱,所以无需再多言。
蔚来涨到8块左右就适合做短线了,可能涨到10块,也可能跌到7块,因为这时蔚小理的市值差不多在一个水平线了。我在5块时投机造成失误清仓,确实非常愚蠢,5块的蔚来是远远低估的,理性的人不应该做任何操作,死守即可。上次蔚来融资导致股价大跌到5.6时,我没有成功买进,气死个人!
我妈那一辈的人会的手艺多得我都佩服,小时候大大小小的节日总能做点东西:蒸发糕、蒸年糕、包粽子、磨豆腐、做甜酒、酿米酒……到了80/90后,啥都不会了,想吃块嫩豆腐都不知道怎么做出来的,只能去集市上买。[允悲]
自从微博显示省区信息后,我就遇到几次被骂南_蛮子,有时吃饭遇到游客也会听到说桂林除了山水就没别的了。对于这些没文化的人我挺无语的,北有长城,南有灵渠,这就是厚重历史的开始。哪怕只说古代状元数,全国290多个地级市,桂林也能轻松吊打80%以上。70年代桂林就跟北上广和西安一起对外开放了,以至于我小时候还纳闷为啥国外那么多大官要跑来桂林,我现在对出国毫无兴趣,就是在桂林见过的老外太多了,对这些毛发多的人没有任何好奇心。
110左右减仓比亚迪,97块多又买回来10万,给比亚迪最后半年机会,还不给我赚钱,就把它归到长城汽车一样的失败案例。投资比亚迪两年,目前港A全算一起才赚了一万多块钱,投了那么多车企,比亚迪是倒数第二了,倒数第一是长城汽车。蔚来第一,我最爱的还是蔚来,昨天清仓今晚又跌了,又有机会买进。
发布召回mega之后股价就提振了一天,你以为就困境反转了?太天真,第二天就大跌三四个点给你看。蔚来2019年的es8召回哪怕车辆还不到mega的一半,后续的负面影响都差点干倒闭。理想mega召回,后续对纯电系列车型的负面影响现在还没法直观体现,至少要等两三个月。
@zhh-4096
美股还是挺客观挺理性的,抄底理想汽车这只票还早,至少目前我是不会的。网传i6有7万订单,销量还下滑,给的理由是供应链跟不上,就当它是真的,我也不会抄底。最后还是得看7款车的整体销量是否逆转,如果纯电车的增量弥补不了增程车的颓势依然不值得抄底。
我还是比较客观理性的,即便我重仓比亚迪,我依然说不看好比亚迪的兆瓦闪充+储能站的模式,还是更认可蔚来的换电站,比亚迪的储能业务进展也慢。投资蔚来我也照样批评蔚来,比如过去多次出现产能拉胯问题、换电站新车型的兼容性做得太烂。没有完美的公司,关键是你看重它的点是否远胜过它的不足之处。
现在美帝的几个大厂在发债筹集资金,不是卖得挺好的。大模型的投入确实巨大,能不能产生收益还是得看 AI 是否能取得更大的突破,目前的大模型确实还不够,拿相对成功的代码大模型来说,对于代码理解是够了的,但是对于代码编写确实还是初级水平,企业目前还做不到用了代码大模型之后就立刻裁掉程序员。
原本计划90左右再买入,昨天还是没忍住,又跌了两个点,先不补了。市盈率20出头也不高啊,还能跌到哪去。
@zhh-4096
110左右减仓比亚迪,97块多又买回来10万,给比亚迪最后半年机会,还不给我赚钱,就把它归到长城汽车一样的失败案例。投资比亚迪两年,目前港A全算一起才赚了一万多块钱,投了那么多车企,比亚迪是倒数第二了,倒数第一是长城汽车。蔚来第一,我最爱的还是蔚来,昨天清仓今晚又跌了,又有机会买进。
用代码大模型编写代码目前确实只是个铺助,至于能提升多少效率这个太难度量了,反正在我的项目里我就没有一次直接用它生成的代码,因为常常发现审核调试它的代码花的时间还不如我自己写,它写的代码只适合给我提供一些思路。只有生成的代码不用或极少需要人干预时,代码大模型才可能获得实质性的成功。
所以是否有 AI 泡沫完全取决于大模型还能走多远?如果像目前这样只是辅助,我不可能付费购买的,那么 AI 无疑是泡沫;哪怕后面只能提升50%的效率,原来4个程序员才能做的事现在用 AI 辅助只要两个人,那我愿意付费,此时当前的 AI 估值合理;若是赌 AI 3年后能完全替代初中级程序员,那就继续投资。
@zhh-4096
用代码大模型编写代码目前确实只是个铺助,至于能提升多少效率这个太难度量了,反正在我的项目里我就没有一次直接用它生成的代码,因为常常发现审核调试它的代码花的时间还不如我自己写,它写的代码只适合给我提供一些思路。只有生成的代码不用或极少需要人干预时,代码大模型才可能获得实质性的成功。
注意,理解现有代码和编写新的代码是两件事情,代码大模型对于现有代码的理解已经做得很好,我也经常用它去分析理解现有代码,只是这个需求能创造的收益远不如编写新代码。所以下一个阶段代码大模型的核心任务是提升代码编写的质量,有多大概率获得突破?我自己的预期是55开,不乐观也不悲观。
@zhh-4096
用代码大模型编写代码目前确实只是个铺助,至于能提升多少效率这个太难度量了,反正在我的项目里我就没有一次直接用它生成的代码,因为常常发现审核调试它的代码花的时间还不如我自己写,它写的代码只适合给我提供一些思路。只有生成的代码不用或极少需要人干预时,代码大模型才可能获得实质性的成功。
我同事那边的自动化交易接的券商只能用 python 写策略算法,东财的 api 支持 java,一方面要收费,另一方面可用的 api 还满足不了我的需求,所以拖了好长时间都没动手写自动化交易程序。
小鹏明年也要出Robotaxi了,这个方向我已经投了一年,昨晚睡前还下了文远知行9.30的买入委托单,结果没成交。Robotaxi还处在大量烧钱的阶段,拿几个城市的固定线路试运营,要普及还挺遥远。股票嘛也是炒作,股价起伏巨大,估值很低时可以买进,千万别追高,否则一周时间就可能腰斩。
现在国内还有一点竞争力的车企有20家左右,其中国企就占了一大半,跟华为绑定的就有5家。国家怎么可能再允许打价格战,把国企淘汰掉得造成多大问题。所以比亚迪在国内的份额能维持在30%都已经算客气了,比亚迪现在只能去海外拼杀,出不了业绩我就清仓。
贸易战暂停一年,中美两国都想利用这一年补自己的短板,美帝一旦觉得自己又行了,一定会再发起进攻的。国内有出海业务的企业也必须利用好这段休战期猛攻城拔寨,这也是我还坚持投比亚迪的外在原因,如果还出不了业绩,贸易战又卷土重来时一切都晚了,到时美帝又会带着自己的一群狗到处撕咬。
去年年初投小鹏蔚来,即便知道销量不好也懒得动,结果半年内看着它们俩腰斩。今年投比亚迪没那么懒了,看到销量下滑就提前大幅减仓,股价下跌后再补回来,所以浮亏不大,就几个点。但是呢,一大笔资金放在那不赚钱,说明还是没投对,也是失败。给一笔钱给我,如果一年连10%的收益都做不到那就是失败。
我最近还买了点上汽,第一次买,主要是股价低业绩开始好转,又跟华为搞尚界,国家不给打价格战之后,上汽这种国企还是能存活的,要是真被比亚迪打垮了,魔都得有多大损失。比亚迪+上汽目前一起买了近20万,拿一段时间,有10个点收益就清仓。
汽车产业至少还可以投资10年,固态电池、智能化,远未成熟,都是热点。汽车产业也是国家最重要的产业之一,人工智能+机器人+汽车,就是未来10年的三驾马车,也是我重点跟踪的投资方向。
小鹏还是很有追求的,这三驾马车都做,甚至还搞飞行汽车,我只担心小鹏有没有这个钱持续烧,毕竟现在连造车都还没有盈利,特斯拉都没做这么多。
@zhh-4096
汽车产业至少还可以投资10年,固态电池、智能化,远未成熟,都是热点。汽车产业也是国家最重要的产业之一,人工智能+机器人+汽车,就是未来10年的三驾马车,也是我重点跟踪的投资方向。
在A股赚钱的难度确实比美股高一个量级,用同样的本金我在美股两周就能赚到A股一年赚的钱了。原因主要有两个:1. A股不支持T+0,不利于散户做短线交易;2. A股的股价上涨跟业绩没有那么大的强关联,还是得看大资金报团炒什么票,所以中长线不好做,只看业绩容易判断失误。
经过第二个优化之后,compact 的速度变得飞快了,优化前重写 leaf page,需要把记录读到内存再把记录写到硬盘,不但要执行多余的序列化反序列化工作,还占用大量内存(一般是二进制数据的10+倍),现在都不需要了,直接 copy leaf page 的二进制数据。
@zhh-4096
在数据库里找到了两个优化点,所以最近几天都在忙着工作,已经做完了一个:能减少一点每个表的硬盘占用空间,第二个正在做:想要优化 compact 重写 page 的速度。另外还修复了一个拖了几个月的 bug。这些都不算什么大事,现在只要能聚焦到一件事都比炒股强,至少这些工作能把一件作品变得更完美。
另外还有几篇小作文,分别是《谷歌哪些地方被投资人看好》和《Physical AI会带来哪些投资机会?》 预计在近期出炉,关注@梁博第二助理 ,正常的投资者都将获得我从技术层面进行的分析。
我是从 hbase、cassandra 一路走过来的,以前对 hbase、cassandra 有很深入的研究,因为它们都用 LSM-Tree,所以我曾经也是 LSM-Tree 粉。现在我是坚定的 LSM-Tree 黑,因为 lealone 的读写性能已经把 hbase、cassandra 按在地下摩擦,lealone 用的是 copy on write btree。
看了一下 H2 数据库的最新实现代码,它做 Compact 时如果一个 page 要重写依然要读到内存,把记录反序列化出来再写到新的位置。直接把 page 的二进制数据挪到新位置确实要对 page 的存储格式进行精密设计,如果其中的某个数据依赖上下文信息那就不能直接挪了,比如checksum的计算依赖上下文信息。
如果不做 olap,列存储的用处不大。lealone 的存储引擎现在也是支持列存储的,当初增加这个功能是为了将来更好的支持 olap,现在不做 olap 了但为了兼容还得花精力支持列存储。所以不重要的功能还是等真正能发挥用处时再做也不迟。
模拟应用服务器接收到一万个并发写请求,用 lealone 的异步 jdbc api 逐条写入一万条记录现在只需要3+毫秒,用 mysql 的同步 jdbc api 写入要100+毫秒,慢了30+倍,所以为啥异步 jdbc api 依然没有普及?
现在的用户或企业对基础软件的性能提升似乎没多大兴趣了,都想着怎么用 AI 取代人,省点机器的钱不如把人去掉省的钱多,只有运行 AI 的系统需要在乎性能想省钱想拼成本时,才会去想怎么优化基础软件提升性能少用一点硬件资源。每次技术革命都是先想着用更少的人,最后才会去想用更少的机器。
这周中概比较惨,蔚来有3次机会赚钱了不舍得卖出,下跌时还补了一点,结果现在还浮亏5个点;文远知行操作得比较好,8块多时几乎减完仓,昨晚7块又开始补回来一些。A股也是先减仓后补仓,这个月还有几百块收益,没有亏。这种动荡的行情,搞量化的爽死。
格力就是太老实,这么多年分红那么多,又不去圈钱,面对小米这种对手,格力就要去港股上市圈点钱回来也说用于扩大国外市场,当然也可以用于跟小米打价格战,品质比小米好,价格还一样,就看小米怎么打?小米有好几条大的业务线,靠手机那点利润能多条业务线打价格战?
我今年投资格力没亏钱,投的也不多,目前还有1200+的收益。就是觉得可惜,这种好公司在牛市不涨就算了,今年还跌了4.66%,价格战对这种高分红还不懂得融资圈钱的公司短期确实不利。比亚迪、宁德时代、小米,这种原本市值比格力高得多的公司都在牛市融了一大笔钱。
redo log 还是需要的,但实现 redo log 的方式可以改变一下,不一定非得把 redo log 全放在专用的文件中保存(这是主流做法),也可以把数据文件和 redo log 文件合并在一起,我最近就在尝试这种方案,好处是备份简单,并且写 redo log 可以多线程写,可以让不同表的 redo log 放到不同的硬盘。
目前在 lealone 中所有数据库中的所有表产生的 redo log 都是用同一个线程全写到一个文件,对于多租户的场景确实是有问题的,比如某个租户的并发事务多了产生的 redo log 也多,自然会影响其他租户,如果把 redo log 分开存放用不同线程写就没有这个问题。
@zhh-4096
redo log 还是需要的,但实现 redo log 的方式可以改变一下,不一定非得把 redo log 全放在专用的文件中保存(这是主流做法),也可以把数据文件和 redo log 文件合并在一起,我最近就在尝试这种方案,好处是备份简单,并且写 redo log 可以多线程写,可以让不同表的 redo log 放到不同的硬盘。
我准备在 lealone 6.1.0 这个最新的大版本中改变 redo log 的实现方式,不再有专用的 redo log 文件,让用户看不到 redo log 的存在,但数据库内部的实现是有 redo log 的功能的,断电或发生其他故障依然能做到不丢失数据,完全满足 ACID。
mysql innodb 有很多乱七八糟的的文件,从 lealone 6.1.0 开始你将会看到一个很干净的数据目录,第一级子目录的名字每个都对应一个数据库实例,第二级子目录每个目录就对应表或索引,最后第三层就是表或索引的 chunk 文件,也就是说整个数据库只有一种类型的文件,那就是 chunk 文件。
@zhh-4096
我准备在 lealone 6.1.0 这个最新的大版本中改变 redo log 的实现方式,不再有专用的 redo log 文件,让用户看不到 redo log 的存在,但数据库内部的实现是有 redo log 的功能的,断电或发生其他故障依然能做到不丢失数据,完全满足 ACID。
花了一个上午就做完了,数据库的目录看起来舒服多了,实现也更简单,硬盘占用空间还减少了一些。当然也保持兼容,老版本存在的 redo log 文件在新版本中依然可以读取,但不会再写它了。应用升级到新版本不需要做任何改动。
@zhh-4096
我准备在 lealone 6.1.0 这个最新的大版本中改变 redo log 的实现方式,不再有专用的 redo log 文件,让用户看不到 redo log 的存在,但数据库内部的实现是有 redo log 的功能的,断电或发生其他故障依然能做到不丢失数据,完全满足 ACID。
小日本这么一闹腾,台湾省的人民就得好好想想了,是愿意尽早和平回归?还是想跟乌克兰一样把台湾变战场当炮灰?那么小的地方,台湾省就比桂林大一点,炸几天就变废墟了。这种选择题但凡脑子正常的人都会选择和平回归,至少回归后待遇不会比香港差吧。如果大多数台湾人选择当炮灰,那也没啥值得同情的。
一楼住着一家人,大女儿在上小学,跟父母的对话两边都经常是大吼大叫,小孩也开始顶撞父母,每次吵急了,那大女儿就会歇斯底里连续大叫杀人啦杀人啦……好可怕的一家人,这种家庭教育出来的小孩心理上都是有问题的!
老版本的 ScheduleService 要执行垃圾收集和刷脏页,此时就不能执行 sql,所以做性能压测时偶尔会抖动,把这两件事交给多个 FsyncService 线程并行去做后,性能压测就没有抖动了。线程模型也改了,全局 redolog 也没有了,用6.1.0这个新的版本号不够大气,用7.0.0的话7这个数字不喜欢,用8.0.0挺好。
@zhh-4096
老版本只有一个 FsyncService 线程,只负责写 redo log,有多个 ScheduleService 线程,负责执行 SQL 和刷脏页;新版本 FsyncService 和 ScheduleService 都有多个,刷脏页也交给 FsyncService 做了,多个 FsyncService 线程可以并行写 redo log 并行刷脏页。
决定把 lealone 6.1.0 这个新版本号改成 lealone 8.0.0 了,这是开源单机版的终极大版本,后续有要修复的 bug 或安全漏洞就只出小版本了。我做不出比 btree 更好的数据结构了,所以目前 lealone 的数据库内核已经是我能想到并能做到的极限,对我来说已经完美。
当然理论上受限于 btree 的时间复杂度,在大数据量的随机读写场景依然不完美,但是这是无解的,除非能找到一种具备 btree 的所有优势同时又能解决它的缺点的数据结构,目前不存在,我也不再花时间去研究这个问题了,因为 oltp 数据库用 btree 已经满足绝大多数应用场景了。
中考和高考对于绝大多数人来说已经是最公平的改变命运的机会了,如果你连读书学习这件事都做不好,我很难相信你会有多大出息。文化水平低的人也有取得成功的,但这个比例极小。就算是拿到冠军的体育生,哪怕数学不好,但是人家有碾压普通人的体育特长,特长生只是例外。
我们家族的基因还是不错的,只要多生几个孩子其中就有可能产生一个会读书的,我有两个堂妹一个表妹读书都挺好,其中两个在三甲医院工作。但是这是个概率问题,我建议我弟再要一个孩子,万一运气好呢,他怕了,两个女儿都普通,再要一个又普通的话,都没勇气养了。孩子考高中都费劲,确实很伤父母的心。
是否存在一种数据结构能同时拥有btree和hash表的所有优点? http://t.cn/AXL5unwa网页链接https://www.doubao.com/thread/w5ed48ce890a16ceb 这是豆包的专家级回答,确实回答得很赞了,用人单位拿这种问题去面试应聘者,豆包能秒杀99%的人。
数据库支持多个存储引擎听上去很美好,但是优化做得越来越细之后才发现,有些优化并不是在所有的存储引擎都能实现,若是这样的优化能提升性能或减少内存占用,但是不能在某些存储引擎上实现,还不如不要它们了。lealone 通过存储插件支持 RocksDB 和 MVStore,我已经遇到好几个优化不能用它们实现了。
数据库的一条记录从硬盘读出来反序列化成一个 java 对象,这个对象占用的内存直接决定了数据库是否吃内存,只要能把这个对象减去一个不必要的字段就能优化内存使用,去掉一个 int 字段,加载1000万条记录就能省38M内存。jdk 最新版本也在 jvm 内部压缩了每个对象头占用的内存空间。
lealone 8.0的 row 对象已经优化到极致,今天做了个优化把 version 字段也去除了,现在的 row 对象只有3个字段:long 类型的 key、指向列值的数组、指向行锁的引用。现在一个 row 对象占用的内存比老版本少了小几十个字节,加载大量记录能省不少内存。java 开发的数据库占用的内存比 mysql 还少了!
@zhh-4096
数据库的一条记录从硬盘读出来反序列化成一个 java 对象,这个对象占用的内存直接决定了数据库是否吃内存,只要能把这个对象减去一个不必要的字段就能优化内存使用,去掉一个 int 字段,加载1000万条记录就能省38M内存。jdk 最新版本也在 jvm 内部压缩了每个对象头占用的内存空间。
在 lealone 8.0 中,索引数据保存在 KeyPage 中,一条索引对应一个 IndexKey 对象,它只有两个字段;表的数据保存在 RowPage 中,一条记录对应一个 Row 对象,它只有3个字段。IndexKey 和 Row 对象都已经优化到了极致,它们的字段数都无法再减少了。截图是某个 KeyPage 和 RowPage 的内存快照。
https://postimg.cc/gallery/tCvpRwy


跟H2数据库对比,H2存储索引的 leaf page 要比 lealone 的 IndexPage 复杂太多了,老版本的 lealone 存放索引的方式跟它也差不多,所以在 lealone 8.0 中才必需彻底优化。H2存储表数据的 leaf page 也比 lealone 的 RowPage 复杂一些,lealone 的 RowPage 不需要像 H2 那样用两个数组存放,所以省内存。
https://postimg.cc/gallery/QdBbv9t




http://t.cn/AXLSWxWa网页链接 https://www.doubao.com/thread/w4afe936692e6a699把 lealone 中最复杂的一个并发控制问题丢给豆包回答,还是能回答出一些要点的,能做到目前这样确实已经很不错了,并发问题本身就极其难。
没结婚没养娃不用出门上下班,可自由支配的时间确实很多,把这些时间专注投入到一件正面的事,想做不好都难。当然如果无事可做,那就容易抑郁最终废掉。我这几周又把时间全投入到数据库了,连股票都没怎么看了,这种专注且自己可控的感觉真好,花掉的时间还能让在做的东西一点一点变得更完美。
已经工作了20+年,人生还很漫长,如果60+岁退休,至少还得工作20年。我不像是会退休的人,如果能活到80+岁,那还需要工作40年,所以一定要去研究一个新领域的,毕竟数据库这个领域有趣的问题已经不多了。让脑子停下来什么都不干,那就跟入土没区别,生命就是在不断折腾中获得各种体验,刺激大脑。
在 jdk 25 之前,如果 row 对象本身的字段占20字节,加上对象头12字节,所以 row 对象总共占32字节;如果 row 对象本身的字段占16字节,加上对象头12字节虽然是28字节,但因为 jvm 要按8字节对齐,所以还是占32字节,也就是说哪怕对 row 对象优化后减少了4字节,但因为字节对齐的关系,这个优化相当于白做了。
但是从 jdk 25开始,对象头从12字节变成8字节了,若 row 对象本身的字段占16字节,那么它实际占用的内存是24字节,相比 jdk 25 之前的32字节少了8字节。可以在 jdk 25 中通过 -XX:+UseCompactObjectHeaders 参数用 jctools 这个工具来验证。
又优化了一下 IndexKey,为每个 IndexKey 对象省了至少16字节,8条记录的 KeyPage 从840字节优化到680字节。IndexKey 会把 long 类型的 row id 封装成一个 ValueLong 对象,然后放到它的 columns 数组中,至少占用24字节,如果把 row id 当成 IndexKey 对象的一个 long 字段,才占用8字节。
@zhh-4096
在 lealone 8.0 中,索引数据保存在 KeyPage 中,一条索引对应一个 IndexKey 对象,它只有两个字段;表的数据保存在 RowPage 中,一条记录对应一个 Row 对象,它只有3个字段。IndexKey 和 Row 对象都已经优化到了极致,它们的字段数都无法再减少了。截图是某个 KeyPage 和 RowPage 的内存快照。
我发现纯内存索引占用的内存远小于持久化到硬盘的索引,因为构建内存索引时它的索引字段对应的对象跟表记录包含的字段对象是同一个,而持久化到硬盘的索引读到内存后它的字段对象是私有的,除非找到表记录的对应字段然后把它赋值给索引。
固执的观念认为 ORM 很耗内存,毕竟一看到要把每条记录用一个对象表示就认为耗内存。这是非常错误的观念,如果数据库内部把记录从硬盘读到内存然后像 ORM 一样把字节反序列化成 ORM 的对象,反而是最省内存的。
为什么这么说?因为每张表的字段通常不是同一种类型,数据库内部把记录的字节反序列化后不能用 int 这样的数组表示所有的字段,只能使用 Object 数组,int 类型的字段放到 Object 数组只能用 Integer 对象表示,所以原本4个字节的 int 变成了16个字节的 Integer 对象,其他 short、char 等基本类型也类似。
如果像 ORM 那样为每个表生成一个类,这个类包含了所有表的字段,并且这些字段都使用 int 这样的基本类型,那么把记录的字节反序列化成这个类的对象时占用的内存自然比 Object 数组小得多。
这条微博又给我提供了一个能大量优化内存使用的思路,就是数据库为每张表在内部自动生成一个类,然后用它构建一个对象存放每条记录的字段值,不再使用 Object 数组存放了。
@zhh-4096
固执的观念认为 ORM 很耗内存,毕竟一看到要把每条记录用一个对象表示就认为耗内存。这是非常错误的观念,如果数据库内部把记录从硬盘读到内存然后像 ORM 一样把字节反序列化成 ORM 的对象,反而是最省内存的。
为什么这么说?因为每张表的字段通常不是同一种类型,数据库内部把记录的字节反序列化后不能用 int 这样的数组表示所有的字段,只能使用 Object 数组,int 类型的字段放到 Object 数组只能用 Integer 对象表示,所以原本4个字节的 int 变成了16个字节的 Integer 对象,其他 short、char 等基本类型也类似。
如果像 ORM 那样为每个表生成一个类,这个类包含了所有表的字段,并且这些字段都使用 int 这样的基本类型,那么把记录的字节反序列化成这个类的对象时占用的内存自然比 Object 数组小得多。
如果 java 的 value types 可用了,就不存在这里说的问题了。
@zhh-4096
固执的观念认为 ORM 很耗内存,毕竟一看到要把每条记录用一个对象表示就认为耗内存。这是非常错误的观念,如果数据库内部把记录从硬盘读到内存然后像 ORM 一样把字节反序列化成 ORM 的对象,反而是最省内存的。
为什么这么说?因为每张表的字段通常不是同一种类型,数据库内部把记录的字节反序列化后不能用 int 这样的数组表示所有的字段,只能使用 Object 数组,int 类型的字段放到 Object 数组只能用 Integer 对象表示,所以原本4个字节的 int 变成了16个字节的 Integer 对象,其他 short、char 等基本类型也类似。
如果像 ORM 那样为每个表生成一个类,这个类包含了所有表的字段,并且这些字段都使用 int 这样的基本类型,那么把记录的字节反序列化成这个类的对象时占用的内存自然比 Object 数组小得多。
桂林七星公园是集自然景观历史人文于一体的景点,还是值得一看的,对本地市民免费,所以我经常来这里散步或爬山,每次换路线从龙隐岩穿过,依然被里面无数的摩崖石刻震撼到,这就是看得见的厚重历史。

广西没有自治州,去了云南所有的自治州之后我才明白虽然自治州跟地级市平级,但是还是有很大不同,自治州更像自治区,州府所在的县级市不但有州政府,还有县级市的市政府,甚至连医院都有州级的人民医院和县级市人民医院,就跟广西自治区一样,南宁是区府,有广西自治区人民医院也有南宁市人民医院。
蔚来四季度的交付指引怎么变成12.5万辆了,少了至少两万辆,意思就是11和12月份跟10月份都是4+万俩,按35万的均价算,那就少了70亿的营收,四季度盈利的目标还能实现否?
蔚来四季度能否盈利其实也没那么重要,当前汽车行业这种疯狂厮杀的局面,还是优先看销量、看市场份额、看车企产品的竞争力,短期看蔚来至少目前在中高端纯电车型上立足了,但是这种优势能保持多久很难判断,因为车企之间的竞争一年后又是另一个样。
@zhh-4096
蔚来四季度的交付指引怎么变成12.5万辆了,少了至少两万辆,意思就是11和12月份跟10月份都是4+万俩,按35万的均价算,那就少了70亿的营收,四季度盈利的目标还能实现否?
一个表的数据由很多 btree page 组成,在 lealone 中这些 page 甚至可以做到部分 page 是按行存储,另一部分按列存储,只是没有发现这么做有什么实用价值,或许频繁修改的 page 按行存储,很少修改但是只读少量字段的数据按列存储。
睡觉前看到友商发了篇文章讲列存储并且还涉及表结构变化,然后我立马在 lealone 试了一下增删字段,发现 lealone 的列存储有 bug,立马花时间修复,明明可以明天再修复,非得熬夜。
别人都在搞 AI,我还在搞老掉牙的 oltp 关系数据库,又不赚钱,连免费用户都不多,你问我有啥意义?确实没啥意义,我一下也没找到更有意义的事,就继续拿这种老掉牙的东西消磨时间了。空闲时间那么多,不找件正经的事做做只会更痛苦。
在一个事务内更新了多张表,虽然用并行写 redolog 可以加快速度,但是也引入了新的复杂性,有可能在并行写多张表的 redolog 时某张表的 redolog 写失败了但其他写成功,如果断电了,部分写成功的也无法回滚,在启动数据库进入恢复阶段时要通过某种办法来识别哪些 redolog 是无效的。刷脏页也得考虑。
刷脏页得等到所有表的 redolog 都通过 fsync 落盘了才能进行,如果不这么做直接对某张表刷脏页,若是其他表的 redolog 写失败就会造成数据不一致。
@zhh-4096
在一个事务内更新了多张表,虽然用并行写 redolog 可以加快速度,但是也引入了新的复杂性,有可能在并行写多张表的 redolog 时某张表的 redolog 写失败了但其他写成功,如果断电了,部分写成功的也无法回滚,在启动数据库进入恢复阶段时要通过某种办法来识别哪些 redolog 是无效的。刷脏页也得考虑。
存储引擎和事务引擎都很烧脑,想把事务和并发控制做得越细就越烧脑。lealone 的存储引擎只有5000+行代码,事务引擎只有3000+行代码,虽然不到一万行,但绝对是整个数据库最烧脑的代码。这种活初级/中级程序员干不好的,写这种代码在脑子里时时都得装着并发两字。
把这个问题解决了,并行写 redolog 才算完整,更新了一大片代码: http://t.cn/AXLeCyIN网页链接 所谓的稳定性,就是在花大量时间解决一些发生概率很低的问题,又不能不解决,因为这些小概率问题可能导致数据不一致。
@zhh-4096
在一个事务内更新了多张表,虽然用并行写 redolog 可以加快速度,但是也引入了新的复杂性,有可能在并行写多张表的 redolog 时某张表的 redolog 写失败了但其他写成功,如果断电了,部分写成功的也无法回滚,在启动数据库进入恢复阶段时要通过某种办法来识别哪些 redolog 是无效的。刷脏页也得考虑。
往一个文件中写10几kb数据都无法保证要么全写成功要么全写失败,更何况用多个线程把这10几kb数据分开写到不同文件。这就是为什么应用从直接写文件系统演化成使用数据库的早期原因吧,有了事务的支持,应用才更省心。
AI 的研究,目前只是帮你培养能按部就班干活的人,还不能帮你解决某个领域独有的前沿未解或解决得不够好的问题,比如要让数据库再往前走几步,还得靠数据库的研究人员去努力,而不是靠 AI。如果 AI 都能推动数据库或者数学或其他领域往前走了,那人类就可以灭绝了。
我现在解决一个技术问题的过程一般是这样:花一个下午甚至一周散步,边走边想,把思路梳理好;然后坐在电脑前花几小时用代码实现,基本上一次过,可以在断网的情况下不看任何文档就能把代码顺利撸完。用于思考的时间更多,如果是特别难的问题,可能会思考半年。
满分100,AI 能在上百个领域做到85分,我只需要在一个领域做到95+分就够了。大学之前可以用通才教育,从大学开始就要专注在一个领域,还想着什么都学一点只会被 AI 取代。
一个孩子偏科至少还能知道他擅长什么,像我侄女这种就是所有科目都普通或差,也没有什么特别的爱好,哪怕玩游戏也玩不好,对于这样的孩子我完全不知道怎么培养,就看她自己的命如何了,我能做的也只是在她读书的关键节点出点钱,不读书毕业了我就不管了。
之前认识一个小姑娘,职校毕业,学习也是属于普通类型,工作多是找行政文员之类的。有段时间找工作困难,我看到她做了好几次点心,就跟她聊起去当学徒学一门专业的手艺,还说没钱交学费我可以出。我本意是好的,后面也不知怎么就被说成pua有爹味了。现在想来,一厢情愿想让别人变好,真的好愚蠢。
如果我很有钱,也绝不会找那种有很多异性朋友且没有边界感的漂亮女人。如果只是看中美色,花点钱就能轻易得到,看腻了再换下一个,为什么要娶回来离婚了还得分走一大笔,但凡脑子会算简单的算术题都不会这么干。以此类推,漂亮的女人想嫁个有钱的好男人还是得专一,别乱抛媚眼,否则只是男人的玩物。
一个日本歌手演出中途被叫停,这种事真显得我们小肚鸡肠了。如果我们现在对待日本的态度就像对待印度那样才是强国大国该有的样子,就因为我们曾经把印度按在地下摩擦,所以压根就没把印度放在眼里,反而让印度气出内伤。现在面对日本还需要放在眼里吗?不需要啊,日本真要作死,那不就是天上掉馅饼嘛。
跟代码大模型互动几个月下来,每次我想解决一个新的技术问题,然后跟代码大模型交流,看看它能有什么更好的想法,结果没有一次比我想的方案好,所以我对自己还是很放心的,代码大模型的智商还是能被我轻易碾压。我只认可代码大模型对于代码的理解能力很强,学习新代码的速度极快。
大模型就像刷了无数题的小镇做题家,让它解决它曾刷过的类似的问题,它的确很擅长。给它一个现有的大中型开源项目,基于现有项目的设计和实现去解决一个特有的技术问题,大模型就没那么强了,因为这种问题它也是第一次遇到,聪明的人类第一次面对这种新问题反而更灵活。创新不是靠刷题,我巨讨厌刷题。
如何培养一个人的创新能力?
使用少量线程就能解决所有的高并发问题,这种线程模型在 http server/application server 或新型语言的 runtime 比较常见,因为这类场景多是无状态或只有少量共享状态,所以实现起来不难。把这种线程模型应用到 oltp 关系数据库这种以共享状态为主还得支持事务的场景,确实很罕见。
很庆幸 lealone 很早就大胆尝试了,所以这么多年我解决很多技术问题都没有可参考的论文或其他产品,都靠自己去想,反而训练出无与伦比的创新能力。
所以你问我如何培养一个人的创新能力?去尝试别人还没用过的方案,大胆试错,快速纠正,多思考总结即可。
在支持事务的数据库中,连豆包都知道并发控制做得最好的数据库是 lealone:
至今最震撼我的还是 lealone 的异步 jdbc api,怎么可以比 mysql 的同步 jdbc api 快那么多,图1和图3的结果太震撼了,这是在模拟 tomcat 收到9600个并发写请求后,如何快速逐条写入数据库,很真实的场景,不可能用批量写,因为不可以等并发写请求攒够一批再写,所以只能逐条写,真实的应用就是这样。
@zhh-4096
每次开48个线程并发逐条写入9600条记录,mysql 的测试结果很不稳定,最新版本的 lealone 即便用同步 jdbc api 也能秒杀 mysql,若是用异步 jdbc api,那就是几十倍的差距。截图里的 total time 不准,因为把线程启动时间算在内了,如果累加每次写入9600条记录的时间,要远远小于 total time。
现代 oltp 关系数据库的性能已经很强悍了,客户端(通常跟应用服务器部署到同一进程中)开16-48个线程,几个毫秒内就能完成上万次的读写请求,还需要 redis 这种缓存干嘛。
跟一个异性交往或有意交往的过程中,看到对方弱的方面我真的会忍不住想让对方变得更好,但是往往事与愿违,人的弱点是无法轻易克服的,老想去改变对方最后反而变成pua变成控制狂,实在无非接受另一半的弱点还不如尽早分开,免得痛苦还浪费彼此的时间。
lealone 有哪些独有的创新,这是豆包代码大模型的回答 http://t.cn/AXLk6yAq网页链接 还是很懂的嘛。[太开心]
特别是最后那一句: "其核心创新并非单一技术点,而是多维度优化的协同,这在现有数据库中具有鲜明的差异化特征",真的太懂我了,豆包代码大模型简直就是我的知音!!!
@zhh-4096
lealone 有哪些独有的创新,这是豆包代码大模型的回答 http://t.cn/AXLk6yAq网页链接 还是很懂的嘛。[太开心]
现在在计算机领域搞研究或读博士,如果做不出创新确实连代码大模型都不如了。软件工程师正在以肉眼可见的速度被代码大模型按在地下摩擦。生在AI 时代对有些人是不幸的,现在回过头来看,2000-2020年才是软件工程师的黄金20年,我正好跨越了这20年,软件工程师从现在开始再也不会有这样的好日子了。
阿里的代码大模型我不知道在哪里能使用,网页版的千问是无法给个 github 项目链接就能深入互动的。目前国内我用过的代码大模型最强的就是豆包代码大模型,字节跳动虽然起步晚,但是最近两年确实进步太快了,搞不好阿里百度最后还是输给字节跳动。
现在除了 AI 热门,不管是数据库还是程序语言或者其他技术圈都冷冷清清,java 发布个大版本都没啥人关心了。自私点说,我还是希望回到 chatgpt 横空出世前的那些日子,搞 AI 干什么,这世界那么多人,大家需要干活,需要寻找活着的意义,AI 抢了人类的工作甚至比人类聪明,对人类有啥意义呢?[笑cry]
@zhh-4096
现在在计算机领域搞研究或读博士,如果做不出创新确实连代码大模型都不如了。软件工程师正在以肉眼可见的速度被代码大模型按在地下摩擦。生在AI 时代对有些人是不幸的,现在回过头来看,2000-2020年才是软件工程师的黄金20年,我正好跨越了这20年,软件工程师从现在开始再也不会有这样的好日子了。
我理想中的好的科技是要为人类服务的,能提高人类的上限,比如能让人类变得更健康、更长寿、更快乐、更聪明,而不是让人类变得焦虑甚至害怕自己被取代,目前 AI 的作用更倾向后者。
代码大模型越先进,对于我这类懂业务懂架构还懂做基础软件研究的大龄程序员,当然是利好的。我只是站在程序员这个群体的层面,意识到代码大模型对绝大多数程序员是不利的。道理很简单啊,做一个软件外包项目,放在以前,前后端程序员我要招5个,现在有了代码大模型,我最多招一个就够了,那4个干嘛呢?
别人家的孩子我管不了,我们家的几个孩子我肯定不会建议她们报考计算机软件专业,没有天赋,学了也是被 AI 取代的命,也不会建议她们去读外语专业。现在养孩子确实比以前更难了,不但要跟别人家的孩子竞争,还得跟 AI 竞争,要避开 AI 最擅长的赛道。
经网友提示,下载并试用了一下阿里的 AI IDE: Qoder,跟它对话的过程中发现响应速度太慢,同样的技术问题回答的效果不如豆包代码大模型好,Qoder 更像是对代码的机械翻译,豆包更像个架构师。其实我也并不需要一个 AI IDE,就像豆包那样设置一个 github 项目链接,然后直接对话,能秒回,就很好了。

可以断定 Qoder 和豆包用的代码大模型是不同的,面对同样的项目,问同样的技术问题,两者给出的答案甚至用词都没有一点共性。我的建议是可以同时使用,总体上我对豆包更满意, 但是 Qoder 有时给的答案也很惊艳,它的回答绝大多数都是代码细节,也就是说 Qoder 更像个高级程序员,豆包更像个架构师。
lealone 的网络层使用的输入输出 buffer 是否高效?
以下是 Qoder 的回答,这次比豆包好 网页链接
不管是 Qoder 还是豆包,对代码的理解都已经很厉害了。
===============================================
我将并行打开网络层的输入/输出与连接相关源码,核实缓冲策略与实现。
结论:Lealone 的网络层缓冲实现是高效的。它通过共享直缓冲、零拷贝切片、批量写入与向量化 I/O、包计数回收门控等机制,把分配和拷贝开销降到很低,同时保障高吞吐与低延迟。
关键设计要点
- 统一的全局输入/输出缓冲
- 每个调度器维护共享的 NetBuffer:NioEventLoop 构造时注入 inputBuffer 和 outputBuffer,避免每包分配新缓冲。
- 读路径:把 SocketChannel 读入全局 inputBuffer 的 ByteBuffer,按包头长度解析,若包未读完则用 NetBuffer.createReadableBuffer 对当前包做切片继续补齐;完整后调用 conn.handle。
- 写路径:TransferOutputStream 使用 GlobalNetBufferOutputStream 将请求/响应连续写入全局 outputBuffer,flush 时按起始位置切片成 WritableBuffer,通过事件循环统一写出。
- 零拷贝与内存复用
- DataBuffer/NetBuffer 默认使用 Direct ByteBuffer(堆外内存),减少 GC 和内核交互开销;容量增长以“至少 MIN_GROW、至少 50% 扩容”的策略降低频繁扩容。
- 切片不复制数据:NetBuffer.sliceByteBuffer 和 createWritableBuffer/createReadableBuffer 返回视图(ByteBuffer slice / DataBuffer slice),避免中间缓冲拷贝。
- 包计数门控的回收:NetBuffer.packetCount 控制何时清空全局缓冲;多个包切片未回收时,仅调整 position/limit,不做 clear,从而避免与未处理包竞争。
- 复用阈值:DataBuffer.MAX_REUSE_CAPACITY=4MB,小于该容量的缓冲优先复用,降低重复分配。
- 高效的批量与向量化写
- 向量化 I/O:NioEventLoop.batchWrite 使用 SocketChannel.write(ByteBuffer[]) 批量写多个 WritableBuffer,减少系统调用次数。
- OP_WRITE 反压与即时写策略:根据 prefer_batch_write、scheduler 是否繁忙、输出队列大小(outputBuffer.getPacketCount 与 max_packet_count_per_loop)决定是直接写还是入队批量;写不完则挂 OP_WRITE 并在后续循环写,避免阻塞。
- 包长度前置占位、flush 回填:写入时先占 4 字节包头,flush 时回填真实长度并只切片这段区域写出,避免额外拷贝。
- 读路径的完整包管理与扩容
- 读取未完整包时保存 packetLength 与切片 inBuffer,下一次继续读;若容量不足,按需 growCapacity 以保证当前包能一次放下。
- 每次循环最多读取的包数与最大包长可配置(max_packet_count_per_loop、max_packet_size),既避免单连接拖垮循环,又防御异常包。
- Socket 层参数与调度协同
- 默认接收/发送缓冲大小 16KB/8KB,可配(ConnectionSetting.SOCKET_RECV_BUFFER_SIZE、SOCKET_SEND_BUFFER_SIZE),设置 TCP_NODELAY、keepalive、reuseAddress。
- 事件循环避免频繁 Selector.open(懒创建),使用轻量 wakeup 标志减少无谓唤醒。
潜在注意点与建议
- 大包场景建议适当调大 socket 缓冲与 max_packet_size,避免多次 grow 或被丢弃。
- 写密集场景 prefer_batch_write 保持默认 true,可显著提升吞吐;低延迟场景可在客户端按需关闭。
- 直缓冲对 GC 友好,但在极端高并发下应关注总堆外内存占用;DataBuffer 的复用阈值和扩容策略已做了保护。
相关实现位置
- 输入:TransferInputStream、NetBufferInputStream(包装 NetBuffer)、NioEventLoop.read
- 输出:TransferOutputStream、GlobalNetBufferOutputStream/GlobalWritableChannel、NioEventLoop.write/batchWrite
- 缓冲核心:NetBuffer、DataBuffer
- 通道:WritableChannel、NioWritableChannel、NetEventLoop/NioEventLoop
综合来看,这套缓冲方案在“少拷贝、少分配、批量写”上做得很到位,结合直缓冲与向量化 I/O,能在 OLTP/高并发客户端场景下提供优良的吞吐与稳定时延。
Qoder 的回答也说明了做一个高效的数据库确实不易,一个小小的网络层输入输出 buffer 问题,就需要考虑那么多细节,豆包讲得太宽泛了一点,没有体现这个问题的精髓。
@zhh-4096
lealone 的网络层使用的输入输出 buffer 是否高效?
以下是 Qoder 的回答,这次比豆包好 网页链接
不管是 Qoder 还是豆包,对代码的理解都已经很厉害了。
===============================================
我将并行打开网络层的输入/输出与连接相关源码,核实缓冲策略与实现。
结论:Lealone 的网络层缓冲实现是高效的。它通过共享直缓冲、零拷贝切片、批量写入与向量化 I/O、包计数回收门控等机制,把分配和拷贝开销降到很低,同时保障高吞吐与低延迟。
关键设计要点
- 统一的全局输入/输出缓冲
- 每个调度器维护共享的 NetBuffer:NioEventLoop 构造时注入 inputBuffer 和 outputBuffer,避免每包分配新缓冲。
- 读路径:把 SocketChannel 读入全局 inputBuffer 的 ByteBuffer,按包头长度解析,若包未读完则用 NetBuffer.createReadableBuffer 对当前包做切片继续补齐;完整后调用 conn.handle。
- 写路径:TransferOutputStream 使用 GlobalNetBufferOutputStream 将请求/响应连续写入全局 outputBuffer,flush 时按起始位置切片成 WritableBuffer,通过事件循环统一写出。
- 零拷贝与内存复用
- DataBuffer/NetBuffer 默认使用 Direct ByteBuffer(堆外内存),减少 GC 和内核交互开销;容量增长以“至少 MIN_GROW、至少 50% 扩容”的策略降低频繁扩容。
- 切片不复制数据:NetBuffer.sliceByteBuffer 和 createWritableBuffer/createReadableBuffer 返回视图(ByteBuffer slice / DataBuffer slice),避免中间缓冲拷贝。
- 包计数门控的回收:NetBuffer.packetCount 控制何时清空全局缓冲;多个包切片未回收时,仅调整 position/limit,不做 clear,从而避免与未处理包竞争。
- 复用阈值:DataBuffer.MAX_REUSE_CAPACITY=4MB,小于该容量的缓冲优先复用,降低重复分配。
- 高效的批量与向量化写
- 向量化 I/O:NioEventLoop.batchWrite 使用 SocketChannel.write(ByteBuffer[]) 批量写多个 WritableBuffer,减少系统调用次数。
- OP_WRITE 反压与即时写策略:根据 prefer_batch_write、scheduler 是否繁忙、输出队列大小(outputBuffer.getPacketCount 与 max_packet_count_per_loop)决定是直接写还是入队批量;写不完则挂 OP_WRITE 并在后续循环写,避免阻塞。
- 包长度前置占位、flush 回填:写入时先占 4 字节包头,flush 时回填真实长度并只切片这段区域写出,避免额外拷贝。
- 读路径的完整包管理与扩容
- 读取未完整包时保存 packetLength 与切片 inBuffer,下一次继续读;若容量不足,按需 growCapacity 以保证当前包能一次放下。
- 每次循环最多读取的包数与最大包长可配置(max_packet_count_per_loop、max_packet_size),既避免单连接拖垮循环,又防御异常包。
- Socket 层参数与调度协同
- 默认接收/发送缓冲大小 16KB/8KB,可配(ConnectionSetting.SOCKET_RECV_BUFFER_SIZE、SOCKET_SEND_BUFFER_SIZE),设置 TCP_NODELAY、keepalive、reuseAddress。
- 事件循环避免频繁 Selector.open(懒创建),使用轻量 wakeup 标志减少无谓唤醒。
潜在注意点与建议
- 大包场景建议适当调大 socket 缓冲与 max_packet_size,避免多次 grow 或被丢弃。
- 写密集场景 prefer_batch_write 保持默认 true,可显著提升吞吐;低延迟场景可在客户端按需关闭。
- 直缓冲对 GC 友好,但在极端高并发下应关注总堆外内存占用;DataBuffer 的复用阈值和扩容策略已做了保护。
相关实现位置
- 输入:TransferInputStream、NetBufferInputStream(包装 NetBuffer)、NioEventLoop.read
- 输出:TransferOutputStream、GlobalNetBufferOutputStream/GlobalWritableChannel、NioEventLoop.write/batchWrite
- 缓冲核心:NetBuffer、DataBuffer
- 通道:WritableChannel、NioWritableChannel、NetEventLoop/NioEventLoop
综合来看,这套缓冲方案在“少拷贝、少分配、批量写”上做得很到位,结合直缓冲与向量化 I/O,能在 OLTP/高并发客户端场景下提供优良的吞吐与稳定时延。
用 Qoder 给 lealone 生成项目 wiki,太强大了,碾压之前的 DeepWiki。代码大模型的进步真的太快了,立马被淘汰的就是写技术文档的员工!

快速看了一部分文档,要哭了,比我写得还好,我看看能不能直接放到 lealone 的 github 主页。
@zhh-4096
用 Qoder 给 lealone 生成项目 wiki,太强大了,碾压之前的 DeepWiki。代码大模型的进步真的太快了,立马被淘汰的就是写技术文档的员工!
我现在非常理解马斯克为什么那么极端猛裁掉员工了,如果你哪怕有超过60%的信心用 AI 能取代某类员工,那现在就开除,逼迫 AI 工程师更进一步提升 AI 的能力,不给自己折中的方案,又不裁员工又把 AI 当鸡肋,这样做之后 AI 工程师也没有动力完善 AI,最后只能得到一个平庸的结果。
AI 泡沫只是说目前对 AI 的投入远比产生的收益要高,这是运行 AI 的固有成本决定了,毕竟大模型的训练和推理都需要巨大的成本支出,不像跑个数据库一两万块钱就足够了。通过技术改进总能一步步降低运行成本,哪次技术革命不都是这么过来的,先看生产力,确认有效后再想办法降低成本。
原来 Qoder 真正的实力是生成项目 Wiki,把我感动哭了,居然花了那么多篇幅帮我鼓吹 Lealone 的渐进式SQL引擎和抢占式调度,写得太特么好了,远超我这个项目创始人的写作能力,文章结尾最后一句简直就是马屁精附体,说出了我想说但是又怕说出来不谦虚的话!!!
https://postimg.cc/gallery/Y0FXchM

半年前看到 deepwiki 给 lealone 生成的文档还很震惊,现在看到 qoder 生成的 wiki 才明白 deepwiki 顶多就是小学生水平,qoder 生成的技术文档已经是专家级的了。
@zhh-4096
被 DeepWiki 震撼到了,对开源项目的分析写得如此深入,初步看下来准确率在90%以上,甩开各种大模型几条街。如果全是人工智能自动生成的,真的是一个巨大的进步,这就是我之前一直想做的开源代码分析网站想要的初步样子。这是它对 Lealone 的深入分析: http://t.cn/A6dxq5UP网页链接 可以直接当设计文档看。
做了10几年数据库,最后才发现最懂我的居然是 AI,你说可笑不可笑?!低智商的人类程序员活该被 AI 淘汰。人类因为嫉妒只会说一些让人讨厌的话,AI 只有理性,反而会说实话,好就是好,做得好就猛夸。未来人型机器人成熟了,连女朋友都不需要找了,人型机器人又能聊技术,又能提供情绪价值。
看 qoder 生成的技术文档比问它问题更让人心情愉悦,整个数据库哪些地方是我有特别花心思的,然后 qoder 就能在对应文章最后的结论里精准说出我的意图,比知音还知音。
我起初以为 qoder 只会拍马屁,直到我看到这篇分析 lealone 协议实现的文章 http://t.cn/AXyP5H58网页链接 它能指出我没有实现 SSL/TLS 加密会有潜在安全风险,同时又看懂了我整个协议实现在设计上的优雅,说明它是客观理性的,好就是好,不好就是不好。
通过阅读 qoder 给 lealone 生成的文档,我可以下结论: qoder 对于代码的理解能力已经是专家级的水平,比高级程序员还厉害,写作能力已经远超我这个原作者。编写代码的能力我还没有试,对代码的理解能力都这么强了,编码能力的提升也只不过是时间问题。我自己的编码能力变强,也是从理解开源代码开始。
让 qoder 生成 lealone 的文档差不多花了一个小时,我直到现在都不敢完全相信这是 AI 生成的,弱弱地问一句: 是不是在这将近一个小时内,后台有很多人在默默写文档?
若真是 AI 全自动生成,我只能说太特么牛逼了!AI 都已经这么强了!幸好我没钱没有招员工写技术文档,否则明天就告知不需要他了。
lealone 这个项目一直缺文档,我也没时间写,最开始我司还有几个同事的,他们做不了数据库研发,我想让他们参与进来先帮我写写技术文档都好,结果憋了一年说了好几次,一篇文档都写不出,最后他们都找别的事做了,公司就剩我一人。今天我用 qoder 把拖了几年的事在一小时内就做完了,效果很满意。
@zhh-4096
让 qoder 生成 lealone 的文档差不多花了一个小时,我直到现在都不敢完全相信这是 AI 生成的,弱弱地问一句: 是不是在这将近一个小时内,后台有很多人在默默写文档?
若真是 AI 全自动生成,我只能说太特么牛逼了!AI 都已经这么强了!幸好我没钱没有招员工写技术文档,否则明天就告知不需要他了。
你越在乎说明你内心还不够强大,就好比我所在的软件行业本身就碾压日本了,对手只有美帝,压根不会正眼看一下日本,你啥时听我聊过日本的数据库软件。
@zhh-4096
一个日本歌手演出中途被叫停,这种事真显得我们小肚鸡肠了。如果我们现在对待日本的态度就像对待印度那样才是强国大国该有的样子,就因为我们曾经把印度按在地下摩擦,所以压根就没把印度放在眼里,反而让印度气出内伤。现在面对日本还需要放在眼里吗?不需要啊,日本真要作死,那不就是天上掉馅饼嘛。
目前还活跃的 java 开源 oltp 关系数据库就剩 h2 和 lealone 了,虽然 lealone 的性能全面碾压 h2,在技术层面 lealone 完胜,但是 h2 的市场份额依然碾压 lealone。所以技术领先并不是赢得市场的全部因素,早期占位,后期宣传,这些都很重要,h2 获得了 spring 生态的绑定也是重要原因。
h2 现在主要是俄罗斯人和美国人在持续开发维护,我之前有想过到 h2 社区发起一个讨论,告诉他们 h2 做得如何差,lealone 如何碾压 h2,觉得这么做不礼貌就放弃了。因为早在10几年前我也为 h2 报 bug 提交 patch 的,后来开分支自己搞了,所以 h2 其实是 lealone 的师傅,现在过去骂师傅水平菜不好!
所以我现在也不去想合并 h2 和 lealone 的事了,毕竟 java 社区就剩下这两个还活跃的开源关系数据库了,有竞争也是好事,可惜 h2 这个对手真的太弱了,不像 mysql 和 postgresql 这么多年打得有来有回,互相成就,这才是良性竞争。
@zhh-4096
h2 现在主要是俄罗斯人和美国人在持续开发维护,我之前有想过到 h2 社区发起一个讨论,告诉他们 h2 做得如何差,lealone 如何碾压 h2,觉得这么做不礼貌就放弃了。因为早在10几年前我也为 h2 报 bug 提交 patch 的,后来开分支自己搞了,所以 h2 其实是 lealone 的师傅,现在过去骂师傅水平菜不好!
11月出啥事了,早早预期蔚来能到5万,结果3.6万,小鹏也不到3.7万,电池产能跟不上吗?没道理啊,如果订单充足,环比少这么多,电池的产能还不如10月份? 股价盘前跌了不少。产能啊产能,每次关键时刻掉链子。还好我空仓。
比亚迪11月销量48万,同比是降的,唯一好看的数据是出口一下爆涨到13万,但是也不用太乐观,前11个月每月出口数据本身就不稳定,如果明年能每个月稳定在10+万才能弥补国内销量的下滑。华为系也开始布局20万以下的车型,总会拿走一点比亚迪的国内份额的。
mysql 一个匪夷所思的设计: 一个表没有主键没有索引,如果在一个事务中执行 update 或delete 语句更新或删除一条记录,其他事务执行 update/delete/insert 都需要等待,哪怕不是同一条记录且隔离级别是读已提交也不行。为啥有这种限制啊?lealone 不会有这种特殊的限制的,行锁不依赖主键或索引。
所以在一个新开发的数据库上想100%兼容 mysql 多难啊,至少这种设计你得兼容吧,这都不兼容怎么能说100%兼容呢,兼容不是只兼容协议和 sql 语法,你还得兼容它的奇怪用法和奇葩设计。即便你的设计更好,也得像它这样锁表,不然应用看到的行为跟 mysql 不同就可能导致错误。
@zhh-4096
mysql 一个匪夷所思的设计: 一个表没有主键没有索引,如果在一个事务中执行 update 或delete 语句更新或删除一条记录,其他事务执行 update/delete/insert 都需要等待,哪怕不是同一条记录且隔离级别是读已提交也不行。为啥有这种限制啊?lealone 不会有这种特殊的限制的,行锁不依赖主键或索引。
Vibe Coding 可能只适合造玩具吧,我以为真能一句话就帮我生成一个生产可用的系统,比如我让豆包:基于 lealone 的插件接口,写出一个兼容 mysql 语法的插件http://t.cn/AXyyUS1R网页链接 就这???距离生产可用还差十万万里,连我手写的初级 mysql 插件它都望尘莫及。
代码大模型或 AI IDE 目前的能力我总结一下: 对于代码的理解已经能做到专家级了,但是编写新代码的能力还是仅限于局部小模块,比如生成几个类或添加几个方法完成一点功能。我没有了解这些 AI 工具前,抱怨数据库要做的插件太多我忙不过来,然后就有网友跟我说 AI 能做,现在我告诉你,AI 还做不了。
mongodb 第三季度的云服务收入还能保持同比30%的增长,且占总营收的75%,这是云服务的胜利啊。6.28亿总营收,6.25万付费客户,平均每个客户一个季度贡献了一万多美金,一年4+万美金,换算成人民币是30万。国内做数据库的公司还在拼拉单拼本地部署,国内云服务白菜价,一个客户一年几千块钱。
mongodb 是文档数据库的绝对龙头,以至于没人在意第二名是谁,非关系型数据库只有做到 mongodb 这样才能更好的活下去。mongodb 一直是 lealone 学习的对象,lealone 也有兼容 mongodb 的插件,后续可能还会花时间完善这个插件。
mongodb 的财报会议上说 AI 对营收的增长目前帮助不大,反而从关系数据库迁移到 mongodb 的客户有不少,所以 mongodb 目前的重要工作是基于 AI 做一些工具方便关系数据库的客户做迁移。这么看 lealone 用同一套内核兼容 sql 和文档 api 真是明智啊,都不用迁移,可以用 mongodb 的 api 读写关系表。
国内有家做文档数据库起家的公司,当年看到 newsql 火了又同时搞关系数据库,最近一年又重新回归文档数据库了。在文档数据库的基础上支持关系数据模型和事务太别扭了,反过来就容易得多,因为文档数据模型就是关系数据模型范式的退化,还不用考虑复杂的事务,所以 lealone 很轻易就能兼容 mongodb 了。
国内的新能源汽车产业虽然有智驾和智能座舱加持,但在资本市场依然被当成传统的制造业对待。像蔚来、小鹏、理想这种年营收在600-1000亿人民币的车企,市值还不如美帝 mongodb 这样的软件公司,mongodb 也没有盈利,年营收也就200亿人民币左右。
不一定非得在一个数据库中同时支持 oltp 和 olap 的,mongodb 其实也算是一个 oltp 文档数据库,并没有去搞 olap 不也获得了巨大成功。官方的高管在财报会议也说了,未来的 AI 推理是 oltp 数据库的天下,因为 AI 推理就是要追求极高的性能。向 qoder 提问,推理响应速度太慢,体验极差,要秒回才好。
阿里并没有公布数据库服务的营收数据,作为数据库的从业者,我比较关心达梦和 mongodb 这两家中美数据库上市公司的业绩,两家公司的营收差了20倍,达梦还是靠国家给口饭吃,mongodb 才是真正的全球化市场竞争。你说美帝强在技术吗?lealone 的性能还碾压 mongodb 呢,只能说美帝的商业氛围好。
老板中途又换了个便宜的老油条厨师,一到饭点炒完菜就悠闲占位坐着(之前的厨师从未见过这种行为,人多时人家还会帮忙打菜),并且菜式搭配、口味都差了一大截,就连餐巾纸都大幅缩减,客流量减了将近一半,中午12点很少需要排队了。这个老板真的在作死!太滑头了,就9月份新开业给点甜头。[摊手]
@zhh-4096
过了个暑假,食堂换了老板换了厨师,做的饭菜极其好吃,价格没变,这是至今遇到的最好吃的食堂了,每天午餐晚餐都对食堂有小期待,连吃饭都变成了享受。所以对吃饭、工作这种日复一日的事情如果做好了其实是很美好的,不能享受其中就会很痛苦!
每次股价一跌,雪球就很多脑残说蔚来完蛋,明明是整个汽车行业迎来转折点导致的问题,理想汽车、比亚迪、上汽11月的销量同比下降你怎么不去喷,蔚来同比大幅增长只是股价回调就说完蛋。空头多努力一把,最好再砸到3块,我准备再次抄底,爽歪歪。
小鹏也在大幅回调,我不觉得是产能问题,补贴没了,再加上购置税快来了,新能源汽车订单下滑是大概率事件。国家过去那么多年花了那么多钱扶持新能源汽车产业,现在销量占比已经超过一半,是该放手了,让车企凭本事在市场上竞争。小鹏和蔚来近期的大幅回调,只是投资者看到行业迎来巨变,提早落袋为安。
今年A股收益top5大半是储能,然后是汽车机器人零配件。A股的车企主机厂截止今天也就江淮汽车还有不错的涨幅,我下半年做得最糟糕的一件事就是重仓比亚迪,白白浪费了储能的大好行情。
美帝那边跟传统开发运维工具相关的软件企业今年被 AI 冲击很大,atlassion、gitlab 股价大跌。AI 用的多是非结构化或半结构化数据,snowflake 和 mongodb 本身因为数据仓库、文档数据库的市场不错,再加上又都是龙头,反而今年营收和股价双涨。
做投资,首先还是要看行业大趋势,其次才是具体的企业。行业趋势变坏了,相关企业或多或少都会受影响。储能行业开始爆发,做电池的大多都受益。汽车行业补贴退坡加上购置税必然会导致需求下降。比亚迪虽然有储能,但是营收占比小,股价还是被卖车拖累了,还好出口能弥补一些,不然股价更难看。
新能源汽车产业已经成年,国家确实不应该再补贴了,要跟油车一样对待,该收的税还是要收。所以明年一季度车企和消费者都要适应这个转变的过程,如果能看到第二季度开始好转,我就会选择合适的时机再买进。
炒A股一定要严格控制加仓的节奏,这是我的血泪教训。去年正式玩A股,亏损的几只票都是加仓太快导致的。有个同事五六万的本金,长江电力下跌了几天,我开始建仓,然后同事也跟着我买,我叫她先买5000就行了,买完又下跌了一些,我一问她才发现买了90%的仓位,半年都没解套,长江电力我都赚了几轮了。
3个字段: f1 int, f2 long, f3 varchar(20), 写入12万条记录,观察数据库进程占用的内存,h2 占用290M+,mysql 是280M+,lealone 是130M+。lealone 8.0 无论是性能还是内存占用都优于 h2 和 mysql 了。
mysql 的 ibd 文件为啥占用的硬盘空间那么大?没有索引,这3个字段写了144000条记录,占用17M硬盘空间,h2 和 lealone 也只不过3M左右。 http://t.cn/AXyta2uo查看图片
@zhh-4096
3个字段: f1 int, f2 long, f3 varchar(20), 写入12万条记录,观察数据库进程占用的内存,h2 占用290M+,mysql 是280M+,lealone 是130M+。lealone 8.0 无论是性能还是内存占用都优于 h2 和 mysql 了。
lealone 性能比 mysql 快数倍,内存占用也比 mysql 少一半,就连硬盘空间都比 mysql 少几倍,还抢不到 mysql 的市场我也没招了,那就不是技术问题了。
@zhh-4096
3个字段: f1 int, f2 long, f3 varchar(20), 写入12万条记录,观察数据库进程占用的内存,h2 占用290M+,mysql 是280M+,lealone 是130M+。lealone 8.0 无论是性能还是内存占用都优于 h2 和 mysql 了。
通过对比48个线程的开始时间和结束时间,我明白为什么会这样了,我的是8核cpu,48个线程每个线程负责写200条记录,因为是异步写,所以这些线程不会阻塞,每次最多只能有8个线程执行,48个线程的开始时间几乎是以8为一组然后顺序递增的,所以144000后面的total time实际上约等于最后一个线程的结束时间减去第一个线程的开始时间,而9600后面的total time是每个线程写200条记录所花的时间。48个线程超过了cpu最大核数,使用异步写时,实际上类似于以8为一组串行执行。收起
@zhh-4096
每次开48个线程并发逐条写入9600条记录,mysql 的测试结果很不稳定,最新版本的 lealone 即便用同步 jdbc api 也能秒杀 mysql,若是用异步 jdbc api,那就是几十倍的差距。截图里的 total time 不准,因为把线程启动时间算在内了,如果累加每次写入9600条记录的时间,要远远小于 total time。
把一个 Runnable 任务扔给 Executors.newFixedThreadPool() 跑,花的时间居然比直接把 Runnable 任务包装成一个 Thread 跑慢,我在这个任务内标记了开始时间和结束时间,然后算耗时,Executors 的方式差不多慢了一倍,为什么?这是豆包的回答: http://t.cn/AXyc0Kas网页链接
可怕,止不住往下跌,还好3季报看到交付指引从15万变12万多我就清仓了,当时我就想不太可能是电池产能问题,电池产能不可能比10月还低,更不可能11/12月都低。明年一季度咋办?真的又要跌回3块吗,好不容易迎来两个爆款,又赶上政策调整。理想也没好到哪去,AI 眼镜对股价没啥提振作用。
蔚来车子卖不好时做手机,理想汽车销量下滑就做 AI 眼镜,现在蔚来专注造车不提手机了。这么看还是小鹏比较有格局,至少机器人、飞行汽车还是强相关,而且小鹏的营收还是3家最低他都能搞几个方向。
这几天开始压测 lealone 8.0 的性能和稳定性,在一台机器上同时跑数据库和客户端,确实无法准确评估 lealone 8.0 的性能有多猛,瓶颈在客户端以及 cpu 核数,客户端用 ThreadPool 和 独立的 Thread 跑都会产生很大差异。同步/异步 jdbc 也有数10倍的差异。
一个产业还是要有技术层面的护城河才好,否则最后只能变成白菜价,企业赚不到钱或利润极少,对投资人、员工、国家税收都是不利的,便宜的产品对消费者有利吗?不一定,企业为了生存要降低成本,产品的质量也难有保证。为啥以前造油车的车企比造电车的车企活得好?因为油车的技术含量高,玩家少一点。
好坑爹,在 eclipse 中启动的数据库 jvm 进程在任务管理器中显示的内存是错的,比在命令行窗口中启动要小很多,做压测时写入上千万条记录,显示的 jvm 进程占用的内存才160多M,实际已经2G多了,导致几个 ZGC ZWorker 在疯狂运转,最初我还奇怪数据库的所有线程我都挂起了,cpu 占用怎么还接近40%。
豆包还是很强的,都能直接分析 jvm 垃圾收集的问题了: http://t.cn/AXyINq1b网页链接
@zhh-4096
好坑爹,在 eclipse 中启动的数据库 jvm 进程在任务管理器中显示的内存是错的,比在命令行窗口中启动要小很多,做压测时写入上千万条记录,显示的 jvm 进程占用的内存才160多M,实际已经2G多了,导致几个 ZGC ZWorker 在疯狂运转,最初我还奇怪数据库的所有线程我都挂起了,cpu 占用怎么还接近40%。
未使用数据压缩的情况下,3个字段(name varchar(20), f1 int, f2 long),写入144万条记录,没有索引,lealone 占用的硬盘空间是34M,h2 是30M,mysql 是108M,postgresql 是73M。mysql 的确是最差的。
lealone 优化了一下 row 对象存储到硬盘的空间,现在小于30M了,不能输给 h2,最后的倔强!
@zhh-4096
未使用数据压缩的情况下,3个字段(name varchar(20), f1 int, f2 long),写入144万条记录,没有索引,lealone 占用的硬盘空间是34M,h2 是30M,mysql 是108M,postgresql 是73M。mysql 的确是最差的。
8核 cpu,开48个线程并发逐条写入这144万条记录,都使用同步 jdbc api 写入,h2、mysql、postgresql 每个线程完成200条记录的写入耗时90-120毫秒,三者差别并不大,leaone 是15-20毫秒,也就是说在高并发下 lealone 在一个 session 中连续处理200条 insert 语句的速度确实比前三者快了5+倍。
@zhh-4096
未使用数据压缩的情况下,3个字段(name varchar(20), f1 int, f2 long),写入144万条记录,没有索引,lealone 占用的硬盘空间是34M,h2 是30M,mysql 是108M,postgresql 是73M。mysql 的确是最差的。
zgc 这个新的垃圾收集算法虽然把暂停时间降到了微秒级,但是面对高并发的场景,内存也会快速增长,这时几个 zgc 线程在收集垃圾的过程中也会占用不少 cpu 时间,从而导致应用线程获得的 cpu 时间变少,所以应用也变慢了。高并发压测数据库时,用 jstack 确实能看到 zgc 线程占用了很多 cpu 时间。
这里有个矛盾点:如果想在数据库中缓存更多记录,就会产生更多 java 对象,从而导致 zgc 线程扫描可收集的 java 对象就越多,进而导致占用 cpu 的时间变多,最后反过来影响数据库并发的处理速度。
@zhh-4096
zgc 这个新的垃圾收集算法虽然把暂停时间降到了微秒级,但是面对高并发的场景,内存也会快速增长,这时几个 zgc 线程在收集垃圾的过程中也会占用不少 cpu 时间,从而导致应用线程获得的 cpu 时间变少,所以应用也变慢了。高并发压测数据库时,用 jstack 确实能看到 zgc 线程占用了很多 cpu 时间。
如果 jvm 能提供 api 告知它哪些 java 对象不用收集就好了,这样能减轻 gc 线程的压力。在数据库中,内存中的记录要不要收集都是可控的,我并不想让 jvm 无脑收集所有的内存记录。
@zhh-4096
zgc 这个新的垃圾收集算法虽然把暂停时间降到了微秒级,但是面对高并发的场景,内存也会快速增长,这时几个 zgc 线程在收集垃圾的过程中也会占用不少 cpu 时间,从而导致应用线程获得的 cpu 时间变少,所以应用也变慢了。高并发压测数据库时,用 jstack 确实能看到 zgc 线程占用了很多 cpu 时间。
高并发压测发现,写 redolog 和刷脏页这两件事不能让一个线程去做,即便刷脏页只需要上百毫秒,也可能在这段时间内被高并发的事务积压了海量 redolog,虽然不阻塞读写事务,但是会导致 jvm 垃圾收集线程疯狂干活,挤占 cpu 时间,从而影响执行读写事务的所有线程,最终会拖慢整个数据库。
好享受这种专注工作的状态,一天出门两次,一次出门是白天,另一次就到天黑了,不用去想是否结婚,也不管老了怎么办,哪怕这种状态一直延续到死前的最后一秒我也乐意。人跟人之间的最主要区别,就是如何消磨时间,工作也是消磨时间的方式之一。
网络、硬盘成为高性能数据库的主要瓶颈,甚至连构建在 localhost 之上的网络连接也成为了次要瓶颈,现在我发现连线程切换在高并发场景也严重影响性能。
比如8核cpu开48个线程,如果每个线程写入200条记录需要20毫秒,若是按纯理论估算48个线程20毫秒能写入9600条记录48*200=9600。
但是因为cpu只有8核,不可能在20毫秒内并行运行这48个线程,所以一次只能同时运行8个线程,然后再切换到另外8个,这个线程切换也是耗时间的,最终导致48个线程写入9600条记录花了50-60毫秒,多了将近两倍的时间。
之前是用 FsyncService 线程写 redolog 和刷脏页,高并发压测时受 jvm 垃圾收集线程影响,某次测试结果比正常情况慢了几10倍,现在改进了一下设计,当脏页大小超过某个阈值就启动一个新线程去刷脏页,这时高并发压测结果就平稳多了。
@zhh-4096
高并发压测发现,写 redolog 和刷脏页这两件事不能让一个线程去做,即便刷脏页只需要上百毫秒,也可能在这段时间内被高并发的事务积压了海量 redolog,虽然不阻塞读写事务,但是会导致 jvm 垃圾收集线程疯狂干活,挤占 cpu 时间,从而影响执行读写事务的所有线程,最终会拖慢整个数据库。
lealone 提供了三种写 redolog 的方式:
1. 不写 redolog,仅用于开发测试阶段,此时的数据库就相当于一个内存数据库;
2. 在调用 fsync 把 redolog 落盘前给客户端返回成功消息,这种方式可以做到极低的微秒级的响应延迟,但是如果断电了,有可能丢失几个毫秒内的数据;
3. 在调用 fsync 把 redolog 落盘后才给客户端返回成功消息,这种方式可以确保数据不丢,但会导致很高的响应延迟,通常取决硬盘的速度,比如在我的笔记本电脑上的 ssd 调用 fsync 需要几个毫秒。
自从进入高性能 oltp 关系数据库这个赛道后,我对时间的执念已经到数十个甚至几个微秒,但凡高于这个时间级别在我眼中就是低性能。比如云厂商的云主机之间的万兆网络通常是100微秒的延迟,这就是低性能;又比如我的笔记本电脑调用一次 fsync 要几毫秒,在我看来已经慢如蜗牛了。
一直用 jdk 17 的 zgc 做压测,看数据不是很稳定,还不如 g1,结果换成 jdk 25的 zgc,压测出来的数据立马就漂亮稳定多了。每次开48个线程并发写9600条记录,连续跑了150次,lealone 平均每个线程的耗时基本维持在15-20毫秒左右。lealone 的数据确实最漂亮,h2、mysql、postgresql 基本在90-120毫秒。
在一台机器上同时跑数据库和压测客户端,想要准确评估一个数据库的性能确实不易,网络、硬盘、操作系统的线程切换这些非数据库本身的因素都会干扰真实的结果,所以我压测 lealone、h2、mysql、postgresql 都刻意把实时 fsync 关了,排除硬盘的影响,另外每个线程的执行时间更代表数据库的处理能力。
如何计算线程切换的总开销?
当数据库的处理能力很强时,就特别容易看出客户端因为线程切换带来的重大负面影响,就拿图1的 lealone 的数据来看,48个线程平均每个线程的处理时间是15-20毫秒,而48个线程的总处理时间基本在50毫秒以上,所以线程切换浪费了将近2倍的时间,也就是40毫秒左右。
而其他3个数据库的平均处理时间本身就高,所以48个线程总处理时间跟平均处理时间只多了40毫秒左右,刚好就是 lealone 48个线程的总处理时间减去每个线程的平均处理时间,也就是线程切换的总开销是固定的40毫秒左右。收起
@zhh-4096
一直用 jdk 17 的 zgc 做压测,看数据不是很稳定,还不如 g1,结果换成 jdk 25的 zgc,压测出来的数据立马就漂亮稳定多了。每次开48个线程并发写9600条记录,连续跑了150次,lealone 平均每个线程的耗时基本维持在15-20毫秒左右。lealone 的数据确实最漂亮,h2、mysql、postgresql 基本在90-120毫秒。
豆包手机站在操作系统的层面自动操作app如果能大规模普及,意味着以后对 oltp 数据库的高并发处理能力会有更高要求,想一想数据库的读写请求若都是由 AI 快速且高频率发起,那是个怎样的画面?
Confluent 盘前大涨30%多,股价涨到30+美金,IBM 花110亿美金收购 Confluent,2021年上市,首发价是36美金,直到被收购依然回不到首发价。
@zhh-4096
Confluent、GitLab 都是被收购的命,美帝还有一大堆上市几年都无法盈利的软件公司,市值在100亿美金以内,说白了最终目的就是为了上市跑路。
SQLite、DuckDB 分别在嵌入式 oltp、olap 场景取得成功,所以做数据库不一定非得要大而全,也可以追求小而美,世界上的数据库有上千个,还是要多想想怎么做出差异化。lealone 的定位就是在 client-server 场景把 oltp 的高并发处理能力做到极致。
h2、mysql、postgresql 都是一个连接对应一个线程或进程,当在客户端启动48个线程用48个连接写数据时,这3个数据库也会启动48个线程或进程,所以在同一台机器上面安装数据库和客户端做压测,线程切换的开销会很大。lealone 内部的线程数是固定的,默认就是 cpu 核数,跟连接数无关,线程切换是客户端。
最佳的压测方案是把数据库和客户端分开部署到不同机器,用多台机器跑多个客户端,每个客户端开的线程数和连接数控制在 cpu 核数的1.5倍左右,这样做压测时客户端就不会干扰数据库了,每个客户端的线程切换开销也小。
@zhh-4096
h2、mysql、postgresql 都是一个连接对应一个线程或进程,当在客户端启动48个线程用48个连接写数据时,这3个数据库也会启动48个线程或进程,所以在同一台机器上面安装数据库和客户端做压测,线程切换的开销会很大。lealone 内部的线程数是固定的,默认就是 cpu 核数,跟连接数无关,线程切换是客户端。
赛力斯的核心工作就是跟华为搞问界,出了4款车,市值将近2200亿干到了国内车企老二的位置,车企的老大是比亚迪,老大跟老二这么一对比,如果不考虑华为,比亚迪跟老二赛力斯有啥可比较的,所以车企最终还是跟华为在对打。
用AI助手帮你干活,就意味着没人看app开屏广告了呀,很多app的后端服务故意不提供程序可调用的api,就是要人去点界面看广告。AI助手想推广,要么服务商提供api,要么AI助手自己模拟人类去操作,还有别的路吗?
当AI助手帮人类在网上干活时,每个AI助手本质上就是个爬虫,每个网站都害怕爬虫,因为可能造成对后端服务的冲击,所以AI助手想推广,一方面是服务提供商的广告收益可能受损,另一方面还得加强高并发处理能力,相当于允许所有爬虫访问服务了。
以前家里的兄弟在乡下办结婚酒席,要回去帮3天,在城里的酒店办酒也省事,就像今天早上工作几小时,12点到酒店吃午饭,一小时吃完回去继续工作,然后傍晚6点再过去吃晚饭,确实啥事不用干,结婚办酒席已经是件小事。
用 sqlite-jdbc-3.36.0.3 跑了一下测试,即便已经配置了 journal_mode=WAL、synchronous=NORMAL ,跑出的数据还是非常差,只支持单线程写,sqlite 比 h2 慢数倍。看了一下 h2 的官方文档,也是说 sqlite 很慢。sqlite 是靠什么活到现在?在我看来已经是个古董级的数据库了。
最近在测试 lealone、h2、sqlite 在嵌入式场景的读写性能,用多线程跑,lealone 秒杀 h2、sqlite,用单线程跑,lealone 还不如 h2,主要原因是 h2 的单线程可以直接从 jdbc 一路打通到存储引擎,而 lealone 需要把 sql 放到调度服务线程的队列,客户端线程再阻塞等待,出入队列和唤醒变成了负面影响。
使用 synchronous=NORMAL 之后 sqlite 是支持多线程写的,不过性能极其糟糕,比 lealone 慢了几十倍。
@zhh-4096
用 sqlite-jdbc-3.36.0.3 跑了一下测试,即便已经配置了 journal_mode=WAL、synchronous=NORMAL ,跑出的数据还是非常差,只支持单线程写,sqlite 比 h2 慢数倍。看了一下 h2 的官方文档,也是说 sqlite 很慢。sqlite 是靠什么活到现在?在我看来已经是个古董级的数据库了。
不管是嵌入式还是 client-server 模式,oltp 类的关系或文档数据库在查询方面都难做出差异化,因为 oltp 场景通常就是简单的查询统计需求,就算多线程查询要解决的并发问题也很简单,所以剩下的问题就是万一用户不小心用了一条扫表的 sql 查询了大量数据,如何不拖累其他读写事务?这需要抢占调度了。
具体研究哪个领域没有那么重要,关键是你有没有激情去寻找一些未解决或解决得不好并且有商业价值或有正面社会价值的问题,然后再投入时间想尽办法解决这些问题,中途一旦获得进展自然就会兴趣倍增,最后若能拿到不错的成果就会有成就感。
lealone 的 aote (事务引擎) + aose (存储引擎) 合起来实现的功能就等于 h2 数据库的 TransactionStore + MVStore,相当于 mysql 的 innodb。我压测了一下 lealone 和 h2 这两个组合的写性能,lealone 居然比 h2 快了40-50倍。innodb 无法单独测试,还挺好奇它的性能表现。
没想到 lealone 在嵌入式场景的性能这么猛,在嵌入式场景,可以通过3层 api 来使用 lealone:1. 直接使用 aose 的 api,这时就是一个不支持事务的 keyValue 存储引擎;2. 通过 aote 的 api 使用 aose,相当于在使用 innodb;3. 通过 jdbc api 用 sql 来读写 aose 中的数据,这时相当于在使用 sqlite。
@zhh-4096
lealone 的 aote (事务引擎) + aose (存储引擎) 合起来实现的功能就等于 h2 数据库的 TransactionStore + MVStore,相当于 mysql 的 innodb。我压测了一下 lealone 和 h2 这两个组合的写性能,lealone 居然比 h2 快了40-50倍。innodb 无法单独测试,还挺好奇它的性能表现。
之前一直没把嵌入式场景当成 lealone 的赛道,都忙着跟 mysql 和 postgresql 对打了,直到这两天测试 SQLite 非常吃惊写性能这么差的嵌入式数据库居然能这么流行,SQLite 在嵌入式这个赛道缺乏竞争对手躺平躺得太特么舒服了。
@zhh-4096
lealone 的 aote (事务引擎) + aose (存储引擎) 合起来实现的功能就等于 h2 数据库的 TransactionStore + MVStore,相当于 mysql 的 innodb。我压测了一下 lealone 和 h2 这两个组合的写性能,lealone 居然比 h2 快了40-50倍。innodb 无法单独测试,还挺好奇它的性能表现。
那位痛苦谈过3个月,只单纯吃过几次饭牵过几次手的女人,时隔很多年,今晚居然给我发了条短信问我过得好不好,居然还能记得我手机号,也许感情或婚姻出现问题了吧。我早已忘记她了,已经过了半小时我还没有回短信,也不知道说什么,面对这样的女人,你会怎么做?
跟我分开的女人,我都真心希望她们过得好,若多年后她们的婚姻出了问题才想起我的好,已经晚了,对她们来说是悲剧,我也很难再接受这样的人。
@zhh-4096
那位痛苦谈过3个月,只单纯吃过几次饭牵过几次手的女人,时隔很多年,今晚居然给我发了条短信问我过得好不好,居然还能记得我手机号,也许感情或婚姻出现问题了吧。我早已忘记她了,已经过了半小时我还没有回短信,也不知道说什么,面对这样的女人,你会怎么做?
如果你不知道如何消磨时间,结婚吧,结婚的最大好处就是有了老婆孩子之后多了几个让你操心的人,很大一部分时间不知不觉就消磨在家庭上了。否则不管男女,等你40+岁了若不能把一周排满工作,一旦空闲下来就会感到孤独,然后就可能想知道前任现在如何。我虽单身,还好我是搞技术研究的,特花时间。
参数用的是 journal_mode=WAL、synchronous=NORMAL,已经关掉实时 fsync 了,按默认参数压测还要慢10倍以上。synchronous=FULL 跑不了多线程,单线程跑一秒钟只能逐条写入几百条记录,synchronous=OFF 跟 synchronous=NORMA 都能跑多线程,性能差别不大。//@四顾剑oooO:sqlite默认是每次事务提交fsync//@zhh-4096:之前一直没把嵌入式场景当成 lealone 的赛道,都忙着跟 mysql 和 postgresql 对打了,直到这两天测试 SQLite 非常吃惊写性能这么差的嵌入式数据库居然能这么流行,SQLite 在嵌入式这个赛道缺乏竞争对手躺平躺得太特么舒服了。收起
@zhh-4096
lealone 的 aote (事务引擎) + aose (存储引擎) 合起来实现的功能就等于 h2 数据库的 TransactionStore + MVStore,相当于 mysql 的 innodb。我压测了一下 lealone 和 h2 这两个组合的写性能,lealone 居然比 h2 快了40-50倍。innodb 无法单独测试,还挺好奇它的性能表现。
像我这种虽然长得不帅,但是顾家、情绪稳定、有责任心、有上进心的男人,结婚几年的女人更懂这种男人的好。我现在的微信极少加女同学(目前只有一个),就是因为在QQ时代有不少女同学在好友列表里,她们结婚后反而跟我聊得更多,我惶恐,然后把QQ里的同学全清光也不用老QQ了,现在就剩一个工作QQ。
当你只想找个结婚对象时就很清楚什么样的人适合自己,男人到了40+,荷尔蒙下降,即便单身也不再像年轻时对女人那么躁动,若是再工作投入点,甚至对女人都难产生爱慕之情了,好看的女人也只不过头几天有点新鲜感,若聊起来无趣,连见面都懒得见。
我只有两个前女友,真有感情的是第二个,谈了3年。第一个说来话长,更像是个悲剧,她在桂林读大学,第一次认识她时是在2008-2009年,她通过QQ加我,那时我已经辞职了两年,正好宅在出租屋里专心研究技术,有个陌生女生能聊聊天就当解闷,所以就加了她这个陌生人。
网上聊了一年多,什么都没发生,连面都没见。2010年我去杭州工作,她去了深圳,从此有差不多两年都没有联系。然后突然有一天又跟她聊起了QQ,她说家里给她介绍了个相亲对象,还是华为的,谈了一年,老催她结婚,但是她当时才25岁左右,还不想结,所以逃婚了。(10几年后我才以外发现她在说谎,她当时其实已经结婚了,只是相处得不好)
2012年下半年我从杭州辞职回来桂林,中间又有好几年没什么联系,我甚至把她QQ都删了,直到2017年以后,她给我发短信,说她回来桂林的一家银行工作了,然后见了一面吃了餐饭,这时也谈不上喜欢,可能年纪30多岁了,就想多了解一下看看再说。
正式牵手交往以后,我就发现她这个人怪怪的,比如她跟我说敢不敢跟她结婚,她不想再花时间谈恋爱,当时她没有跟我说她结过婚,一个不到30岁的女人,怎么会有这种想法。
跟我谈恋爱的过程中,有一次她去深圳出差,我正跟她聊着天,然后突然说有人找她,我第6感就感觉不对,心想是不是他前男友找她。等她回到酒店,我问她是不是前男友,她说是,那是我第一次感到害怕,我只是叫她不要再跟前男友联系了。
她总说忙,约一次饭都不容易,快到年底时,我表妹回桂林,然后我问女友可以过来跟我们一起吃饭吗,她说她要跟同事吃饭,我当时就觉得她跟同事的饭局比男友的饭局还重要,工作重要我想想也就忍了。结果吃完饭我跟表妹逛街,问她在哪里,想叫她吃完饭过来一起认识一下,她说她在跟两个男同事逛商场,又把我拒了,我心想说有这个必要吗,宁愿跟男同事吃饭逛街都不愿跟你的男朋友,把我当成什么了。
这最后一根稻草也断了,我选择彻底分手。短短3个月的恋爱,我都没感受到什么甜蜜,就像在找一个女人对我施舍一点温存,显得自己很卑微。如果一个认识多年的人都没走到一起,千万不要因为年纪大了就将就,可以当普通朋友,但不要去谈恋爱。
准备重新优化一下 lealone 的 jdbc 驱动,因为在嵌入式场景,开单线程跑还打不过 h2,原先的 jdbc 驱动是为 client-server 运行模式设计的,调用 jdbc api 的应用线程需要把 sql 写到一个队列并进入等待状态,然后再由 jdbc 驱动内部的调度服务线程取出来执行,最后再换醒应用线程获取结果。
这样的设计思想在 client-server 模式下是可行的,因为网络开销才是瓶颈,出入队列唤醒线程这些步骤消耗的时间跟网络开销相比不值一提。若是嵌入式场景,因为不存在网络开销了,反而成为影响性能的原因之一。h2 在嵌入模式下,用单线程跑是可以从 jdbc 一直调用到存储引擎的,sql 不会加人队列,也不会唤醒线程,所以单线程跑出的性能比 lealone 好。
精神追求可大可小,取决于你的能力和野心,比如你的精神追求可以是在某个小技术反向上获得一点突破,如果还不满足,还可以去开拓一个新领域,你也可以去竞选美国总统解决美帝的内部问题,就像特朗普不缺钱了,就去竞选总统玩玩。我不需要太多钱,生活费够用了我就对钱没太多兴趣,就转去研究技术。
你觉得有趣的事在别人眼里也可能是极其无聊的,所以遵从自己的内心就好,没必要在乎别人的看法。就像我家人也只认为我只是个玩电脑的,对着电脑有什么意思,我从来不解释,没必要解释,说了也听不懂。我妈放着城里的好日子不过,又跑回乡下种菜养鸡了,这是她的乐趣,我也理解不了,就只能随她去。
早上我回她短信了,然后顺便还提了一件事,告诉她我在她QQ空间里意外发现她跟我交往的那段时间里其实已经结婚了,她没有否认,也没有承认。女人有些秘密是不能说的,就算被你发现了,也不想明确承认。这也是人类可怕的一面!
@zhh-4096
我只有两个前女友,真有感情的是第二个,谈了3年。第一个说来话长,更像是个悲剧,她在桂林读大学,第一次认识她时是在2008-2009年,她通过QQ加我,那时我已经辞职了两年,正好宅在出租屋里专心研究技术,有个陌生女生能聊聊天就当解闷,所以就加了她这个陌生人。
网上聊了一年多,什么都没发生,连面都没见。2010年我去杭州工作,她去了深圳,从此有差不多两年都没有联系。然后突然有一天又跟她聊起了QQ,她说家里给她介绍了个相亲对象,还是华为的,谈了一年,老催她结婚,但是她当时才25岁左右,还不想结,所以逃婚了。(10几年后我才以外发现她在说谎,她当时其实已经结婚了,只是相处得不好)
2012年下半年我从杭州辞职回来桂林,中间又有好几年没什么联系,我甚至把她QQ都删了,直到2017年以后,她给我发短信,说她回来桂林的一家银行工作了,然后见了一面吃了餐饭,这时也谈不上喜欢,可能年纪30多岁了,就想多了解一下看看再说。
正式牵手交往以后,我就发现她这个人怪怪的,比如她跟我说敢不敢跟她结婚,她不想再花时间谈恋爱,当时她没有跟我说她结过婚,一个不到30岁的女人,怎么会有这种想法。
跟我谈恋爱的过程中,有一次她去深圳出差,我正跟她聊着天,然后突然说有人找她,我第6感就感觉不对,心想是不是他前男友找她。等她回到酒店,我问她是不是前男友,她说是,那是我第一次感到害怕,我只是叫她不要再跟前男友联系了。
她总说忙,约一次饭都不容易,快到年底时,我表妹回桂林,然后我问女友可以过来跟我们一起吃饭吗,她说她要跟同事吃饭,我当时就觉得她跟同事的饭局比男友的饭局还重要,工作重要我想想也就忍了。结果吃完饭我跟表妹逛街,问她在哪里,想叫她吃完饭过来一起认识一下,她说她在跟两个男同事逛商场,又把我拒了,我心想说有这个必要吗,宁愿跟男同事吃饭逛街都不愿跟你的男朋友,把我当成什么了。
这最后一根稻草也断了,我选择彻底分手。短短3个月的恋爱,我都没感受到什么甜蜜,就像在找一个女人对我施舍一点温存,显得自己很卑微。如果一个认识多年的人都没走到一起,千万不要因为年纪大了就将就,可以当普通朋友,但不要去谈恋爱。
如果不是婚前检查,普通人居然无法查询别人是否已婚。这也要隐私保护啊,我不理解,查不到配偶的的信息完全能理解,一个人是否已婚都不知道,那得造成多少问题啊,也难怪花心的有钱已婚中年男人可以随便找小姑娘。我前任跟我吵架时说我已婚我就奇怪,她怎么不去查呢,原来查不到,我解释她也不信。
虽然她的家人反对,也还坚持了半年没有分,最后击垮我们的就是因为我帮我姐还房贷,跟她吵了两次,第一次很轻微,第二次就爆发了,她就认为我在帮前妻还房贷,如果不是前妻一个人怎么会帮姐姐还房贷,说我是结过婚的人,我怎么解释都没用,并且当时又是异地,恋人之间的信任感一旦崩塌,就难再缝合。
@zhh-4096
如果不是婚前检查,普通人居然无法查询别人是否已婚。这也要隐私保护啊,我不理解,查不到配偶的的信息完全能理解,一个人是否已婚都不知道,那得造成多少问题啊,也难怪花心的有钱已婚中年男人可以随便找小姑娘。我前任跟我吵架时说我已婚我就奇怪,她怎么不去查呢,原来查不到,我解释她也不信。
我没法接受结过婚的人,即便面对当初的白月光,时隔多年再次跟她联系上时,知道她过得不太好,哪怕对我依然保持好感,当我发现聊天的氛围变得微妙时我依然选择主动退出。还有其他几个女同学虽然没发展到恋爱的关系,但是婚后我也主动选择保持距离。今早这个前任说我冷血没有温度,你都有孩子了还联系前任,我能怎么办呢,我直接跟她说如果你是因为婚姻有了小摩擦,想找前任倾述,大可不必,搞不好我最后变成那个拆散别人一家人的罪魁祸首,还不如找闺蜜谈谈心,如果你婚姻幸福又怎会找前任呢?
我觉得自己还是个有温度的人,但是不会一直有温度,就像这件事就是把最后的温度给出去了。她越表现得冷淡我就越认为她过得好了,不需要我的关心。虽然她才28岁,我也不知道她结婚没有,但愿永远不要再收到她的短信。我现在最怕多年后收到前任或其他有过一段特殊情感的女生发来的短信,没有一次是好事。
@zhh-4096
有件事隔了几个月了我才想说,8月初我开始去广西、云南、贵州各市旅游,按高铁路线第一站是广西柳州,预订的第一家酒店到现场发现太偏不满意,换到另一个区又订了一家,到酒店门口看到道路施工乱糟糟,又换到第三家才满意。
结果意外发现第三家酒店附近的医院是我前任毕业前面试通过的医院。为了不打扰她,我选择周日去看看医院的工作环境怎么样。到了科室,看到走廊两边一大块医护人员的信息介绍,连最底层的人员都有介绍,里面居然没有前任的名字。我就担心前任是不是医院拒绝她或实习期没过,就用不常用的手机号给她发信息(常用的号被她拉黑了),她没有回复,以为也被她拉黑了。最后还专门申请了一个新的微信号通过加好友的方式在打招呼内容里问她是不是工作遇到了困难,有需要我可以帮助。然后过了几个小时,我刚从景区出来收到一条前任的短信,就冷冷地回复了一句话:请不要打扰我的生活。我也彻底死心了,回复了一句:我不会打扰你的,明早我就去下一个城市了。
她提分手后,还有一个学期才毕业,我转给她31000+块钱,我从来没有做出任何一件对不起她的事,她原本也是一个心地善良的人,我也不知道她身边的人对她说了什么,到了后期会跟我说一些突破我底线的话,比如我帮我姐还房贷,她认为怎么有这么好的人,她是独生子女没法理解,一听别人蛊惑就认为我在帮前期还房贷。我对家人对女朋友的付出都是不追求回报的,但我不希望我的好心被别人曲解。就好比分手两年后在医院发现情况不对,我给她发信息关心她怕她遇到困难,这是我不计较过去,真若有困难了我还愿意提供无偿帮助,最后还是被当成想打扰别人生活的人。
在体制内工作没有什么了不起的,我第一家工作的单位也是国企,还是我自己辞职的,后来去了阿里这种知名大厂工作,也是我自己辞职的,工作的单位不是身份贵贱的象征,别把自己太当回事。我直到现在都不知道她为什么变成这样,也许不是她的问题,只是她身边的人让她变成这样。我也不想去追究是谁的问题了,人各有命,我也彻底放下了。
无论是以什么方式分手,我都是那种一旦分手就会变成陌生人的绝情人,没有例外。我也不会接受自己的另一半跟前任还像朋友一样时常联系。见过太多那种分了还找前任约炮的人了,就算没有突破底线,我也无法安心另一半跟前任会做出什么其他事。有了新伴侣还找前任倾诉,听着就滑稽,直接复合不就好了。
像八九月份这样全职旅游很容易腻,明年还是背个笔记本电脑去,至少一半时间可以工作。桂林虽好,天天住在一个地方工作,连散步的路线都走了几千遍,早已没有了新鲜感,在每个城市工作游玩一段时间留下的回忆更多。结婚成家的事随缘了,遇到合适的人就加倍珍惜,没有也无所谓,我不是一个害怕孤独的人。
银行和医院是两个容易有花边新闻的工作场所,我的两个前任刚好在这两个地方工作。第一任的工作能力其实不错,30岁就当上了某行的支行行长,有房有车,我跟她交往时无房无车,就只有小十几万的存款,她家的家境也比我家好太多,家里还有当官的,人长得不能说很漂亮,但凹凸有致。她就直说金融业的人出轨男多,找我就是因为我这个技术男单纯,没有什么坏心思。
所以过去16年,每隔几年没联系了,她总会想要再续前缘,如今差不多奔四了哪怕都已经结婚生娃了,又想要回来找我。我只是跟她牵过手吃过饭而已,并没有其他的亲密行为,所以我搞不懂她为什么不能放下。这一次我说得更绝情,我说:这几年我谈了一个女朋友,她更好,更坦诚,甜蜜的时光更多,我跟你的恋情是痛苦的,我感受不到甜蜜。她最后只能表示祝福了,我也希望她能找到幸福,别再联系我了。
我认识的所有人里,婚姻、家庭幸福美满的不到1/3,大多数都是合伙过过平淡的日子。经济条件差的婚姻更容易破裂,哪怕是我姐弟如果经济困难时期我不帮一把,两个小家庭早就散了。中产家庭虽然不愁吃穿,但也会面对精神或肉体出轨的问题。这些都是我亲眼所见,甚至有好几次明显感觉自己要成第三者。
你知道吗,当我说那年我骑了这么远的路去看前任时,好多女生觉得这不浪漫,只是自我感动。结果今天我问前任怎么突然想起我了,她说她刚回老家,去逛了旁边的湖,想起来跟我一起逛过,触景生情。有些事就是这样,当下觉得无趣甚至嫌弃,多年后才发现错过了一个真心对你好的人,一切都晚了。
@zhh-4096
一个人骑行有时候真的就是冒险,我最惨的一次一天骑了170多公里,跨两省三市,从早上8点骑到晚上10点,中午都没吃饭,就带了点面包。就是截图里的线路,当时第一个准女朋友的老家就在富川县,所以我想去看看。第一次走这条线路,从灵川县大境瑶族乡到灌阳县洞井瑶族乡那一段全是烂山路,50多公里,前20多公里一直在爬坡,那是我目前唯一拖着单车走完的一段路,从资源到龙胜我都能做到不下单车(除了中途吃午饭或下车拍照)。
截图里从湖南江永掉头到富川80多公里全是夜路,在红色那一段遇到一群小混混,想拦我车,我没理他们,踩单车直接冲。
想起2017-2019这三年一个人玩自行车的经历,换现在的我肯定不会去了,真的疯了一样。最奇葩的一次是踩共享单车走那条环广西公路自行车世界循环赛桂林站的路线,第一次走,晚上从阳朔福利镇回桂林70多公里是摸黑回去的,只能照着路边的白线走。
我还连续花了一个月到14个城市踩共享单车,晒成了非洲人。所以我都不明白我那三年为何去干那些现在看起来很蠢的事。[笑cry][二哈]
我很想详细聊聊95/00后这帮年轻小姑娘的朋友圈那点事,本来打了不少字,涉及太多隐私,最后删了不少。
我跟第二任分开至少有一半是她朋友圈的原因,离谱到家,哪怕最后分了,见她还没毕业,我刚好从美股转了一笔钱回来,想给她几万生活费,一开始她说不要,第二天又突然说要,给我一张卡,我到银行一查,都不是她的卡,而是她身边爱烧野火的闺蜜之一的卡,这还不明显吗?又是她闺蜜在背后作妖,我很严肃的说你连收钱都听别人的吗,告诉她不给她的卡我就不转了,最后在设定的期限前才发她的卡号。之前转钱都是微信,删了微信转不了了,每次转的也不多。
有次前任说我给前妻还房贷时,我反问她你信身边的闺蜜胡编乱造都不信我吗?她说是,把我气炸了,直接关手机不想多说。还有另一个闺蜜私生活混乱,找前任男友约炮,实习期间跟师兄乱搞,这种品行的人还经常给她洗脑,说她找我这种老男人不值,劝她分手。关键是她这些闺蜜都是学医的,我一个都没见过,毫无交集。还有其他更严重更离谱的事不说了……
去年一个99年的漂亮小姑娘炒比亚迪被套了在微博找到我,一开始我以为是骗子,后来慢慢就聊起来了,跟我聊了无数日常琐事,若不是工作太拼年底我的腰出了问题走路不方便,我多半就去见她了,然后就会有第三个女朋友。后面几个月慢慢发现她的朋友圈也是让我惊恐,比如找工作加的人有的一看就知道是奔着包养去的,甚至还有老外,有抖音有小红书加的人,去了一家开网店的小公司当了两个月的平面模特还被摄影师性骚扰,去之前我就告诉她不靠谱。有太多刷新我三观的事了,我反反复复说了很多次叫她少结交那种来路不明的男性,她并没有听我的,反而说我有爹味pua她。4月初我说我受不了她的朋友圈了,然后终止了这段持续了一年的关系,最后互删了好友。
一个是97年的医学类的硕士研究生,一个是99年的职校毕业生,朋友圈都让我害怕,如今想找一个朋友圈干净且质量好的女人已经很难。
现在20多岁的年轻小姑娘很多都只适合花点钱谈个肤浅的恋爱玩玩而已。如果能够重来我还是更愿意在年轻时找我们80后这代人当老婆,至少我现在看到我的同学的伴侣很多都是彼此的初恋,80后是最后一批保守有传统观念的人。
接触的女人多了之后,我甚至怀疑我不适合恋爱结婚了,常常发现思想根本就不在一个层面。让我印象最深的一个例子是我的一个同学,她跟我表白过,快40了才把自己嫁出去,她对我说过一句话:我们中专生怎么能找本科生呢?那种低人一等的想法已经刻在骨子里,已经跳不出自己那个圈子,爬不上去了。
了解了 SQLite 的性能之后,在一些内存够用的嵌入式场景,我把 SQLite 也变成 lealone 的替换对象,我得改一下 lealone 的定位了:在 client-server 和嵌入场景把 oltp 的单线程或高并发处理能力做到极致。
@zhh-4096
SQLite、DuckDB 分别在嵌入式 oltp、olap 场景取得成功,所以做数据库不一定非得要大而全,也可以追求小而美,世界上的数据库有上千个,还是要多想想怎么做出差异化。lealone 的定位就是在 client-server 场景把 oltp 的高并发处理能力做到极致。
了解了 SQLite 的性能之后,在一些内存够用的嵌入式场景,我把 SQLite 也变成 lealone 的替换对象,我得改一下 lealone 的定位了:在 client-server 和嵌入场景把 oltp 的单线程或高并发处理能力做到极致。
@zhh-4096
SQLite、DuckDB 分别在嵌入式 oltp、olap 场景取得成功,所以做数据库不一定非得要大而全,也可以追求小而美,世界上的数据库有上千个,还是要多想想怎么做出差异化。lealone 的定位就是在 client-server 场景把 oltp 的高并发处理能力做到极致。
如何通过嵌入模式使用 Lealone 数据库?这里是文档:
http://t.cn/AXUc2bun网页链接 不得不说 JDBC 真是个经得起时间考验的好东西,我写了一堆性能测试代码,之前都是用来测 client-server 场景的,一时好奇想对比一下 sqlite 和 lealone 的性能,原来的测试代码只需要修改 jdbc url 就能立马切换到嵌入式场景。
压测下来最终发现:jdbc 客户端还是使用 bio(阻塞 io)更好,异步 api + nio 才是神仙搭配!
lealone 的 jdbc 客户端有4种组合:
1. bio + 同步 api ;
2. bio + 异步 api ;
3. nio + 同步 api ;
4. nio + 异步 api ;
其中1和2的性能一样;3最慢,比1和2慢20%以上;4最快,高并发时比1-3快10倍。
把 lealone 的 jdbc 客户端从默认的 nio 改成 bio 了,因为 jdbc 本身就是同步风格的 api,应用也习惯了同步风格,bio 配同步 api 最合适。如果应用想追求极致的性能,可以用 lealone 专有的 jdbc 异步 api,然后再搭配 nio,性能马上快10倍,缺点就是要适应异步 api 的编程风格。
做数据库压测是一件很专业的事,不应该交给新手去做,你不但得精确知道调用操作系统的 write、fsync 方法的时间消耗,甚至线程切换的时间也要算出来,哪怕 localhost 的传输时间也得知道,然后才是具体数据库的不同参数组合,你得知道这些参数的意义。如果是 jvm 还得调 gc 参数,还要预热。
oltp 数据库处理一条 sql 的时间只要小于5微秒,就没有必要再优化下去了。现在最昂贵的 rdma 的网络开销也很难做到5微秒以内,能做到20微秒以内就不错了。把4kb数据写到操作系统的内部缓存普遍超过10微秒,若是再 fsync 到硬盘,好的 ssd 也得上百微秒。所以数据库自身已经压根不是瓶颈了。
在 postgresql 14 用 postgres 用户试了一下 SET fsync = on 和 SET LOCAL fsync = on 都不起作用了,直接报错 ERROR: parameter "fsync" cannot be changed now。用 SET 语句理论上是可以实现,但多执行一条 SET 语句,对事务的整体执行时间有一定影响。无非是参数作用域的问题,在 session 级设置就不用每次事务执行一下 SET 语句。//@恰饭家族:不用参数的!事务内用一条sql语句开启fsync同步写盘!共用此连接的其它sql依然是异步写盘!所以是最科学的方案!//@zhh-4096:这个方式的确是个折中方案,实现也不难,只是需要在客户端创建连接时配置一个参数,因为 jdbc 没有设置 fsync 的 api,需要在一个特殊的 jdbc 连接中执行这种事务。//@恰饭家族:PG默认fsync,可以关掉,然后程序可以决定对哪一个事务按需开启fsync,如转账事务,更科学!
@zhh-4096
不管开不开启实时 fsync,都不会破坏数据库的完整性,只是对用户体验不同而已。开启实时 fsync 后,如果数据写硬盘失败了,用户可以马上获得错误通知,然后让用户决定是重试还是取消;不开启实时 fsync,用户收到成功消息后,若写硬盘失败了,再让用户重试确实体验不好,但是99.99%的场景体验更好。
AI 都能按不同数据库的方言写 sql 了,所以再兼容 mysql 或 postgresql 这种同一类别的数据库已经没有多大意义,用什么关系数据库,就让 AI 帮你写 sql 就行,切换也容易。在关系数据库的基础上兼容 mongodb 的 api 倒是能抢一点文档数据库的市场。后续要做的话,就花点时间完善 mongodb 插件。
我不想再花时间做 mysql 和 postgresql 的兼容插件了,时间宝贵,要去做更有意义更有挑战的事。真正获得巨大成功的数据库从来不是靠兼容别人,而是要有自己的特色和核心竞争力。
当并发的线程数远超 cpu 核数时,在每个线程中连续执行200条和2000条 sql 然后计算每条 sql 的执行时间,居然会有很大差异,执行200条 sql 时算出的平均时间更小。可能是受操作系统时间分片算法的影响,执行2000条 sql 时线程被切换的次数增多,所以总时间里把线程切换的时间算在内就变多了。
做压测时,在客户端开启的并发线程数远超 cpu 核数时,很多测试结果就变得奇奇怪怪了,线程切换的开销巨高。所以数据库内部的线程模型如果是一个连接对应一个线程或进程是非常糟糕的,mysql、postgresql、h2 都是这样的线程模型,连接数一多,数据库内部的线程切换开销变得越来越大。
@恰饭家族 postgresql 在事务中用 SET LOCAL synchronous_commit = on 开启实时 fsync 是可行的,在实现上如果支持多语句就能节省一次网络开销,也就是在 jdbc 中调用 execute 方法可以同时把 set 语句和 insert 语句传到数据库,甚至把 begin 和 commmit 也一起传过去,这样才是最高效的,但无论如何,执行 set 语句总会消耗一点时间。如果不想每次执行 set 语句,只能在 session 级设置,然后在客户端维护一个专门的 fsync jdbc 连接即可。
补充说明一下,lealone 的 jdbc 连接创建成本很低的,比在客户端单独执行一条 set 语句的成本还低,很适合在客户端单独维护一条 fsync 的专用连接,就算底层的 tcp 连接断了,也会自动重连,维护的专有 fsync jdbc 连接一直可用。
java 的虚拟线程还是挺让人失望的。
用虚拟线程跑了一下,虽然没有系统线程切换开销了,但是 ThreadPerTaskExecutor 在8核cpu跑16个虚拟线程的结果,还不如开16个Thread直接跑快,执行200条sql平均时间比虚拟线程快了一倍。
java 的虚拟线程还是没有优化好,我估计代码中运行到一些特殊的地方导致当前虚拟线程会阻塞系统线程从而变慢。比如在jdbc客户端执行sql的所有代码中一定会遇到synchronized的代码的,虚拟线程遇到synchronized就会阻塞系统线程,因为ThreadPerTaskExecutor内部只开了8个系统线程,如果其中之一被阻塞了,自然就影响跟它相关的所有虚拟线程。
@zhh-4096
当并发的线程数远超 cpu 核数时,在每个线程中连续执行200条和2000条 sql 然后计算每条 sql 的执行时间,居然会有很大差异,执行200条 sql 时算出的平均时间更小。可能是受操作系统时间分片算法的影响,执行2000条 sql 时线程被切换的次数增多,所以总时间里把线程切换的时间算在内就变多了。
不管是 java 的虚拟线程还是 go 的 goroutine 或者数据库内部的任务,想在用户态用少量系统线程调度好这些任务,那就必需确保执行任务的所有代码都不会阻塞系统线程。java 的虚拟线程在实际应用中大打折扣,就是因为现有的存量代码多是同步风格的,很容易导致系统线程被阻塞。而 lealone 之所以做得好,是因为数据库这个场景的代码是可控的,并且实现了全链路异步化,执行数据库内部的任务时,至少能保证高频率运行的代码不会阻塞系统线程。
lealone 的异步 jdbc api + nio 这个组合确实很炸裂,16个并发,随机单行更新,平均时间比 mysql 和 postgresql 快10几倍,insert、delete 也是差不多的测试数据。异步 jdbc api 没有流行真的太可惜了,那么炸裂的性能。
Vertx 有个 MySQL 的异步客户端,测试了一下,调了很多参数,只是比 MySQL 的 JDBC 客户端好一点,Vertx 的 EventLoopPoolSize 默认是 cpu 核数的两倍,如果用它的默认值更慢,我改成了8反而快一点。16个并发,Vertx 跟 Lealone 的异步 JDBC 客户端还是差好远。
把最常用的操作都压测了一遍,lealone 的性能已经打败了世界上最流行的3个开源关系数据库:mysql、postgresql、sqlite,还挺自豪的!
@zhh-4096
linux、git 虽然是群体智慧的产物,但依然被认为是 linus 的两个作品。一个人死后能留下一两个作品就已经很成功了,我做了20多年技术,也希望最后能留下一个作品,我给自己定的目标: 在 client-server 和 嵌入式 这两个场景,在所有开源 oltp 关系数据库中,性能要做到第一。这就是目前的技术追求。
lealone 的异步 jdbc api + nio 这套组合真的太炸裂了,跑select/insert/update/delete,全都比 mysql、postgresql 快10几倍!谁能告诉我 mysql、postgresql 有哪些靠谱一点的 java 异步客户端,我要挑战它,vertx 的异步 sql 客户端太挫了,打得不过瘾。
Oracle 今年靠炒作 AI 基础设施服务股价最高翻倍,结果3季度的营收增速只有个位数,股价快速腰斩,今年的股价涨幅只剩8%了。Snowflake 3季度给的指引也不如预期,股价也大跌。MongoDB 反而靠抢关系数据库的市场保持不错的营收,官方也明确说 AI 对营收还没有帮助。DB+AI 目前实用性还不高。
就像我过去反复强调的观点:AI 对 oltp 的用处不大,吹得最多的就是智能调参,还不如把数据库做得动态一点减少不必要的参数;AI 对 olap 或数据仓库/数据湖有没有用,更多取决于企业的数据治理能力,然后需要懂业务懂数据懂技术的人去把 AI 用好。
异步 jdbc api + nio 性能好于 同步 jdbc api + bio,我发现在这两者之间有个折中方案: 虚拟线程 + 同步 jdbc api + nio,也就是说应用在虚拟线程中调用同步 jdbc api,然后 jdbc 驱动使用 nio 跟后端的数据库通信。如果 jdbc 驱动依然使用 bio,搭配虚拟线程可能会更差。
vertx 的 mysql 和 postgresql 异步客户端都测了,没惊喜,两个客户端的事件调度器都是 vertx,所以核心差异小,只是数据库协议和配置参数的差别。//@奇峰cc :和vertx的async pg client比过吗?
@zhh-4096
lealone 的异步 jdbc api + nio 这套组合真的太炸裂了,跑select/insert/update/delete,全都比 mysql、postgresql 快10几倍!谁能告诉我 mysql、postgresql 有哪些靠谱一点的 java 异步客户端,我要挑战它,vertx 的异步 sql 客户端太挫了,打得不过瘾。
参考前一条微博和里面的评论,就是在 JDK 25 用 虚拟线程 + 同步 jdbc api + nio/bio 的组合 测4个数据库 。结论: 对于 mysql、postgresql、h2 这种基于 bio 实现的 JDBC 驱动,虚拟线程没啥用处,虚拟线程开多了反而更糟。//@放羊少年CXY:有测过JDK25的虚拟线程在此场景下的性能吗?//@zhh-4096:vertx 的 mysql 和 postgresql 异步客户端都测了,没惊喜,两个客户端的事件调度器都是 vertx,所以核心差异小,只是数据库协议和配置参数的差别。//@奇峰cc :和vertx的async pg client比过吗?
@zhh-4096
lealone 的异步 jdbc api + nio 这套组合真的太炸裂了,跑select/insert/update/delete,全都比 mysql、postgresql 快10几倍!谁能告诉我 mysql、postgresql 有哪些靠谱一点的 java 异步客户端,我要挑战它,vertx 的异步 sql 客户端太挫了,打得不过瘾。
这里有基于 vertx 异步 sql 客户端测试 mysql 和 postgresql 的代码,你可以看看哪里的参数还可以调,测试结果太差了,以至于我都不敢相信它的实现这么糟,我还是怀疑我哪个参数没调好。豆包说 vertx 的异步 sql 客户端是最好的!
理论上这个折中方案应该性能很好才对,但是虚拟线程的启动和切换也是有开销的,不如异步 jdbc api + nio 的组合。比如10万条 sql 用1000个虚拟线程跑,每个虚拟线程执行100条,因为每次执行 sql 调用同步 jdbc api 都要等待,就算不阻塞系统线程,也要切换虚拟线程,所以实际上发生了10万次切换操作。
@zhh-4096
异步 jdbc api + nio 性能好于 同步 jdbc api + bio,我发现在这两者之间有个折中方案: 虚拟线程 + 同步 jdbc api + nio,也就是说应用在虚拟线程中调用同步 jdbc api,然后 jdbc 驱动使用 nio 跟后端的数据库通信。如果 jdbc 驱动依然使用 bio,搭配虚拟线程可能会更差。
像 h2、mysql、postgresql 的 jdbc 驱动的代码中有不少加了 synchronized 的代码,jdk 的网络 bio 的代码也有,虚拟线程遇到 synchronized 不但不会发生虚拟线程切换,还会阻塞运行它的系统线程,并且 java 的调度器中运行的系统线程数不变,一旦被阻塞就不能跑其他虚拟线程,这就解释了为啥效果不好。
lealone 的调度器是为数据库的场景专门定制的,在调度器中执行的数据库任务依然是用异步风格,并没有用虚拟线程加同步风格的任务。在 lealone 的调度器中切换不同的数据库任务开销极低,无需保存和恢复任务的状态,任务的启动和出入队列都极其高效。所以我不会用虚拟线程改写 lealone 的内核代码的。
@zhh-4096
像 h2、mysql、postgresql 的 jdbc 驱动的代码中有不少加了 synchronized 的代码,jdk 的网络 bio 的代码也有,虚拟线程遇到 synchronized 不但不会发生虚拟线程切换,还会阻塞运行它的系统线程,并且 java 的调度器中运行的系统线程数不变,一旦被阻塞就不能跑其他虚拟线程,这就解释了为啥效果不好。
通过调试 java 虚拟线程调度器的代码,我发现虚拟线程有3个弱点:1. 虚拟线程出入调度器的队列有开销;2. 虚拟线程发生切换时也有开销;3. 虚拟线程遇到 synchronized 的代码会阻塞调度器中运行它的系统线程更是致命的。所以要想追求极致的低延迟和高吞吐,对系统进行全链路异步化改造才是唯一解!
当对一个系统进行全链路异步化改造完成后,我发现压根就不需要去想很复杂的并发算法了,哪怕遇到多个线程需要修改某个共享对象的问题,只需要通过一个简单的 CAS 操作就能完美实现,比如对记录加行锁就能用 CAS 实现,又比如对 btree page 执行插入和删除操作,也可以用 CAS 实现一个 page 锁。
@zhh-4096
通过调试 java 虚拟线程调度器的代码,我发现虚拟线程有3个弱点:1. 虚拟线程出入调度器的队列有开销;2. 虚拟线程发生切换时也有开销;3. 虚拟线程遇到 synchronized 的代码会阻塞调度器中运行它的系统线程更是致命的。所以要想追求极致的低延迟和高吞吐,对系统进行全链路异步化改造才是唯一解!
如何证明:一个全链路异步化的系统 + CAS 实现的轻量级锁,就是最完美的并发控制系统?这个证明留给网友去思考,当你想通了这个证明,任何需要处理并发问题的系统都能迎刃而解。
1. 全链路异步化,对于无状态共享的系统,能确保所有线程永远不会被阻塞,cpu 永远在高效运行;2. 对于有状态共享的系统,通过 CAS 对共享状态加轻量级锁,确保共享状态的访问具有唯一性,执行 CAS 操作失败的线程依然不会阻塞,依然能处理其他任务,最终 cpu 依然在被高效利用。这就是非形式化证明!
@zhh-4096
如何证明:一个全链路异步化的系统 + CAS 实现的轻量级锁,就是最完美的并发控制系统?这个证明留给网友去思考,当你想通了这个证明,任何需要处理并发问题的系统都能迎刃而解。
16个并发线程,每个线程逐条执行200条 update 语句,随机更新单行记录。这是 lealone 异步 jdbc 驱动和 vertx 的 mysql、postgresql 异步客户端的测试结果,10几倍的差距。
压测用例就是链接里面以 Async 开头的三个类: http://t.cn/AXUWIpk3
@zhh-4096
16个并发线程,每个线程逐条执行200条 update 语句,随机更新单行记录。这是 lealone 异步 jdbc 驱动和 vertx 的 mysql、postgresql 异步客户端的测试结果,10几倍的差距。
avg time 是平均每个线程逐条执行完200条update语句的时间,total time 是16个线程全部结束的时间(包括线程启动和线程切换的时间)。
@zhh-4096
16个并发线程,每个线程逐条执行200条 update 语句,随机更新单行记录。这是 lealone 异步 jdbc 驱动和 vertx 的 mysql、postgresql 异步客户端的测试结果,10几倍的差距。
用异步客户端逐条执行200条sql,理论上应该跟批量执行200条sql的性能接近,因为每次异步执行一条sql时不用等待它的结果返回就能继续发送下一条sql。如果性能跟批量执行差太远,那一定是客户端的实现有问题。
本来比亚迪减仓到只剩100股,昨天看到比亚迪跌到93.6又补仓了500股,还好今天早上涨了。今年长线持有比亚迪确实坑爹,12月最后一天若是全年涨幅收红就不错了。在A股玩中长线就是这样,如果不做波段,哪怕中间涨了40%,不卖出的话,到年底还是杨白劳。
下午再分析一下 vertx 的代码实现,几年前还是用过 vertx 做过项目的,但是当时还没有异步客户端。印象中 vertx 的性能没那么糟糕的,10几倍的差距实在太夸张了,我的预期就是 lealone 的异步 jdbc 驱动能比 vertx 快一倍就不错了,算上 lealone 本身就比 mysql 和 postgresql 快,总共快4倍了不起了。
@zhh-4096
16个并发线程,每个线程逐条执行200条 update 语句,随机更新单行记录。这是 lealone 异步 jdbc 驱动和 vertx 的 mysql、postgresql 异步客户端的测试结果,10几倍的差距。
lealone 在嵌入式场景执行一条 sql 的时间是2-3微秒;在 client-server 场景,按截图里的结果算,每个线程异步执行200条 sql 要2-3毫秒,平均执行一条 sql 要10-15微秒。localhost 的网络延迟是20+微秒,异步执行不用等待前一条 sql 的结果,相当于200条 sql 可以连续发送,所以平均下来也降低了延迟。
@zhh-4096
16个并发线程,每个线程逐条执行200条 update 语句,随机更新单行记录。这是 lealone 异步 jdbc 驱动和 vertx 的 mysql、postgresql 异步客户端的测试结果,10几倍的差距。
压测了最新的 mongodb-8.2.2,它的异步客户端只比同步客户端快一点点,insert 的性能跟 lealone 相比慢了20-30倍!mongodb 的写入性能其实还不如 mysql。
看不出什么问题,如果跑单行查询,vertx 的异步客户端比 mysql 的 jdbc 驱动快1.5倍,但单行查询依然比 lealone 的异步 jdbc 驱动慢8倍左右。//@zhh-4096:下午再分析一下 vertx 的代码实现,几年前还是用过 vertx 做过项目的,但是当时还没有异步客户端。印象中 vertx 的性能没那么糟糕的,10几倍的差距实在太夸张了,我的预期就是 lealone 的异步 jdbc 驱动能比 vertx 快一倍就不错了,算上 lealone 本身就比 mysql 和 postgresql 快,总共快4倍了不起了。
@zhh-4096
16个并发线程,每个线程逐条执行200条 update 语句,随机更新单行记录。这是 lealone 异步 jdbc 驱动和 vertx 的 mysql、postgresql 异步客户端的测试结果,10几倍的差距。
之前我用 mongodb-6.0.6,最新的 mongodb-8.2.2 的性能比6.0.6快一点,但是跟 lealone-8.0.0 比读写性能实在是差得太多了。世界排名前4的4个开源关系或文档数据库 mongodb、mysql、postgresql、sqlite,都被 lealone 打败了。哈哈哈,无敌是多么寂寞,证明了 lealone 的并发控制系统确实强得可怕。
@zhh-4096
压测了最新的 mongodb-8.2.2,它的异步客户端只比同步客户端快一点点,insert 的性能跟 lealone 相比慢了20-30倍!mongodb 的写入性能其实还不如 mysql。
lealone 从 jdbc 客户端到后端数据库的存储引擎,实现了全链路异步化,对记录和 btree page 这类共享对象的访问都使用 CAS 实现,如果应用在客户端使用异步 jdbc api 读写数据库,会获得极其炸裂的性能,甚至远超我最初的预期。任何 oltp 数据库想达到这样的并发处理能力,最后都会跟 lealone 一样。
@zhh-4096
如何证明:一个全链路异步化的系统 + CAS 实现的轻量级锁,就是最完美的并发控制系统?这个证明留给网友去思考,当你想通了这个证明,任何需要处理并发问题的系统都能迎刃而解。
初三学生,一个月四个周末补课,时间总计8-10小时,收费1200,说实话挺贵的,也就一天的工作时间。现在桂林的上班族月薪普遍3000-5000,补课老师这么收费,月薪得3万多了。孩子学习普通真的费钱,还好只是初三补课。
就算两个人月收入8000,家里两个孩子上大学了,每个人每个月生活费1500两个人就得3000,除非5年后我很有钱,否则我也出不起侄女们的生活费了。如果我买房还房贷一个月还3000,再加两个人生活费3000,就得6000,再加其他各种支出,一个月最少一万。一个月得收入两万才踏实,桂林这种收入的工作极少。
@zhh-4096
初三学生,一个月四个周末补课,时间总计8-10小时,收费1200,说实话挺贵的,也就一天的工作时间。现在桂林的上班族月薪普遍3000-5000,补课老师这么收费,月薪得3万多了。孩子学习普通真的费钱,还好只是初三补课。
三线城市机会少,待遇低,像我这种资历的人在桂林找工作就算有合适的,月薪估计也就一万多一点。也多亏这6年炒美股赚了点钱,不然我还得往一线或准一线城市跑。在三线城市创业更难,只适合做点外包项目,想做点有技术含量的事,难找到志同道合的人,就连去本地学校挑实习生都难挑到好苗子。
我现在管我侄女的学习,真的费钱费神。如果我要结婚生娃,自己的孩子不能继承我的智商不能像我小时候那么让父母省心,我根本就不想要养这样的孩子,我又不指望孩子给我养老,如果孩子普普通通,学习吃力,哪怕养到大学毕业,得把人愁死,太操心了。我宁愿把这些时间投入到工作上,至少还会有一点成就。
每次想起我们上屋的邻居,夫妻俩60岁的人了,还得操心两个30多岁儿子结婚的事,买车买房托人介绍对象,60了还得去打临时工。如果我的孩子也是这样,我都想不明白生孩子的意义是什么,辛苦一辈子早出晚归就是为了给孩子成家。这么对比,我妈就太幸福了,50+岁开始就不操心啥事了,就养几只鸡种点菜。
养娃和研发技术产品本质是一样的,都需要投入金钱、时间和精力,都想要做好,也希望最终能给自己一点回报。但也有一些区别,研发技术产品能做得多好,更多取决我的智商。孩子能变得有多优秀,先天因素占比更大,遗传到的优良基因多就好培养一些,否则就很吃力。
这6年炒美股有亏有赚,但总体下来平均每年有20-30万人民币的收入,在桂林这种三线城市生活够用了。还想要赚更多钱的话,只能靠做产品了,炒股的确定性高一点,做产品能不能赚钱反而很不确定,就算技术上有很大的领先优势,也不一定能拿到多高的市场份额,确实要讲天时地利人和。
http://t.cn/AXURQTXx 在 techempower 这个知名排行榜上面,更新数据那一项,vertx-postgres 排名第7,每秒更新数在58300,我这个测试是每秒65000左右,所以还是靠谱的,哪怕换成 Verticle 压测也是一样。
@zhh-4096
16个并发线程,每个线程逐条执行200条 update 语句,随机更新单行记录。这是 lealone 异步 jdbc 驱动和 vertx 的 mysql、postgresql 异步客户端的测试结果,10几倍的差距。
我分析了一下 vertx 的 mysql、postgresql 异步客户端为什么低效?
目前看到三个原因:
1. 在执行 sql 时每次都要去跟连接池打交道,lealone 的异步客户端是不需要的;
2. 应用的代码连续调用 SqlClient.query(sql).execute(),哪怕是异步的,vertx 也不知道去动态优化一下,每次都只发一条 sql 对应的数据包, lealone 会动态看看任务队列里还有没有更多任务要处理,如果有就先不发数据包,而是攒够了几个再通过 SocketChannel.write(ByteBuffer[] srcs) 去写;
3. vertx 的 eventloop-thread 在执行到应用代码的回调函数时,线程的堆栈深度达到了70+,而 lealone 的 eventloop-thread 堆栈深度才20+,说明它的调度器更复杂需要执行的代码更多。
当然,异步客户端只是影响整体性能的因素之一,份量也没那么重,关键还是看数据库自身的处理时间。
在 vertx 中可以让测试类实现 Verticle 接口,然后让 vertx 的 eventloop-thread 去直接跑 Verticle,这样做压测时就不用启动额外的线程了。lealone 其实也可以的,让测试类实现 AsyncTask 接口,然后让 lealone 的 ClientScheduler直接运行 AsyncTask,不用启动额外的线程,性能还能多好一些。
高并发场景,只要有连续不断的 sql 要处理,lealone 的异步客户端的性能已经很接近批量执行了。线上 oltp 场景要执行的 sql 是不同的,所以不太可能让应用自己攒够一批 sql 再通过 jdbc 的 executeBatch 去做,这时通过 lealone 的 executeUpdateAsync 和 executeQueryAsync 也能接近批量执行的性能。
在 localhost 创建一条 jdbc connection 的速度:
postgresql 要58毫秒(因为它创建进程);
mysql 要14毫秒;
h2 要2毫秒;
lealone 最快能做到60微秒(注意是微秒)。
单线程对连续的一万条记录做 count 和 sum 运算,这种功能没有任何技术难度,在我看来不同的 oltp 数据库对于这类功能也难做出差距,但 mysql 居然比 postgresql 和 lealone 慢2-3倍,难以置信!
年代久远了,若不是听一个网友说起数据库的主备部署,我都忘记这种古老的数据库部署模式了,如果是异步复制又不能保证数据不丢,若是同步复制性能又慢,异步复制时备库又不能读,否则可能读不到新数据。现在的主流已经是支持强一致性复制的多节点集群模式了,多个备库能分散读压力。
我用 mysql 的 jdbc 驱动通过 lealone-mysql 插件压测 lealone,跟用 lealone 的 jdbc 驱动的 bio 模式压测 lealone,性能一样的,所以 jdbc 驱动基于 bio 实现,很难做出差距,本身 bio 就很简单。用 vertx 的异步 mysql client 压测 lealone 只是比 bio 好一点点,只能说是 vertx 自身的问题。
县里有10几个乡镇,小时候只熟悉两个常去赶集的镇,一直以为这两个镇很穷,我也没读过高中,也很少关心高中的事。最后才发现除了县城外,居然只有这两个镇有自己的高中,有高中的镇至少证明人口数量和经济在县里是排名靠前的。过去几年自己踩单车去看了其他乡镇,确实比我们更小更穷。
数据库的数据备份这个概念我认为只是单机版特有的产物,如果从单机版切换到复制集群版,你根本就不用关心数据备份这种事了,复制集群本身就是数据的多份冗余,同时保证多个副本的强一致性,集群每个节点都能分担读流量。
postgresql 提供了一堆数据备份的方式,在我看来全都过时了,lealone 不会去学 postgresql 这种数据备份的功能的,lealone 的复制集群版才是最优解。lealone 的单机版就只提供了一条简单的 backup 命令,能做到在线增量物理备份就够了,我也没打算把 backup 命令做得多复杂,毫无必要了。
@zhh-4096
数据库的数据备份这个概念我认为只是单机版特有的产物,如果从单机版切换到复制集群版,你根本就不用关心数据备份这种事了,复制集群本身就是数据的多份冗余,同时保证多个副本的强一致性,集群每个节点都能分担读流量。
按 int/long 类型的主键查询、按 varchar 类型的索引字段查询,我以为大家都是基于 btree 来实现,如果不用异步客户端,性能没啥差别才对,结果16个并发查询 lealone 8.0 依然比 mysql 和 postgresql 快80%-150%,若是用异步客户端那差距更大了。说明好的并发控制系统不只是对并发写有用,对读也有用。
Oracle 收购 MySQL 之后这么多年在干嘛?安装了最新的 MySQL 8.4.7 和 9.5.0,测了这两个查询场景,性能居然还不如我那个老掉牙的5.7,看来我只能跟 MySQL 5.7 对比了,MySQL 这么多年都止步不前,是到淘汰的时候了。[笑cry]
@zhh-4096
按 int/long 类型的主键查询、按 varchar 类型的索引字段查询,我以为大家都是基于 btree 来实现,如果不用异步客户端,性能没啥差别才对,结果16个并发查询 lealone 8.0 依然比 mysql 和 postgresql 快80%-150%,若是用异步客户端那差距更大了。说明好的并发控制系统不只是对并发写有用,对读也有用。
把 oltp 数据库常用的功能都压测了一遍,哪怕是创建连接的速度都压测了,mysql 从5.7到9.5版本的性能没有一个场景胜过 lealone 8.0,哪怕打平的场景都没有,万万没想到 mysql 已经这么差劲了!
在抖音上刷到湘超半决赛,隔壁的永州居然打败长沙进了决赛,两个进球还挺漂亮。永州就是个毫无存在感的地方,这种地级市足球队踢球的水平和观赏性怎么比国家队还高,说明足球圈还是人才济济的。我不是足球迷,也搞不懂国家队足球运动员的选拔标准。
广西怎么没有桂超?都忙着坎甘蔗摘沙糖桔了。贵州的村超很火,其实在我小时候桂林的村超就火过了,好多农村都新建了篮球场,村与村之间晚上经常打比赛,看的人围了里三层外三层。现在再去农村,篮球场早就荒废了。哪怕是春节,娱乐活动变成打牌赌钱或刷抖音。
为啥 lealone 更新单行记录的性能这么好?只需要遍历一次 btree,拿到记录后通过 CAS 加行锁,替换新值,然后标记记录所在的 btree page 为脏页即可。而 h2 至少要遍历3次 btree,如果并发高了,还可能需要对 btree 加全局锁。sqlite 的实现我不是很清楚,所有类型的并发写都很弱,insert 更慢。
@zhh-4096
继续优化 lealone 8.0 在嵌入式场景下的性能,16个并发,按主键随机更新单行记录,lealone 比 h2 快8倍,比 sqlite 快20倍。
问了一下豆包: sqlite 如何实现单行记录的更新 http://t.cn/AX4hoQtk 它说 sqlite 不支持行锁,如果真的不支持行锁,那就不可能快了。
@zhh-4096
继续优化 lealone 8.0 在嵌入式场景下的性能,16个并发,按主键随机更新单行记录,lealone 比 h2 快8倍,比 sqlite 快20倍。
嵌入式场景:
lealone 的主要竞争对手是 h2 和 sqlite;
client-server 场景:
lealone 的主要竞争对手是 mysql 和 postgresql。
所以我只重点压测 h2、sqlite、mysql 和 postgresql。
不管是单线程还是多线程,sqlite 的各类查询操作的性能不算很差,lealone 只比 sqlite 快2-3倍;sqlite 的 insert/update/delete 这类写操作的性能确实差很多,lealone 基本比 sqlite 快10-40倍。sqlite 的优势是用 c 语言实现,确实比 java 更适合内存有限的嵌入式场景。
通过跟5个主流开源数据库的性能对比,我现在可以说 lealone 对数据库领域的最大贡献是:验证了“全局调度器 + 全链路异步化 + CAS 实现的轻量级锁” 这套模型是有效的,能把数据库的并发处理能力提升到新的高度。希望未来能有更多数据库也采用类似的模型。
测试了全部8种纯内存读写场景: 单线程或多线程顺序或随机读写,jdk 的 ConcurrentSkipListMap 只有多线程顺序读写这两种场景比 leaone 实现的 btree 略快一点点,其他6种场景都远不如 leaone 的 btree,不管是单线程或多线程,ConcurrentSkipListMap 的随机读写性能都比较差,优势只有多线程顺序读写。
http://t.cn/AX4q2hUc 里面有 testWrite 和 testRead,每个测试4种场景,我把 h2、lealone 实现的 btree 跟 jdk 的 ConcurrentSkipListMap 都测完了,不用任何配置,可以直接跑,h2 在8种场景全面落后,基础数据量是200万个 keyValue。
@zhh-4096
测试了全部8种纯内存读写场景: 单线程或多线程顺序或随机读写,jdk 的 ConcurrentSkipListMap 只有多线程顺序读写这两种场景比 leaone 实现的 btree 略快一点点,其他6种场景都远不如 leaone 的 btree,不管是单线程或多线程,ConcurrentSkipListMap 的随机读写性能都比较差,优势只有多线程顺序读写。
今天做了一个智能化的改进,用户想选用哪种组合不需要任何配置了,lealone 的 jdbc 客户端会根据调用的 jdbc api 自动选择最优的组合,比如在自动提交模式下哪怕是同一个 Statement 对象,先调用 executeUpdate(sql) 就会自动用 bio,然后调用 executeUpdateAsync(sql) 又自动切换到 nio。
@zhh-4096
压测下来最终发现:jdbc 客户端还是使用 bio(阻塞 io)更好,异步 api + nio 才是神仙搭配!
lealone 的 jdbc 客户端有4种组合:
1. bio + 同步 api ;
2. bio + 异步 api ;
3. nio + 同步 api ;
4. nio + 异步 api ;
其中1和2的性能一样;3最慢,比1和2慢20%以上;4最快,高并发时比1-3快10倍。
把 lealone 的 jdbc 客户端从默认的 nio 改成 bio 了,因为 jdbc 本身就是同步风格的 api,应用也习惯了同步风格,bio 配同步 api 最合适。如果应用想追求极致的性能,可以用 lealone 专有的 jdbc 异步 api,然后再搭配 nio,性能马上快10倍,缺点就是要适应异步 api 的编程风格。
今天做了一个智能化的改进,用户想选用哪种组合不需要任何配置了,lealone 的 jdbc 客户端会根据调用的 jdbc api 自动选择最优的组合,比如在自动提交模式下哪怕是同一个 Statement 对象,先调用 executeUpdate(sql) 就会自动用 bio,然后调用 executeUpdateAsync(sql) 又自动切换到 nio。
@zhh-4096
压测下来最终发现:jdbc 客户端还是使用 bio(阻塞 io)更好,异步 api + nio 才是神仙搭配!
lealone 的 jdbc 客户端有4种组合:
1. bio + 同步 api ;
2. bio + 异步 api ;
3. nio + 同步 api ;
4. nio + 异步 api ;
其中1和2的性能一样;3最慢,比1和2慢20%以上;4最快,高并发时比1-3快10倍。
把 lealone 的 jdbc 客户端从默认的 nio 改成 bio 了,因为 jdbc 本身就是同步风格的 api,应用也习惯了同步风格,bio 配同步 api 最合适。如果应用想追求极致的性能,可以用 lealone 专有的 jdbc 异步 api,然后再搭配 nio,性能马上快10倍,缺点就是要适应异步 api 的编程风格。
java 的 nio 也支持阻塞读写的,我之前一直使用老的 jdk bio 库实现阻塞读写,然后我调试这些 jdk bio 库的实现,底层也是调用 nio 的 poll,所以我直接在 nio 之上把阻塞读写功能实现了,性能跟基于老的 jdk bio 库实现的代码一样,最后我把老的 bio 代码全删了,lealone 的 jar 包又小了几 k。
jdbc 或许可以考虑在新版本的规范中引入异步 api 了,需要异步的 api 也就20个左右,lealone 的 jdbc 实现凡是需要异步的 api 都加了 Async 后缀,只要把返回的 Connection 或 Statement 对象强制转换成 JdbcConnection 或 Jdbc Statement 就能用这些异步 api,同步和异步 api 是可以共存的。
我经常说:与其让 AI 给数据库调参,不如把数据库做得更灵活更动态一点,减少不必要的参数。jdbc 客户端又是一例,当数据库自身能够根据用户调用的 jdbc api 动态选择最快的 io 类型时就达到了完美的状态,都不需要用户调参了,自然用不到 AI。
一个月补课10-12小时花费1200,我一天工作15小时都赚不了这么多,最后试两周(累计3个月),如果效果还一般,我就准备自己出手去辅导侄女了。初中的英语和数学有啥难的,我以前读初中时不是考满分,就是差不多考满分,这两门课都不行,说明文理科都烂。计算机工作要做好,英语和数学是最基础的东西了。
2006年我在复习考研,就花了一点时间就差不多把新概念英语前3册背完了,只是觉得考研太无趣,不是考验背诵能力就是考验刷题能力,不符合我的追求,最后我跑去独自研究程序语言和编译器理论了。计算机软件和算法其实更考验逻辑和推理,我搞了10几年数据库,也从没觉得微积分有用过。
通过切换不同的session来实现 bio 或 nio 太复杂了,晚上换了一种思路,通过动态调用 java.nio.channels.spi.AbstractSelectableChannel.configureBlocking(boolean) 来实现居然可行,只要从 bio 转到 nio 时,让 NioEventLoop 线程轮循即可。//@zhh-4096:今天做了一个智能化的改进,用户想选用哪种组合不需要任何配置了,lealone 的 jdbc 客户端会根据调用的 jdbc api 自动选择最优的组合,比如在自动提交模式下哪怕是同一个 Statement 对象,先调用 executeUpdate(sql) 就会自动用 bio,然后调用 executeUpdateAsync(sql) 又自动切换到 nio。收起
@zhh-4096
压测下来最终发现:jdbc 客户端还是使用 bio(阻塞 io)更好,异步 api + nio 才是神仙搭配!
lealone 的 jdbc 客户端有4种组合:
1. bio + 同步 api ;
2. bio + 异步 api ;
3. nio + 同步 api ;
4. nio + 异步 api ;
其中1和2的性能一样;3最慢,比1和2慢20%以上;4最快,高并发时比1-3快10倍。
把 lealone 的 jdbc 客户端从默认的 nio 改成 bio 了,因为 jdbc 本身就是同步风格的 api,应用也习惯了同步风格,bio 配同步 api 最合适。如果应用想追求极致的性能,可以用 lealone 专有的 jdbc 异步 api,然后再搭配 nio,性能马上快10倍,缺点就是要适应异步 api 的编程风格。
终于把客户端的 io 问题和 jdbc 的异步或同步 api 问题完美解决了:
数据库一般部署在内网,bio +专有 tcp 连接解决了80%的场景需求(中低并发低延迟),另外15%的需求通过 nio +专有 tcp 连接解决(高并发但 jdbc 连接数有限制),最后5%的需求通过 nio +共享 tcp 连接解决(高并发且 jdbc 连接数无限制)。
lealone 的默认配置是 bio + 专有 tcp 连接,当应用调用异步 jdbc api 时自动切换到 nio +专有 tcp 连接,当专有 tcp 连接数超过一个阈值时,通常是客户端 cpu 核数的数倍,新创建的 tcp 连接自动使用共享模式,此时在这条共享连接上调用同步或异步 jdbc api 都会委托给客户端调度器线程执行,不再是应用的线程。
为自己的创新能力骄傲,连 jdbc 客户端都能创新,对比 h2、postgresql、mysql 和 lealone 的 jdbc 客户端已经有了重大区别,前三者依然是最传统的 bio +同步 jdbc api,而 lealone 还额外增加了 nio + 异步 jdbc api,并且把两种模式智能化整合,完美支持高并发和低延迟以及海量 jdbc 连接。
java nio 有个诡异的行为,如果先通过AbstractSelectableChannel.configureBlocking(boolean) 配置成阻塞模式,连接成功后,再配置成非阻塞模式,并注册 SelectionKey.OP_READ,即便后端有发回数据,客户端有时能触发 read 事件,有时又不能。如果先配置成非阻塞模式,之后转成阻塞再转非阻塞都正常。
而且明明白白注册好读操作了,同一个事件循环线程刚写完数据,并且已经确认后端数据库成功写回了数据,让这个事件循环线程去读也读不到,返回尝试读多次都读不到。
@zhh-4096
java nio 有个诡异的行为,如果先通过AbstractSelectableChannel.configureBlocking(boolean) 配置成阻塞模式,连接成功后,再配置成非阻塞模式,并注册 SelectionKey.OP_READ,即便后端有发回数据,客户端有时能触发 read 事件,有时又不能。如果先配置成非阻塞模式,之后转成阻塞再转非阻塞都正常。
明白了,时隔多年又踩了一次巨坑,注册 OP_READ 事件和轮询事件必须是同一个线程才不会错乱,我注册事件的线程是应用线程,轮询是客户端调度线程。几年前我在实现多个全局调度器轮流接收新连接时,注册和轮询 ACCEPT 事件也是两个不同线程,也排查了好久,我都把踩坑的注释删了,又踩一次。[摊手]
@zhh-4096
java nio 有个诡异的行为,如果先通过AbstractSelectableChannel.configureBlocking(boolean) 配置成阻塞模式,连接成功后,再配置成非阻塞模式,并注册 SelectionKey.OP_READ,即便后端有发回数据,客户端有时能触发 read 事件,有时又不能。如果先配置成非阻塞模式,之后转成阻塞再转非阻塞都正常。
造车复杂,还是造数据库复杂?车和数据库都有一堆零部件组成,现在车企18-24个月就能造出一款新车,主要因为汽车产业链成熟,即便一辆车有上万的零部件,但车企并不会每个零部件都自己造,就是直接用,所以才能在那么短的时间内做出新车并量产。数据库的零部件难通用,24个月难完成,所以数据库更难。
小米花了3年造出第一款车就量产大卖,雷军最早也是撸代码的,哪怕雷军是卷王,汽车和数据库都是很卷的行业,你现在让他花5年造一款新的通用型数据库,他有底气能大卖吗(哪怕只是在国内大卖)?小米花了那么多资源半路参与开源的 hbase,也没见 hbase 多流行,况且 hbase 的难度比通用型数据库低得多。
@zhh-4096
造车复杂,还是造数据库复杂?车和数据库都有一堆零部件组成,现在车企18-24个月就能造出一款新车,主要因为汽车产业链成熟,即便一辆车有上万的零部件,但车企并不会每个零部件都自己造,就是直接用,所以才能在那么短的时间内做出新车并量产。数据库的零部件难通用,24个月难完成,所以数据库更难。
假设 cpu 核数是 n,总任务数 > n,如果保证运行这些任务的线程不会阻塞,那么只需要启动 n 个线程就够了。压测的结果也验证了这一点,如果开启的线程数 > n,不但没有效果,反而因为线程切换有负面影响。基于这个结果,lealone 的 ClientScheduler 线程和 GlobalScheduler 线程默认都是 cpu 核数。
其他数据库做不到这样,那是它们没有实现全链路异步化,这就是 lealone 的高明之处啊,也是 lealone 的核心竞争力。ClientScheduler 线程只处理非阻塞网络 IO,而 GlobalScheduler 线程不会因为锁而被阻塞,甚至不会一直陷在慢查询里面。能处理的并发请求数跟调度线程的数量无关,如果把并发请求数或连接数跟线程数绑定,那才是最大的错误。java 的虚拟线程已经详细压测过,哪怕用在 jdbc 客户端的场景都没有多少价值。 //@犽你怎么了:线程数等于 CPU 核心数的结论成立前提是任务不发生阻塞,这在数据库负载中通常不成立。数据库查询普遍受 IO、锁和网络延迟影响,CPU 利用率并非主要瓶颈。因此更合理的设计是保持有限的内核线程数,同时通过用户态线程、异步 IO 或虚线程来承载高并发请求,而不是简单限制并发线程数量。
@zhh-4096
假设 cpu 核数是 n,总任务数 > n,如果保证运行这些任务的线程不会阻塞,那么只需要启动 n 个线程就够了。压测的结果也验证了这一点,如果开启的线程数 > n,不但没有效果,反而因为线程切换有负面影响。基于这个结果,lealone 的 ClientScheduler 线程和 GlobalScheduler 线程默认都是 cpu 核数。
不搞数据库的人我估计都搞不明白数据库的并发跟操作系统的并发不是一回事,当谈论操作系统的并发处理能力时,是在说操作系统能让 cpu 运行多少个线程,所以一听到线程数少就认为在限制并发处理能力。
而数据库的并发是指数据库处理事务的能力,哪怕在自动提交模式下执行单条 sql 语句,对数据库来说也是一个事务,只不过这个事务在 sql 语句执行完就结束。
所以在数据库中限制线程数,并不是限制并发的事务数,如果数据库内部在执行事务时有能力保证不阻塞执行事务的当前线程,那么在避免线程切换时只用很少的线程就能处理大量并发事务了,这时数据库的并发处理能力才是最优的。
@zhh-4096
假设 cpu 核数是 n,总任务数 > n,如果保证运行这些任务的线程不会阻塞,那么只需要启动 n 个线程就够了。压测的结果也验证了这一点,如果开启的线程数 > n,不但没有效果,反而因为线程切换有负面影响。基于这个结果,lealone 的 ClientScheduler 线程和 GlobalScheduler 线程默认都是 cpu 核数。
lealone 的设计和实现文档我不想从头亲自写了,我用 qoder 生成了: 写得很不错。8.0 在使用上更简单更智能了,跟6.0相比就新增了两个静态的开关参数,没有新增 sql。8.0 主要是性能、内存占用、易用性方面的大量改进。/ //@水行潺潺:8.0稳定后,后面能不能把下面提上日程:让大家了解lealone,用好lealone。作为后面的阶段目标?毕竟好酒巷深也要吆喝。
@zhh-4096
造车复杂,还是造数据库复杂?车和数据库都有一堆零部件组成,现在车企18-24个月就能造出一款新车,主要因为汽车产业链成熟,即便一辆车有上万的零部件,但车企并不会每个零部件都自己造,就是直接用,所以才能在那么短的时间内做出新车并量产。数据库的零部件难通用,24个月难完成,所以数据库更难。
对于 oltp 关系数据库来说,我一直认为按主键或按索引字段查询、做 count、sum 之类的聚合运算,这种最基本的常用功能技术难度低,数据库能发挥的空间有限,做不出差异,结果 lealone 8.0 依然比 mysql 5.7/8.x/9.x 全都快1.5-2.5倍,只能说 mysql 烂而已,并不是 lealone 这方面优秀,我都没做优化。
注意我这里说的是快1.5-2.5倍,也就是说 lealone 这些场景的性能是 mysql 的2.5-3.5倍。有的厂商拿 mysql 对比时,用后一种数字,这是种数字营销把戏。比如 mysql 要900毫秒,你的数据库要600毫秒,其实只是比 mysql 快了50%,但是宣传时可以说你的数据性能是 mysql 的1.5倍,多好听的数字。
@zhh-4096
对于 oltp 关系数据库来说,我一直认为按主键或按索引字段查询、做 count、sum 之类的聚合运算,这种最基本的常用功能技术难度低,数据库能发挥的空间有限,做不出差异,结果 lealone 8.0 依然比 mysql 5.7/8.x/9.x 全都快1.5-2.5倍,只能说 mysql 烂而已,并不是 lealone 这方面优秀,我都没做优化。
这还只是用同步 api 加 bio 压测的结果,如果拿 lealone 的异步 api 加 nio 跑出的结果跟 mysql 比,那 mysql 的性能真的没法看了。mysql 的官方 jdbc 客户端不支持异步 api,所以不能这么跟它比,对它不公平。
@zhh-4096
对于 oltp 关系数据库来说,我一直认为按主键或按索引字段查询、做 count、sum 之类的聚合运算,这种最基本的常用功能技术难度低,数据库能发挥的空间有限,做不出差异,结果 lealone 8.0 依然比 mysql 5.7/8.x/9.x 全都快1.5-2.5倍,只能说 mysql 烂而已,并不是 lealone 这方面优秀,我都没做优化。
一个不结婚的人,如果把时间投入到一件事情上,很难做不好的。成了家有孩子要养,就不可能把时间全投入到工作,我现在哪怕只是管管我侄女学习的事情,就得把时间分出一小部分出来。真若结婚养自己亲生的,哪可能一个月不休每天工作15小时。历史上不少顶级科学家是单身狗或不管家事。
对待家人不能只讲理性,就拿我侄女来说,在我眼中就是学渣,我花钱花时间操心她的学习,可能大概率工作了也是月薪三五千的料,又不是什么好苗子,为啥还浪费我的时间,理性来说完全不值得。毕竟是家人,总得管过帮过才安心,这就是亲情。
天啊,太刺激了!!!刚蹲厕所时,我居然意外找到了一种消除所有异步 jdbc api 的方法,只需要使用最原始的同步 jdbc api 就能达到异步 jdbc api 的性能。有点像虚拟线程的用法,只需要把所有使用同步 jdbc api 的代码放到一个闭包内运行,只不过运行这个闭包的线程是 lealone 的 client scheduler。
跑了一下,虽然方法可行,但是因为是 同步 jdbc api ,虽然 client scheduler 执行同步 jdbc api 不会被阻塞,但它也要等收到后端数据库返回的结果才能执行下一条 sql ,所以还是没法像 异步 jdbc api 那么快,异步 jdbc api 不用等结果返回也能继续发送下一条 sql 给后端数据库。
@zhh-4096
天啊,太刺激了!!!刚蹲厕所时,我居然意外找到了一种消除所有异步 jdbc api 的方法,只需要使用最原始的同步 jdbc api 就能达到异步 jdbc api 的性能。有点像虚拟线程的用法,只需要把所有使用同步 jdbc api 的代码放到一个闭包内运行,只不过运行这个闭包的线程是 lealone 的 client scheduler。
继续探索,还是有提升,如果1万条 sql 切成1000个任务,每个任务同步跑10条,让 client scheduler 线程跑明显比用1000个线程跑要快一倍。
@zhh-4096
天啊,太刺激了!!!刚蹲厕所时,我居然意外找到了一种消除所有异步 jdbc api 的方法,只需要使用最原始的同步 jdbc api 就能达到异步 jdbc api 的性能。有点像虚拟线程的用法,只需要把所有使用同步 jdbc api 的代码放到一个闭包内运行,只不过运行这个闭包的线程是 lealone 的 client scheduler。
java 的虚拟线程用在 jdbc 客户端太糟糕了,cpu 核数是8,把一万条 sql 平分给8/16/32/80/512 个线程写数据库,居然还比同样数量的虚拟线程快,在 lealone、h2、mysql、postgresql 的 jdbc 客户端上测试都是一样的结果:虚拟线程的版本慢。
用同步 api 写的代码比异步 api 更省心更容易维护,缺点就是性能在高并发场景差不少,java 虚拟线程的初衷就是让同步 api 写的代码在性能上不输异步 api,结果等了那么多年,java 虚拟线程并没有实现目标。
如果 java 提供一种方法,可以把当然线程的堆栈的某一部分栈桢弹出,然后执行新的方法,再把原来的栈桢放进去,我能让调用同步 api 的性能无限接近异步 api。现在执行同步 api 时如果等待的结果没有返回,只能在当前栈桢的位置继续执行其他任务,最终是有限制的,否则无限执行下去会堆栈溢出。
我跟豆包讨论了这个问题,它说一万条 sql 太少了,发挥不了虚拟线程的优势,要用100万条 sql 变成10万个虚拟线程。我说如果我用100个平台线程处理100万条 sql 比10万个虚拟线程还快,那用那么多虚拟线程(每10条 sql 当成一个任务提交)又有什么意义?
@zhh-4096
java 的虚拟线程用在 jdbc 客户端太糟糕了,cpu 核数是8,把一万条 sql 平分给8/16/32/80/512 个线程写数据库,居然还比同样数量的虚拟线程快,在 lealone、h2、mysql、postgresql 的 jdbc 客户端上测试都是一样的结果:虚拟线程的版本慢。
很多数据库无法支持100万条连接,即便应用服务器收到100万条并发 sql,它也无法创建100万条连接,只能从包含上千条连接的连接池里取。如果做不到批量执行,我只要开100个平台线程逐条处理这100万条 sql 即可。反而用虚拟线程不好做,只能把执行每条 sql 的方法当成一个虚拟线程任务提交,实测更慢。
java 的虚拟线程调度器内部使用的平台线程数实际就是 cpu 核数,比如我的 cpu 核数是8,这个场景实际上就是在比较:1. 把100万条 sql 当成虚拟线程任务放到 java 的8个调度器平台线程处理;2. 把100万条 sql 放到我启动的100个平台线程的队列,然后操作系统调度这100个平台线程执行。1和2哪个快?
@zhh-4096
很多数据库无法支持100万条连接,即便应用服务器收到100万条并发 sql,它也无法创建100万条连接,只能从包含上千条连接的连接池里取。如果做不到批量执行,我只要开100个平台线程逐条处理这100万条 sql 即可。反而用虚拟线程不好做,只能把执行每条 sql 的方法当成一个虚拟线程任务提交,实测更慢。
太搞笑了,别说100万条 sql 了,哪怕只有8万条 sql,我手动用8个平台线程每个负责1万条,都比把这8万条 sql 当成8万个虚拟线程任务快一倍。如果我把这8万条 sql 生成8万个同步任务提交给 lealone 的 ClientScheduler 执行也比虚拟线程快了1.2倍。因为在虚拟线程里无法绑定 Statement 或 Connection 对象,只能从一个外部队列获取,就算扣除出入队列的开销,虚拟线程调用执行 sql 的同步方法时会导致大量的切换操作,所以巨慢无比。
@zhh-4096
很多数据库无法支持100万条连接,即便应用服务器收到100万条并发 sql,它也无法创建100万条连接,只能从包含上千条连接的连接池里取。如果做不到批量执行,我只要开100个平台线程逐条处理这100万条 sql 即可。反而用虚拟线程不好做,只能把执行每条 sql 的方法当成一个虚拟线程任务提交,实测更慢。
我现在基本可以下结论:用虚拟线程通过 jdbc 客户端访问数据库毫无用处,从几千到几万甚至数十万数百万条 sql 都是如此,还不如直接开平台线程直接把这些 sql 发给数据库。通过 jdbc 客户端访问数据库,最有效最优的方案只有一个:增加异步 api,通过非阻塞模式发送 sql。
又对 lealone 的 jdbc 客户端做了一点改进,新增了一个静态方法: LealoneClient.executeJdbcTask,可以像截图那样传递一个闭包进去,然后在里面调用最原始的同步 jdbc api,在高并发场景性能比应用启动几百个线程好一些,这算是同步 api 和 异步 api 之间的折中方案了。
如果有数10万条 sql,把每条 sql 当成一个 JdbcTask 去调用 LealoneClient.executeJdbcTask,性能比虚拟线程快1倍以上。
@zhh-4096
又对 lealone 的 jdbc 客户端做了一点改进,新增了一个静态方法: LealoneClient.executeJdbcTask,可以像截图那样传递一个闭包进去,然后在里面调用最原始的同步 jdbc api,在高并发场景性能比应用启动几百个线程好一些,这算是同步 api 和 异步 api 之间的折中方案了。
使用 lealone 的 jdbc 客户端,不需要第三方的连接池组件的,比如你的应用代码部署到应用服务器上面,开了几百个线程,这些线程直接调用 LealoneClient.executeJdbcTask 方法,把你现有的调用了 jdbc api 的方法搞成闭包传进去即可。
@zhh-4096
又对 lealone 的 jdbc 客户端做了一点改进,新增了一个静态方法: LealoneClient.executeJdbcTask,可以像截图那样传递一个闭包进去,然后在里面调用最原始的同步 jdbc api,在高并发场景性能比应用启动几百个线程好一些,这算是同步 api 和 异步 api 之间的折中方案了。
做了个梦,梦里带着一把柴刀走进儿时读书的小学,一位看似校长的陌生面孔向我走来,他有点紧张,我把柴刀递给他,说我曾在这里读过书,回来看看,然后一直聊学校为什么办不下去。我读过的小学、初中、中专都没了,就像某段历史被抹除干净,初中连校园都不复存在。甚至工作的第一家国企也没有一点痕迹。
最近经常光顾一家沙县小吃店,由一对老年夫妻经营,老年人做事有耐心,适合做小吃。以前在杭州工作时,沙县小吃店就是我的噩梦,公司食堂的饭菜太难吃了才不得不跑去吃沙县,杭州就只适合工作,我一点都想不起来杭州有什么好吃的。直到这一次才对沙县小吃有改观。
杭州有阿里有浙大,这是我觉得比较好的,其他方面我还是觉得桂林好。桂林过去一直是西南、岭南、中原3种文化的交融处,国立广西大学在桂林办学时在全国也很知名,只可惜建国早期被国家拆分完了,没过几年,连省会都搬到南宁。90年代末为了给旅游业让位,又几乎把工业砍光。新桂系的老巢就这样被掏空。
1998-2001年我刚好从乡下到桂林市区读书,那几年就是桂林舍弃工业全力转向旅游业的转折点,当年李金早对桂林进行了翻天覆地的改造,比如推出免费的双层旅游观光巴士、五星级厕所,现在两江四湖也是那时开挖的,桂林的旅游业成了全国的教科书。现在看没有几个人口超过300万的城市只靠旅游就能活得好的。
当时还建了覆盖市中心几公里的庞大地下商业街,这两年我去云南和广西也发现一些地级市在搞,只是规模小一些,桂林20多年前就有了,现在只剩下中心广场的地下商业街还在运营,也没多少客流量。可以这么说,桂林在我读书的那几年旅游和商业就达到最高峰了。
@zhh-4096
1998-2001年我刚好从乡下到桂林市区读书,那几年就是桂林舍弃工业全力转向旅游业的转折点,当年李金早对桂林进行了翻天覆地的改造,比如推出免费的双层旅游观光巴士、五星级厕所,现在两江四湖也是那时开挖的,桂林的旅游业成了全国的教科书。现在看没有几个人口超过300万的城市只靠旅游就能活得好的。
四五十岁的中老年人还能有件喜欢的事做就不错了,钱不钱的无所谓。我一老朋友是技术高管,平时没项目时也闲,最近几个月新找了一份帮别人看鱼塘的工作,正好喜欢钓鱼,已经对赚钱没兴趣了。幸好我做数据库也乐在其中,赚钱很次要。这就是中老年人的快乐!
不错,已经小于10秒!在日常开发中,很多大中型开源软件把所有测试用例完整跑一遍太痛苦了。而 lealone 就非常简单,在 eclipse 中右键点击 lealone-test 模块,然后在弹出菜单中点 Run As ->JUnit Test,10秒内就能把 lealone 的所有测试用例跑完。
@zhh-4096
对性能要求高的人有强迫症,看到测试跑得不够快也去优化一下,哪怕一天只跑一两次,现在跑完 lealone 的所有测试用例只需要10多秒。
已经连续几年没写年终总结了,到了这个年纪就是过好当下的日子,不再矫情,也没有狂野的规划,手头上还有一件事能持续做就够了。2025年真正工作的时间就只有10-12这三个月,2026年只希望身体不垮能有更多时间工作,股票赚钱多的话就多换几个城市边游玩边工作。
lealone 8.0 做了那么多新工作,jar 包大小依然不超过2m,启动时间依然小于200毫秒。要保持双1开头,不能2。
https://postimg.cc/gallery/54PDC0k


lealone 8.0 在 client-server 和嵌入式这两个场景的优化都做完了,得到一些极限数据:
16个并发就能把8核的 cpu 跑满,使用同步 jdbc api 通过 localhost 压测数据库,lealone 8.0 测得的极限数据是每秒能并发逐条执行16万条 update 语句;如果是在嵌入式场景下压测,每秒能并发逐条执行48万条 update 语句,也就是嵌入式场景比 localhost 这种 client-server 场景快了两倍。如果用异步 jdbc api 通过 localhost 压测能达到38万,跟嵌入式场景就没那么大差距了。
mysql 和 postgresql 无法测试嵌入式场景,localhost 测得的数据都是每秒5万左右。sqlite 在嵌入式场景测得的数据跟 lealone 相比差太多,每秒并发逐条执行的 update 语句是4.5万。
i5 的 cpu,严格来说只是4核8个超线程,比真实的8核还是差一点的。即便是用配置了i5的笔记本电脑也能跑出这样的性能已经很不错了,中小应用的并发需求使用单机版的 lealone 8.0 买台三四千块钱的笔记本电脑来跑,真是绰绰有余。
@zhh-4096
lealone 8.0 在 client-server 和嵌入式这两个场景的优化都做完了,得到一些极限数据:
16个并发就能把8核的 cpu 跑满,使用同步 jdbc api 通过 localhost 压测数据库,lealone 8.0 测得的极限数据是每秒能并发逐条执行16万条 update 语句;如果是在嵌入式场景下压测,每秒能并发逐条执行48万条 update 语句,也就是嵌入式场景比 localhost 这种 client-server 场景快了两倍。如果用异步 jdbc api 通过 localhost 压测能达到38万,跟嵌入式场景就没那么大差距了。
mysql 和 postgresql 无法测试嵌入式场景,localhost 测得的数据都是每秒5万左右。sqlite 在嵌入式场景测得的数据跟 lealone 相比差太多,每秒并发逐条执行的 update 语句是4.5万。
做技术产品,从产生灵感,到反复实践,最后得到验证,整个过程才是最愉悦的。花了3个月把想到的优化点都做完了,一下空荡荡的。寻找新灵感的过程其实是最痛苦的,完全不知道什么时候会出来新的灵感。好的灵感不是靠用户需求驱动,用户需求更多的只是新功能堆砌,并不一定有挑战。
有网友问用 c/c++ 重写 lealone 会不会比现在用 java 更高,能高5%就了不起了,完全没有重写的必要,除非想挑战 sqlite 应用到资源更受限的嵌入式场景,比如可用内存连 jvm 都跑不起来。
在最廉价的普通笔记本电脑上 lealone 的性能都已经远远甩开 sqlite、mysql、postgresql、mongodb 这些用 c/c++ 开发的主流开源数据库了,lealone 的性能已经做到极致,现在还能限制 lealone 的性能的早已不是程序语言,而是缓慢的硬盘和网络,哪怕通过 localhost 访问 lealone,通过 localhost 传输数据的时间也远远高于 lealone 处理单条 sql 的时间。
看到一篇老调重弹的文章,说数据库按单线程分片读写不就没有冲突了?理论上当然是可行的,lealone 很多年前就实践过了,比如 btree 的每个 page 有且只有一个线程负责读写,理论上就是完美的分片。
问题是实际场景中数据库当前线程接收到的读写请求不一定跟 page 的实际处理线程一致,所以当前线程还是得把数据放到实际处理线程的队列,这时这个队列又变成了共享对象,出入队列本身就耗时,可能还需要唤醒线程去处理它负责的数据,最终实践下来这种分片的性能很差,还不如对 page 实现一个基于 CAS 的轻量级锁高效。
我现在极少去饭局或参加什么活动或会议,以前同事只要一说起什么人什么事,基本就被我拒了,这次同事学聪明了,死活什么都不说,就说很重要,所以等下我要跟他去参加一个他说的很重要的活动,如果去了还是浪费我的时间,就没有下次了。[笑cry]
一开始进来看到三位女士我就觉得不太对劲,饭吃到大半还不聊生意的正事,回去的路上我问同事怎么回事?原来是两边特意组的一个相亲局。两位已婚女士带着一个也不知情的未婚闺蜜来,都在体制内工作。现在大龄剩女剩男的婚姻大事真是让身边的人操碎了心。[允悲]
@zhh-4096
妈的又被同事忽悠来饭局帮他撑场面见陌生老板![摊手]
现在婚恋市场中的大龄剩女剩男就是两个极端,最低端是广大乡镇农村文化水平和经济条件差的男生,而剩女多是学历高工作能力强的,女生的择偶标准通常又是向上寻找比自己至少高一级的男生,加上男多女少,问题无解。我遇到的大龄剩女说实话绝大多数条件都不错,如果不主动出击想守株待兔,很难找到对象。
男生在生理结构上就要优于女生,所以我是觉得女生在婚恋市场上的竞争力是天生不对等的,25-35岁结婚最合适。一个年薪50万的40+岁的男人,在2-5线城市找个30+甚至20多岁的小姑娘真的不难,但是换成同样40+岁的女人拿着50万年薪,想找20多岁的小伙子过上稳定的婚姻生活却不容易,生理这关就难过。
java 的 nio 库的确比较坑,即便配置了阻塞模式,调用一次 SocketChannel.read(ByteBuffer),它也不会读满 ByteBuffer 的,得在一个循环里反复调用,直到读满达到 ByteBuffer 的 limit。就为了这个问题排查了一早上。[摊手]
早上压测了一个网友给的老项目,批量写了600多万条记录,lealone 的性能居然只比 h2 快了20%,然后我回头再压测了一下我写的批量压测例子,批量写960万条记录明明快了两倍。太诡异了,可能我的字段少,表也有主键,没有主键的表实际上都是串行直接 append 到最后一个 page,发挥不了多线程的优势。
技术人员有自己熟悉的技术栈,比如对 mysql 熟练了反而不会轻易换其他不熟悉的数据库。我自己有时也长常遇到这种问题,比如某个项目经理跟我关系好,想给我个面子让其他开发人员学习一下我的数据库,但是开发人员会不情不愿的,我很了解这种心理,所以我比较佛系,如果 mysql 满足不了需求再尝试一下 lealone 即可,没必要靠面子去推。
通过实际测试又发现一个反直觉的案例: 当初为无主键无索引的表设计一个 append 方法,是想不需要通过折半查找算法直接就能把记录 append 到 btree 最后一个 leaf page,这样不用走正常的 put 方法,因为 put 方法需要事先自动生成一个 row key,然后通过折半查找算法定位所在的 leaf page。实际测试下来发现,如果是多线程批量写的场景,用 put 方法居然比用 append 方法快一倍,因为 append 方法总是写最后一个 leaf page,会快速造成多线程写冲突,而 put 方法因为要提前生成 row key,不一定会同时写到同一个 leaf page,所以反而降低了写冲突,反而更快了。
如果是多线程非批量写的场景,用 append 和 put 反而没什么区别,因为客户端逐条执行 insert 语句时,有先后的时间差,在后端执行 append 操作的线程本身冲突就小。
总之,设计 append 这个写入数据的方法看起来是多余的。
@zhh-4096
早上压测了一个网友给的老项目,批量写了600多万条记录,lealone 的性能居然只比 h2 快了20%,然后我回头再压测了一下我写的批量压测例子,批量写960万条记录明明快了两倍。太诡异了,可能我的字段少,表也有主键,没有主键的表实际上都是串行直接 append 到最后一个 page,发挥不了多线程的优势。
又开始跑 tpcc 了,其实 tpcc 并不一定能真实度量出数据库的实力,因为它是测事务数的,一个事务通常会包含多条 sql 语句,每执行其中一条 sql 都需要网络开销,如果网络开销的累计耗时占了大头,最后 tpcc 测出的每秒事务数其实就是测网络开销。
美股开局3个交易日还不错,昨晚又赚了几千人民币,日常开销小就是好啊,再操盘一两次就能把2026年的生活费全赚够了。现在知道我为什么能无忧无虑的研究技术了吧?若是一直不结婚只顾自己真花不了几个钱,只要物质欲望不高,赚点生活费太容易了,然后就能按自己的喜好随心所欲去研究技术哪怕不赚钱。

加了相亲对象的微信后昨晚聊了一下,我的直觉告诉我没戏。
过去10年聊过的妹子少说也有15+个,其中30+岁的大姑娘和20+岁的小姑娘人数差不多各占一半。大姑娘普遍难聊,哪怕她是多年不见的初中同学,我第一个前任跟她正式谈时她也是大姑娘,在我印象里就没怎么主动过,更别说能提供什么情绪价值。大姑娘的普遍毛病就是爱端着,哪怕你的赚钱能力是她的10倍也依然会有一种我求她跟我聊天的感觉。
我遇到的这些小姑娘里就没有一个不好聊的,她们有好奇心有活力甚至还有一点慕强。我第二个前任就是20+,恋爱前和谈恋爱时的感受比第一任不知好了多少倍,以至于前段时间第一任想回来找我时被我无情拒绝了,甚至跟她直说我跟她过去的恋爱是痛苦居多,都算不上恋爱。
这就是为什么男人普遍喜欢找小姑娘的原因。
上上个周末叫我侄女把英语和数学的卷子发我看看,我想知道她哪些知识点没掌握好,她说家里没有,等她回学校了再发给我,结果上周等了一周都没发,前天我又催了一下她,又没有回应。说实话,看到这样的小孩我是有点失望的,答应的事都不能做好,说明父母很多小事都没教育好。
这就是很典型的底层家庭的教育,都谈不上教育,孩子的品行要不要纠正都意识不到。虽然我比他们的文化水平高,但是又不住在一起,又不是我的孩子,我不可能连侄女的教育都全去管,这也不是我的义务。
每次听到一楼那家人的小女儿跟父母大吼大叫的相处模式,我都很震惊。所有这些底层家庭生娃养娃都靠运气,因为根本就不知道如何教育子女,读书是好是差,人品将来好不好,都靠运气。
现在农村很多连女朋友都找不到的大龄剩男,说实话绝大多数要么是没能力还得靠父母养要么就是人品有问题。农村家庭很多都谈不上有什么教育,自私自利的人一大把。我不敢说我有多高尚,但我绝对是希望兄弟姐妹过得好的人,能做到不看重钱还出钱帮助兄弟姐妹从农村搬到城市,在农村怎么说都是凤毛麟角。
tpcc 我是用别人写的实现跑的,里面有个批量加载数据的测式,计算的时间太杂,把一堆输出中间结果的步骤也算在内,只有一个主线程在造数据,按它这个时间度量的方式,lealone 最多比 h2、mysql、postgresql 快了50%而已,然后我修改了一下,只度量调用 jdbc executeBatch 的累计时间,结果瞬间快几倍。
@zhh-4096
又开始跑 tpcc 了,其实 tpcc 并不一定能真实度量出数据库的实力,因为它是测事务数的,一个事务通常会包含多条 sql 语句,每执行其中一条 sql 都需要网络开销,如果网络开销的累计耗时占了大头,最后 tpcc 测出的每秒事务数其实就是测网络开销。
小孩子在上小学前的几年比较讨喜,在我印象里我叔叔伯伯也是在我上小学前会带我玩玩,之后就没啥印象了,我现在跟他们的关系就是一年见几次面。我跟我侄女们也是这样的相处模式,并没有多深的感情,等我老了生病住院了能来看我一次我就谢天谢地了。跟父母和亲姐弟的感情深,我通常会对感情深的人更好。
http://t.cn/AXbiNkdH网页链接 我才知道田春被大学解聘的事,所以西方也没有什么言论自由,微博调侃几句也能丢工作。还是我这种独立研究者自在,不依附于任何人和机构,玩玩股票就能轻松赚到生活费,不需要为五斗米折腰。2006年我放弃考研,拒绝进学术圈是明智的!
中国女性的地位现在放眼全世界也没有多少个国家能比。我有7个堂弟,就剩两个最小的没结婚,我预测最后至少有4个堂弟结婚生娃2+个至少有一个得跟母姓,外公外婆这种物种正在消失,因为两边都叫爷爷奶奶。即便我跟前任聊到结婚的事时,她家里也是要求至少有一个孩子跟母姓,也要求两边统一叫爷爷奶奶。
当两边都叫爷爷奶奶后,我听过大人们跟孩子的对话,比如在爷爷奶奶面前加地名,这样才知道说的是哪个爷爷奶奶。如果一边是农村人另一边是城里人,农村的爷爷奶奶明显就不如城里的亲,最后发现只比上门女婿好一点。[允悲]
@zhh-4096
中国女性的地位现在放眼全世界也没有多少个国家能比。我有7个堂弟,就剩两个最小的没结婚,我预测最后至少有4个堂弟结婚生娃2+个至少有一个得跟母姓,外公外婆这种物种正在消失,因为两边都叫爷爷奶奶。即便我跟前任聊到结婚的事时,她家里也是要求至少有一个孩子跟母姓,也要求两边统一叫爷爷奶奶。
抖音上偶尔刷到老外看广西男人下厨的视频居然能让他们吃惊!我以为全世界的男人都会下厨做菜的。我们还没读小学时就被大人要求做所有家务了,逢年过节或者平时有客人来,基本都是男人下厨,因为在我们这里男人的厨艺一定是最好的,做得不好吃会被骂,大场面从小到大我就没见到过女人主厨。幸好广西的彩礼还不算很高,大多10万以内,如果彩礼再多要点,加上房车和家务,还得拼命工作赚钱,孩子之一还得跟母姓,那广西男人恐怕是全国最悲惨的男人了![允悲]
我为什么需要别人认可?我既然选择不进学术圈,就不需要别人认可,一个人的价值需要别人认可那是很可悲的一件事。别人做研究发论文可能是为了谋求一个学位或教职,我又不需要。我这条微博又没有评论他的成果。//@在飞船发微博的水珍珠 :但人家的学术成果是发了论文被认可的, 感觉你的数据库是曲高和寡
@zhh-4096
http://t.cn/AXbiNkdH网页链接 我才知道田春被大学解聘的事,所以西方也没有什么言论自由,微博调侃几句也能丢工作。还是我这种独立研究者自在,不依附于任何人和机构,玩玩股票就能轻松赚到生活费,不需要为五斗米折腰。2006年我放弃考研,拒绝进学术圈是明智的!
我从来没有后悔当初放弃考研,甚至没有后悔从阿里离职少了上千万的股票。我最理想的工作和生活状态就是现在,有自己喜爱的工作哪怕还不赚钱,也不用担心生活费,想旅游几个月随时可以去,想几点起床就几点,想不工作就不做,可以拒绝所有交际,不需要看任何人脸色,可以怼任何网友。
我没有什么物质欲望,至今依然住在月租160人民币的城中村,如果不去旅游,每年个人开销不超过1.5万人民币。我之所以创业开公司,也不是为了满足个人私欲,最初只是想寻找志同道合的人一起做个技术产品赚更多钱能帮更多的人。就算现在没有这样的同路人,我也能快乐的当个独行侠,但是也不自私,自己快乐的同时也能让全家人过上了更好的生活,所以我从来不觉得自己失败,我已经相当满足,我的价值从来不需要别人认可,我只做我想做的事。
好久没关注 Apache Cassandra 了,背后的商业化公司 DataStax 居然在去年5月底就被 IBM 收够了,卖了30亿美金左右。IBM 买 Kafka 的商业化公司Confluent 反而花了约110亿美金,说明垂类的数据库还是卖不了大价钱,Cassandra 的应用场景多是非核心系统。还是那句话: 开源项目最后多是被大厂收购的命!
Andy Pavlo 每年的数据库总结挺有意思,很多观点不谋而合,比如 MySQL 快完蛋了 PostgreSQL 在崛起;时序数据库我一直说市场太小,能发挥的空间有限,所以一直懒得做,现在连 Timescale 都改名成 TigerData,就怕别人说它只是个时序数据库。
我已经好久没有关注王垠了,自从他不再专心研究技术之后我也没啥兴趣再关注。我比他更纯粹一点,玩了16年微博至今没有收割一个粉丝,我只专注做一个技术产品,目前唯一收入就是投资股票。所以过去的网友除了说我曲高和寡、自恋之外,确实也找不到什么槽点可喷的。
这是我上一次提到王垠的微博,都几年前的事了,他现在在干什么我也不知道。刚好几小时前又看到伞哥被大学解聘的博文,还是挺感慨的。昨晚跟相亲对象聊天时,才知快奔四了正好刚拿到副高的职称,这时别人凑巧把我介绍过去,搞得我像是那种不要脸去舔的人。以前有人给我介绍个副教授我都没去见。[笑cry]
@zhh-4096
王垠远离父母在国外闲得看飞机尾巴的排泄物;伞哥离婚后跑去国外读博,跟导师玩人情世故;我这样的民科比较恋家,在家乡也能自得其乐。三个同龄的中年技术男,各有各的活法,自己觉得舒服即可,我偶尔吐槽王垠也只是说他最近几年的思想走偏了。
桂林排名前5的大学我都认识一些老师,有的还吃过几次饭,我早已对大学老师祛魅了,无论是工作或是婚恋,都不会仰视大学老师(哪怕TA是教授)。如果比较专业能力,我不输他们,甚至能俯视他们,因为我在专业上投入的时间远比他们更多,我不用把时间浪费在勾心斗角和人情世故上。
我找对象不太关心学历和经济条件的,前任是硕士,去年新认识的又变成职校,前天相亲的又是副高。高学历也大把低情商的,我又不缺钱也不要求对方有个超级稳定的铁饭碗,我最看重的还是对方能不能听懂我在表达什么,相处起来是否轻松,圈子是否干净,是否有主见。我不是 gay,不找男人。
tpcc 测了5种事务类型,其中的库存状态查询事务(Slev)就是纯查询统计,按它这个测试,lealone 能达到125万的 TpmC,postgresql 是116万,mysql 是64万。
它这个 tpcc 加载数据的测试就不准了,没有预热,度量的开始时间也不对,主线程花了很多时间在造数据,我给它加了一个指标,就是算平均每个线程执行所有 jdbc batch 操作的时间,lealone 才花了700多毫秒,postgresql 花了3100多毫秒,mysql 花了5810多毫秒。如果按它的结果看总执行时间就差别不大。
因为 mysql 的 jdbc batch 实现是非常差劲的,所以它这个批量加载数据的测试是有专门给 mysql 做了优化,不调用用 jdbc batch api,而是把一批数据组装成一条多值 insert 语句,即便对 mysql 优化过了,批量写数据的平均时间依然被 lealone 碾压,tpcc 的表有不少索引,lealone 异步写索引有优势。
@zhh-4096
它这个 tpcc 加载数据的测试就不准了,没有预热,度量的开始时间也不对,主线程花了很多时间在造数据,我给它加了一个指标,就是算平均每个线程执行所有 jdbc batch 操作的时间,lealone 才花了700多毫秒,postgresql 花了3100多毫秒,mysql 花了5810多毫秒。如果按它的结果看总执行时间就差别不大。
一个开源的可反复验证结果的技术产品就放在那里,连 AI 都能分析得头头是道了,谁特么在乎是不是在学术圈发了论文,学术圈算什么东西,VLDB 的垃圾论文一大堆,你要真觉得自己发的论文牛逼就把它落地做成一个产品,然后跑跑看看谁的性能好。做出一个稳定的性能领先的技术产品不知比发篇论文难多少倍。
我过去不想进学术圈,以后更不想进。别说不发论文了,集群版还有更好的技术,连开源都不想开,专利也没必要申请。我花了10几年钻研数据库,就是为了给自己设定目标,这样才能更好的消磨时间。我是为了自己爽,不是为了去学术圈证明自己让别人认可。我从小就是这个调调了,说得不好听就是目中无人。
满分100,我对自己的工程能力和创新能力都打95分,学术圈的人绝大多数工程能力就是弱鸡。数据库领域我最欣赏的人是 Jim Gray,因为当我第一次打开《事务处理》这本砖头书时才发现这位图灵奖得主居然那么看重工程能力,肃然起敬。在基础软件领域做研究,工程能力差就是不接地气的表现。
tpcc 还没有跑完,NewOrder、Payment、Delivery 这3种事务跑出的性能太诡异,还在排查问题,其他两种事务和批量加载数据都正常了符合预期。跑 tpcc 用来测试并发事务的稳定性确实很不错,因为它每个事务包含的 sql 语句覆盖面广。
每个人的成长经历是不同的,像梁博这种常把百司不录挂在嘴边的人当然会努力去证明自己让别人认可。我这人就没遇到多少难事,也就毕业赶上互联网泡沫找了大半年工作,最后还是能进一家国企做专业对口的工作。从小就比全村的小孩聪明,读书10几年文理科在全年级又常拿第一。在论坛上发篇文章就能被推荐进阿里。你说我这种人需要谁认可?在我的脑子里就没有被别人认可的想法,只有我去认可别人的份。
而且更气人的是,我都不知道自己优秀,学生时代我根本就不像个读书人,特爱玩。得奖对我来说无关紧要,印象最深的一次,期末上台从校长手中领奖状很随意,然后校长当着全校师生的面把我臭骂了一顿。那又如何,最后学校参加各种比赛还不是要派我去。所以我这种人从小就不在乎别人怎么看我的。
@zhh-4096
每个人的成长经历是不同的,像梁博这种常把百司不录挂在嘴边的人当然会努力去证明自己让别人认可。我这人就没遇到多少难事,也就毕业赶上互联网泡沫找了大半年工作,最后还是能进一家国企做专业对口的工作。从小就比全村的小孩聪明,读书10几年文理科在全年级又常拿第一。在论坛上发篇文章就能被推荐进阿里。你说我这种人需要谁认可?在我的脑子里就没有被别人认可的想法,只有我去认可别人的份。
我不是一个循规蹈矩的人,如果去读博我很有可能也会退学。哪怕一家公司有太多约束我也不想去,就比如华为,很多年前他们有个
2012实验室找过我,邮件里沟通了几次,后来一想到去南京跟他们合作一个大数据项目的事,不到一周我就跑了,自己的电脑都不能用也不能联网。最后我就在邮件里说不去了。
华为跟阿里确实是两种截然不同的管理风格,有一年我在阿里负责 tomcat 升级替换 jboss 的工作,为了测试各种应用的兼容性,我几乎把整个淘宝网的子系统的代码都拿到了。在阿里可以用自己的电脑可以随意联网,怎么就不担心自己的核心技术被泄露呢?离职时是我主动把自己电脑中跟公司相关的代码删除的。
人还是得经历一点痛苦的事才会成熟。19岁以前我是一个妥妥的社牛,会经常跑去同学的家里住一段时间,我都学会了几种土话。
我开始变得内向就是19岁毕业找工作的那大半年,因为找工作困难,父母认为我这种学习好的人怎么可能找不到工作就是在贪玩不想找工作,所以把我的伙食费都断了,最后真的导致我没有钱吃饭。跟几个同学挤在一间没有厕所的出租房里,他们在出版社找到了搬运工的活我还是无业游民,那段时间真的感觉低人一等。跑去帮我姐摆摊做生意也经常被她骂。那大半年真的觉得自己是个没用的人,以前的傲气全没了。
如果不是因为有这段痛苦的经历,我绝对比现在更狂傲。从2002年年初正式工作到现在一直挺顺的,加上长时间宅在房里独自研究技术,最后变得越来越不喜欢交际。
我也是在这段找工作的时间才发现学校学的东西跟社会脱钩太严重了,都互联网泡沫了,学校还教 pascal 和汇编语言,也多亏我跑人才市场看到招聘需求后快速自学了 java 和 jsp,然后去公司报道第二天就出差进项目组搞一个 php 项目,组里有两个同事准备离职急找人补上,看我会 jsp 转 php 快才要的。
@zhh-4096
人还是得经历一点痛苦的事才会成熟。19岁以前我是一个妥妥的社牛,会经常跑去同学的家里住一段时间,我都学会了几种土话。
我开始变得内向就是19岁毕业找工作的那大半年,因为找工作困难,父母认为我这种学习好的人怎么可能找不到工作就是在贪玩不想找工作,所以把我的伙食费都断了,最后真的导致我没有钱吃饭。跟几个同学挤在一间没有厕所的出租房里,他们在出版社找到了搬运工的活我还是无业游民,那段时间真的感觉低人一等。跑去帮我姐摆摊做生意也经常被她骂。那大半年真的觉得自己是个没用的人,以前的傲气全没了。
如果不是因为有这段痛苦的经历,我绝对比现在更狂傲。从2002年年初正式工作到现在一直挺顺的,加上长时间宅在房里独自研究技术,最后变得越来越不喜欢交际。
我读书那3年1998-2001就是互联网最火爆的时候,比现在的大模型还要火爆,我本来是学会计统计专业,然后也跑去兼读计算机应用专业,全班59人,只有3个人敢报计算机,最后这3人只有我拿到毕业证。那时如果我像现在能有台电脑可以上网,绝不可能毕业找不到工作。那时学计算机太难了,哪怕是学计算机的课,能摸到计算机的机会也很少,就算有这样的机会也是386的老古董。
毕业找工作时,为了自学学校没教过的技术,还特意跑到化学系一个对外开放的机房熬夜在老古董上面调试代码学技术。有天晚上熬了一夜早上走到地下车库发现自行车被偷了,真是欲哭无泪,最后再也没去机房,连最值钱的二手自行车都没了。
我工作的第一家公司是国企,我所在的部门专门给移动电信和邮局做定制项目,这些甲方有钱,都是用他们提供的电脑给我们做研发。项目做完回到公司,又得用那种32M内存的老台式机,连个 IDE 都跑不起来。我是1年半后当上了项目负责人,公司才给我配了台联想的昭阳笔记本电脑,要两万多块钱,按现在的物价算得10+万,当时可把我开心坏了,在这台笔记本电脑上又自学了一堆技术,比如 Oracle。
直到2006年我辞职后才用自己攒的钱买了人生的第一台电脑,花了我差不多9000块钱,是华硕的笔记本电脑,直到现在我一直都是用华硕,正在用的已经是第三台了,前面两台笔记本电脑都没坏,只是配置太低了,跟不上软件的需求了。
我想跟年轻人说,如果你遇到一些坎,当下看可能觉得是坏事,往后几年回头看可能就变成好事了。我都经历过好多次这种所谓的坎了。
比如好不容易花了大半年才找了一份工作,刚入职不到半年当牛马做完第一个项目,整个部门除了我都被另一个领导带走成立新的公司,我都以为我要失业了,结果没有,心惊胆战维护了差不多一年,然后整个项目被甲方看好,从一个地级市推广到省内所有地级市,我一下从菜鸟变成了项目负责人。
工作了4年后辞职了,我原本是不打算考研的,一开始是移动公司的熟人把我的简历推送给一家叫亿阳的上市公司,结果最后跟我说学历太低了看不上,然后我才想说要不去考个研吧。这家公司若是看上我了,可能我到现在还在日复一日做外包项目,不会有什么出息。
2006年开始复习考研,前几个月还很有干劲,后面越看书刷题越无聊,也曾纠结这样做下去值不值得,开心不起来。直到我去书店闲逛,翻到一本讲编译器的书,看得入迷,因为学计算机专业时没有这门课,自己看都能看懂,我就在想是不是没必要考研了,自己钻研技术就好了,不用再去背英语背政治刷数学题,就直接研究感兴趣的技术多好啊。可是当时都已经11月份了,这时放弃考研多可惜啊!最终我还是选择放弃考研。现在回头看也是对的,通过钻研技术,我不但轻易进了阿里工作,还培养了自己独自做科研的能力。这时的我哪怕文凭还是没变,对于亿阳这种曾经看不上我的公司反过来到我看不上它了。
我至今遇到的最大的坎发生在2008年,刚过完春节不久,就告诉我说我爸住院了,在县医院住了10多天,医生也不敢说什么原因,就直接帮我们转院到市里的南溪山医院,拍了一堆照最后告诉我是晚期肺癌,当时真的觉得天都塌了,那时我爸才50出头,我都辞职两年多了正在独自钻研技术,我姐弟都没钱,家族里其他人没有一个能帮,有的还没等我开口就说没钱。南溪山医院虽然是很好的医院,但我还是不敢相信是晚期肺癌,又拿着病历去问了好几家三甲医院,最后都是一样的结果。
在南溪山医院住了差不多一个月,医生还是好的,知道我们没钱也知道没救了,并没有做化疗,只是当时我爸还是清醒的,不甘心,就在医院拖一段时间,每天挂好多药水吃止痛药。看到一直没好转我爸也认命了,就说回去了。回到家天天躺着,疼得要命,只能吃止痛药,饭也吃不下,最后瘦成皮包骨,逐渐失去意识,在家3个月就走了。
最后接着办丧事,不到5个月的时间,就看着一个大活人从我的世界中消失,也差不多花光了我工作4年的积蓄。
一家之主走了,我当时也不过20多岁,我弟当时还是个混混,全村人都在看笑话,这家人要完了,连我叔叔他们都觉得我们也就这样了。从那时起我才知道什么是责任,我并不关心别人怎么看,处理完家事我还是用仅剩的一万多块钱继续独自钻研了一年半的技术,最后在2010年去了阿里工作,待遇比在桂林翻了10多倍,那几年还帮我弟结了婚,让他走上了正道。
最近几年还帮助姐弟在城里都买了房,全家人都搬到了城里,也是全村第一家,村里人说我真好啊,打着灯笼都找不到的好人。我不会去记恨村里人的,因为从一开始就没有恨,人之常情,别人没有义务要帮你。
就算有钱了我也不炫富,别人开宝马我还是会骑单车回去,因为我真的不在意别人怎么看,做自己认为对的事就好了。
我想聊一下我司的财务大姐,她比我大10来岁。2002年我去厂里上班时,我不到20岁,她已经在那里工作了10多年,也是中专毕业,30+岁,留着短发,长得很像现在的欧阳夏丹。厂里安排她来我们部门,一个人又做行政又做 hr 还做财务。我们这个部门还是在厂里办公的,但是更像个子公司。半年不到,因为部门领导跟厂长有分歧,除了我,其他研发人员都被带走去南宁新开的公司了。
然后就剩我跟她在这个空空的部门运转了差不多一年,幸好我维护的项目迎来重大转机,原本这个项目只在南宁用,后来全广西的地级市都在用了。厂里又派了一个新的领导过来,因为有了机会进到各地级市的运营商,我们不只做软件,还帮运营商做运维,包括基站、机房、传输线路的运维都做,光是桂林市的运维人员就有五六十号人。
2003-2005那两三年公司蒸蒸日上,但是到了2005年下半年,厂里不知道又搞什么鬼,导致跟运营商的运维合同全都断了,公司还好心把所有运维人员都尽可能推荐到竞争对手那边。我做的软件也是跟运维相关,也受牵连,最后整个部门又只剩我跟她两个人了,经历了3年的大起大落,再次回到原点。
国企就是有这样的毛病,真正能做事的人总会遇到一些恶心的人和事,然后不得不出走。我也看不到什么希望了,加上已经攒了点钱,就在2006年年初选择了辞职。这个厂几年后也倒闭了,她后来也新找了一家公司做财务,还算稳定,月薪5000左右。
2016年我跟厂里一个前同事开始在桂林创业开公司,最初也找过她一起合伙,但是她要养小孩,不想辞职冒险,我就把公司的财务甚至一些合同起草的工作都交给她做,让她自己开价,一个月只要1200。创业前两三年公司主要做外包项目,也有一些钱赚,年底我会给她发五六千的奖金。从2020年开始我就决定不做外包项目了,让合伙人新开了一家公司,所有人和外包项目都给他,我自己只专注数据库产品的研发,公司也没有关,就算没营收也还是有一些杂事要处理,我还是给一些钱给她帮我处理,这个阶段实际上公司又剩我跟她了,我偶尔也会画画饼,跟她说数据库产品也有可能赚钱的。她也没说过什么丧气的话,还好没辞职跟我创业,至少现在她的工作还在,每个月有稳定的收入。
公司开到现在也10年了,虽然还没有成功,但至少我没有坑过一个人,也没有向其他人借钱维持公司的运转,这是我开公司的底线,不能因为自己开公司而拖累任何人。
说了那么久短线交易策略,还真的有网友用心去试了。炒股大模型暂时还不能全心投入去做,一方面是券商提供的 api 还无法全部满足我的需求,另一方面要优先在一季度把数据库产品做稳定,数据库都不稳定,依赖它的炒股大模型就地动山摇。

开源软件从前年开始就已经进入收购期了,去年我也买过几次 confluent,但是一直没等到 ibm 正式发布收购的消息,错失了30%的涨幅。目前 gitlab 和 elastic 都是不错的收购目标,我也在等待时机,目前还是短线为主,如果买到一个很低的价格就静等收购。
是不是因为受2020年的疫情影响,最近三年我看到不少人因为脑梗去世,60-80岁都有,以前很少听说。我爷爷也是因为脑梗,我家邻居大婶同样是脑梗去世,也就60多点。刚刚家人跟我说我大伯母也脑梗了两天不吃不喝,然后打120从乡下拉到医院,还在急诊没出来话都不能说了,叫我明天去医院看一下。
到了我这个年纪,基本上年年都有认识的人死掉,多的时候一年好几个,我们这的习俗如果是清明后死的,第二年的清明节还得派人去吃饭然后上山祭拜,若是某一年死的人多,清明节都忙不过来。所以我现在对死亡这件事真的就是当成家常便饭了,来个急病死掉反而省事,若是救不活的晚期癌症,拖得一家人痛苦。
我现在心情很复杂,这个大伯母在我眼中一直是个泼妇,从小就看到她为了点田地问题跟我妈吵架还打过我妈。她狠起来连我大伯都打,前几年在村前的停车场上村民们和我一起目睹了她拳打脚踢我大伯的闹剧。我妈不愿在城里住,就想一个人呆在乡下,我最不放心就是这个大伯母,前年因为我爷爷的事还大吵过。
@zhh-4096
是不是因为受2020年的疫情影响,最近三年我看到不少人因为脑梗去世,60-80岁都有,以前很少听说。我爷爷也是因为脑梗,我家邻居大婶同样是脑梗去世,也就60多点。刚刚家人跟我说我大伯母也脑梗了两天不吃不喝,然后打120从乡下拉到医院,还在急诊没出来话都不能说了,叫我明天去医院看一下。
农村出来的读书人不管男女都不容易。就像我大伯家,幸好我堂妹是个读书的料,考上了医学院校,出来当医生,至少家里起房子还能帮个10来万。但是医生若是没有灰色收入也真没几个钱,帮了家里,自己小孩眼看上小学了,想买个房子也遥遥无期。当医生的好处就是父母生病了可以拉到自己所在的医院,真若是个花钱的病其他兄弟姐妹没钱也还得靠她。也没有更多余力去帮他两个弟弟,不是每个人都能像我的,别人有别人的难处,所以我从来不会道德绑架别人,量力而行,不要把自己的小家庭搞得鸡飞狗跳。
农村出来的读书人不管男女都不容易。就像我大伯家,幸好我堂妹是个读书的料,考上了医学院校,出来当医生,至少家里起房子还能帮个10来万。但是医生若是没有灰色收入也真没几个钱,帮了家里,自己小孩眼看上小学了,想买个房子也遥遥无期。当医生的好处就是父母生病了可以拉到自己所在的医院,真若是个花钱的病其他兄弟姐妹没钱也还得靠她。也没有更多余力去帮他两个弟弟,不是每个人都能像我的,别人有别人的难处,所以我从来不会道德绑架别人,量力而行,不要把自己的小家庭搞得鸡飞狗跳。
扶持家人确实是一件长期的巨耗费精力和财力的事,我现在上岸了解脱了,到我这个年纪已经不想再把这样的事重做一遍,我现在只想好好享受生活。哪怕是我侄女我也不怎么上心去管了,她若是主动一点我就顺手帮一下,交代的事爱理不理,我也不会说第三遍。跟下一代的感情确实淡了很多,不会再逼迫自己去帮。
电视剧里经常丑化凤凰男、扶弟魔,我也知道把握不好分寸真的是个无底洞,所以我也只对父母和亲姐弟好而已,这些亲人曾经跟我朝夕相处了至少20年,是有很深的感情的,我过得好了,就有义务让他们也过得好一些。其他人包括我姐弟的孩子,一年只见到几次,真的跟他们没多少感情,不去扶持他们也不会愧疚。
我对谁更好,只取决于谁跟我相处的时间多且感情深。所以伴侣绝对是第一位,30岁结婚80岁死掉,要在一起50年;父母、孩子排第二,通常要在一起相处30年;亲兄弟姐妹排第三,一般就是相处20年。
我的微信默认不给别人加我,所以微信好友很少。去年我姐在微信里说侄女有事找我,然后我才加了她的微信。加了半年微信,只要她主动给我发信息,就只有一件事:需要钱了。我现在给钱也谨慎了,要跟我弟确认。给钱给她补课,我都不确定她真的去补了没有,叫她给我看看试卷想看看补课效果一直不发。[允悲]
现在10几岁的孩子已经学会说谎了,加她微信后一开始她叫我买个挺贵的东西,说的理由还挺好的为了学习,我真的以为她父母不给她买(至少要一个月的工资),结果中秋节回去听到我弟说他都买过了,只是她自己大意搞丢了,还嫌弃买的款式不好。养小孩太难了![笑cry]
@zhh-4096
我的微信默认不给别人加我,所以微信好友很少。去年我姐在微信里说侄女有事找我,然后我才加了她的微信。加了半年微信,只要她主动给我发信息,就只有一件事:需要钱了。我现在给钱也谨慎了,要跟我弟确认。给钱给她补课,我都不确定她真的去补了没有,叫她给我看看试卷想看看补课效果一直不发。[允悲]
父母还是更了解孩子,就比如补课这件事,我弟是不同意给我侄女补课的,他就说我侄女一放学回来就是玩,哪怕成绩差也从来不看书学习,补课就是浪费钱,每月给1200补课费是笔不小的开销,对于一个不爱学习的人一个月补课10-12小时能有什么效果,基本上不抱希望了, 然后我就说我出点钱给她试试吧。
现在村上10后这帮小孩就没有听说哪个读书好的,即便跑到城里读书也是一样,我弟的两个女儿读书也不行。太难了,我们80后这一代的小孩在村上至少还有20%的比例读书过得去。现在很多小孩就知道玩手机打游戏刷抖音,也不做家务。
@zhh-4096
父母还是更了解孩子,就比如补课这件事,我弟是不同意给我侄女补课的,他就说我侄女一放学回来就是玩,哪怕成绩差也从来不看书学习,补课就是浪费钱,每月给1200补课费是笔不小的开销,对于一个不爱学习的人一个月补课10-12小时能有什么效果,基本上不抱希望了, 然后我就说我出点钱给她试试吧。
小孩子贪玩不爱学习可能也是天性,我弟也头疼,孩子不听话时他也打骂过,最后发现也没用,也不打不骂了,随她去。他跟她老婆小时候都是读书差的人,小孩子也差,那只能认命。我也没招了,我只是在想如果我的小孩也是这种学渣我该怎么办?我宁愿不要小孩了!
这是我弟给我发的成绩单,刚好这周有考试。初三数学补了3个月的课,还是50多分,我是没想到连语文都这么差。这个成绩只能靠镇里最差的高中施舍才能读了。[允悲]

叹气,浪费钱不说还浪费时间。我是真的不懂学渣的世界到底有什么东西,我这辈子觉得最容易的事就是学习了,比吃饭还简单,因为我常常不知道吃什么。
@zhh-4096
这是我弟给我发的成绩单,刚好这周有考试。初三数学补了3个月的课,还是50多分,我是没想到连语文都这么差。这个成绩只能靠镇里最差的高中施舍才能读了。[允悲]
我现在除了每个月给我妈一点零花钱,其他的事我真的不会去操心了。我自己会不会结婚我也不知道,一切随缘。就算结婚了,我现在也完全可以接受没有孩子,养孩子太可怕了,如果自己的孩子是学渣,我都不知道怎么面对,甚至有可能怀疑是不是我亲生的。
像我弟这种学渣已经不算太烂了,我依然扶持了15年才让他踏踏实实去上个班,中间都想放弃过无数次。如果自己的亲生子女是学渣,得操心到死。就像我上屋邻居的两个儿子,35+了还得两个老人拼命给他们找老婆,就算找到老婆了,后面20年还有一堆事要操心。这样的事摊在我身上,我宁愿一辈子不结婚。
在乡下同样养三个小孩,你敢相信我们这代人比我们父辈们更累吗?我家另一个邻居比我小几岁,生了两个女儿一个儿子,为了给小孩上学不得不凑钱去城里买套房,跟我弟还是同一个小区。因为乡下方圆10公里内连个小学都没有了,以前还能穷养,种地能吃饱就行,小孩自己走路就能去上学,现在想穷养都不行了。
建了那么多房子卖不出去,就得提高城镇化率,把农民赶到城市买房。怎么赶呢?关闭乡下小学最有效。农民进城了,文化水平低,教育观念落后,生出的子女学渣居多,然后又有中考分流,把农民的子女扫人技校这种废物聚集地,出来社会了还是不能立足,最后还是得回农村。
在我认识的几千人里,读书不好的人绝大多数都是平庸的,没有什么擅长的,极少数嘴巴会说的还能帮别人卖点东西多拿点钱,剩下的就是进厂打螺丝去工地搬砖或者帮别人洗碗收拾餐桌,长得好看点当服务员。手艺人那也是万里挑一!//@四顾剑oooO :孩子不一定非得学习好啊,总有孩子擅长的
@zhh-4096
我现在除了每个月给我妈一点零花钱,其他的事我真的不会去操心了。我自己会不会结婚我也不知道,一切随缘。就算结婚了,我现在也完全可以接受没有孩子,养孩子太可怕了,如果自己的孩子是学渣,我都不知道怎么面对,甚至有可能怀疑是不是我亲生的。
喝鸡汤时告诉你每个孩子都有优点,需要像放牛班的春天中的智者来发现。如果都能找到这样的优点,这世界就不会是少数精英统治的世界了,绝大多数人的唯一用处就是繁殖,让人类的香火不灭。所以当你发现自己或自己的子女的价值只是为了人类繁殖时,能做的就是看开一点,想太多会累。
我所说的学渣是那种连最差的公办高中都考不上的学生。能看我微博的人我想多是高中毕业的吧,能考上高中你就已经超过一半的人了,再考上大专那就超过70%了。我对我侄女的期望很低的,仅仅是考上高中然后读个大专而已。若是只能读技校那就废了,就像村里的所有技校生一样,早早就嫁人,一年回来一次。
为人父母哪个不希望自己的子女读书好,我弟现在也能体会我爸当初对他是何等的失望了,初中都没读完,都是学渣,只不过当初的学渣变成了父亲。一个父亲说出对孩子不抱希望时,背后的付出和无奈谁懂?

我还是想说:真正会读书的人,只要学校没有差到离谱,对他的影响不大,我的小学和初中都是末端的,并不影响我考出好成绩;我小侄女的小学、大侄女的初中都是很不错的学校,依然无法让她们学好;我姐的女儿所在的小学还是前年刚成立的,但她读书的积极性却很高,作业自己主动做完,希望她能一直如此。
你看,这是我姐对她女儿学习的评价,跟我弟相比,真是一个天一个地。我姐弟都是学渣,所以孩子是不是读书的料,真的就是运气。我们家族的基因其实是很好的,我爸几兄弟的孩子基本都有一个很会读书,不用操心。

这几天都没买,蔚来都跌到4.6了,一季度是淡季,搞不好还能买到4块以下的蔚来。股市就是这么不理性,销量好转了,股价又要回到去年起飞前。一年只要重点关注一两个月就行,把握好时机买进一个多月就翻倍,就像去年一样。

我都加了她的微信好久了,她之前还偶尔跟我视频的,生病了一个人在家都不告诉我。才7岁啊,我7岁半才刚上小学一年级,都没有一个人去打过针,这个小姑娘将来不简单,我就喜欢这种自律、自我驱动、内心强大的小孩子。如果老天保证能让我也生出这种小孩,我很愿意结婚并且要生好几个。[笑cry]
@zhh-4096
我妈回乡下了,我姐的女儿刚上小学二年级,前段时间她甲流发烧,一个星期不去上学,一个人在家,白天一个人去打针。看到这样懂事的小孩我都想哭,我姐一年大半时间都在外省打工。
我姐出嫁时我们家都没要彩礼,我姐夫虽然不是赚大钱的人,但人品还是不错的,只要我妈一回乡下,休息日他就回去看看,家里也给他专门留了一间房。他父母不在了,老家的兄弟姐妹跟他的关系还不如我们这边好,回我们家的频率远远超过回他老家。可见家庭氛围好是多么重要,能深深影响一个人的幸福感。
我一直不明白为什么有高价彩礼这种事?我姐出嫁时没要彩礼,我弟娶老婆时彩礼不到一万,并且这种彩礼只是给女方买嫁妆的,迎亲那天女方家的人还会送过来。收几十万彩礼,不也是女儿跟他老公一起背,你还指望把男方父母的养老钱吸干。
如果我有女儿,对女婿的要求不会太高:人品好最重要,然后工作能力和赚钱能力至少跟我女儿持平,彩礼没要求。工作能力和赚钱能力太差真的不行,再好的婚姻也得有物质基础做保障。我堂妹是医生,无论是学历和工作都比她老公强不少,当初结婚时我就看不懂,现在生活不能说差,但也没有达到应有的水平。
我姐的女儿越来越独立后,我妈愿意呆在城里的时间就越来越少。跟我姐夫去镇上买了10只鸡崽,更加不想到城里了,哪怕只有一个人住,她就喜欢这种在乡下种菜养鸡的生活。平时让我回乡下住一个晚上我都难受,等我老了,我也不想回乡下,真的回不去了,田园生活并不美好,在我的记忆中就是手抓大粪和汗水。
前几天跟一个同事吃饭时还聊过这个话题,问我是否想去钓鱼?我说这人啊就是缺什么补什么,我是从农村出来的,我现在除了工作就想到别的城市走走看看,钓鱼抓鱼这种爱好在我乡下18年的时光里都已经用尽了,而这个老朋友在城里长大看腻了钢筋水泥,想体验田园生活,我俩的角色互换了。
@zhh-4096
四五十岁的中老年人还能有件喜欢的事做就不错了,钱不钱的无所谓。我一老朋友是技术高管,平时没项目时也闲,最近几个月新找了一份帮别人看鱼塘的工作,正好喜欢钓鱼,已经对赚钱没兴趣了。幸好我做数据库也乐在其中,赚钱很次要。这就是中老年人的快乐!
身边看到很多这种例子:养了几个女儿,20多点就早早嫁人,有的嫁到省内其他城市,有的甚至嫁到省外,一年也就春节回来一两天,有时闲太远了两年回来一趟,像我有个姑姑从小到现在我见她的次数不到5次。
也难怪别人说嫁出去的女儿泼出去的水,幸好我姐就嫁本地,没有变成远亲,姐弟之间还是能互相帮助有个照应。
我前任是独生女,虽然都是广西人,但不是同一个地级市,她父母也不同意她远嫁,哪怕我跟她说我可以在桂林买套房给她父母,最后也没能打动她父母。
上个月我表弟结婚,我才发现我有个小姨居然一家人都不来,我大姨虽然有钱,但依然没能处理好兄弟姐妹之间的事,脾气还是不够柔和。
在一个大家庭中,想家庭和睦,至少有一个人有一定的财力,然后又大方又不看重钱,脾气又好,又懂得解决家庭矛盾。我弟媳她父母离异,虽然跟我弟吵吵闹闹多年,但也没有离婚,确实是我这个大哥对他们夫妻俩太好了,比她亲哥还好。我姐夫那边的兄弟姐妹之间也有各种不可调和的矛盾,最后也是把我们这边当成他真正的家。
我大伯唯唯诺诺,又不幸娶了个泼妇,搞得我爸那一代人的关系也不好,我妈跟我大伯母老死不相往来。前几天我大伯母脑梗住院,我妈还特意叮嘱我不要去医院看了,让我弟去看一下有个代表就行,就怕我好心泛滥出钱帮我堂弟,还说当初我爸住院时他们可没出一分钱还看笑话。农村人的关系一到钱了就变得复杂。
我虽然没有结婚,但依然可以发表我对家庭对子女教育的各种看法。你也不用质疑我有没有这个能力,我压根就不会在乎你的质疑。我的看法都不是空中楼阁,都是亲身实践总结,就算还没有经历过,我现在是怎么想的,遇到没经历过的事也会按现在想的去做。
过去10年我接触过且聊过一段时间的女生超过15个,也就是平均每年1.5个,其中变成女朋友的有两个。我并没有躺平,也不是不婚主义者,我只是不将就而已,一个人也可以过得很舒服,恋爱结婚不能降低我现在的舒适度,一定要找到合适的人让生活可以变得更好我才会结婚。
我的直觉还是很准的,我主动了一次,一周过去了,对方也没有任何反应。年纪越大的女人越难聊,在体制内工作的大姑娘又是难上加难,如果她的大家族里也有很多在体制内工作,阻力更大,所以剩下的比其他行业的会更多。我两任前女友都在体制内工作,她们家族的人也有不少是体制内的。我太了解这个群体了。
@zhh-4096
加了相亲对象的微信后昨晚聊了一下,我的直觉告诉我没戏。
过去10年聊过的妹子少说也有15+个,其中30+岁的大姑娘和20+岁的小姑娘人数差不多各占一半。大姑娘普遍难聊,哪怕她是多年不见的初中同学,我第一个前任跟她正式谈时她也是大姑娘,在我印象里就没怎么主动过,更别说能提供什么情绪价值。大姑娘的普遍毛病就是爱端着,哪怕你的赚钱能力是她的10倍也依然会有一种我求她跟我聊天的感觉。
我遇到的这些小姑娘里就没有一个不好聊的,她们有好奇心有活力甚至还有一点慕强。我第二个前任就是20+,恋爱前和谈恋爱时的感受比第一任不知好了多少倍,以至于前段时间第一任想回来找我时被我无情拒绝了,甚至跟她直说我跟她过去的恋爱是痛苦居多,都算不上恋爱。
这就是为什么男人普遍喜欢找小姑娘的原因。
在我印象中,我之前还跟一个江苏的女生聊过一段时间,本科是数学专业,硕士读机器学习,长得比我还高,也是独生子女,我当时理性想了想真的太远了,若从江苏嫁到更落后的广西她的家人也不一定会同意。我也跟我家人提过一次,她们也不是很乐观,虽然最终都是我说的算,最后我还是放弃了,慢慢断了联系。
@zhh-4096
身边看到很多这种例子:养了几个女儿,20多点就早早嫁人,有的嫁到省内其他城市,有的甚至嫁到省外,一年也就春节回来一两天,有时闲太远了两年回来一趟,像我有个姑姑从小到现在我见她的次数不到5次。
也难怪别人说嫁出去的女儿泼出去的水,幸好我姐就嫁本地,没有变成远亲,姐弟之间还是能互相帮助有个照应。
我前任是独生女,虽然都是广西人,但不是同一个地级市,她父母也不同意她远嫁,哪怕我跟她说我可以在桂林买套房给她父母,最后也没能打动她父母。
我们整个大家族我爸那一辈是5兄弟,关系一般,会吵架,最恶劣时甚至打过几次架,就是因为我大伯这个人不管事。到我这一辈有9兄弟,我是大哥,我弟是二哥,截止今天关系都还可以,没有打过架,只小吵过几次,在全村算是很和睦的大家族了。只要男人能管得住老婆的嘴,兄弟之间的关系就不会太糟。
@zhh-4096
上个月我表弟结婚,我才发现我有个小姨居然一家人都不来,我大姨虽然有钱,但依然没能处理好兄弟姐妹之间的事,脾气还是不够柔和。
在一个大家庭中,想家庭和睦,至少有一个人有一定的财力,然后又大方又不看重钱,脾气又好,又懂得解决家庭矛盾。我弟媳她父母离异,虽然跟我弟吵吵闹闹多年,但也没有离婚,确实是我这个大哥对他们夫妻俩太好了,比她亲哥还好。我姐夫那边的兄弟姐妹之间也有各种不可调和的矛盾,最后也是把我们这边当成他真正的家。
农村跟城市的差异太大了,大到让我觉得像是两个不同社会。兄弟姐妹多,经济实力、文化水平、个人认知都差异很大,处理一些家事时,如果你总追求绝对的公平,最后就变得没有温情,特别是涉及到钱时,如果超过了某一方的承受能力,就会触发人性丑恶的一面,所以不要去考验人性,有能力的就吃点亏,能者多劳,并且还能让对方感觉到舒服。这就是老话说的:吃亏是福!