<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Liao Lile</title>
<link>https://liaolile.com/</link>
<atom:link href="https://liaolile.com/index.xml" rel="self" type="application/rss+xml"/>
<description>Liao Lile</description>
<generator>Wowchemy (https://wowchemy.com)</generator><language>zh-Hans</language><lastBuildDate>Sat, 01 Jun 2030 13:00:00 +0000</lastBuildDate>
<image>
<url>https://liaolile.com/media/icon_hu0b7a4cb9992c9ac0e91bd28ffd38dd00_9727_512x512_fill_lanczos_center_3.png</url>
<title>Liao Lile</title>
<link>https://liaolile.com/</link>
</image>
<item>
<title>Example Talk</title>
<link>https://liaolile.com/talk/example-talk/</link>
<pubDate>Sat, 01 Jun 2030 13:00:00 +0000</pubDate>
<guid>https://liaolile.com/talk/example-talk/</guid>
<description>&lt;div class="alert alert-note"&gt;
  &lt;div&gt;
    Click on the &lt;strong&gt;Slides&lt;/strong&gt; button above to view the built-in slides feature.
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Slides can be added in a few ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Create&lt;/strong&gt; slides using Wowchemy&amp;rsquo;s &lt;a href="https://wowchemy.com/docs/managing-content/#create-slides" target="_blank" rel="noopener"&gt;&lt;em&gt;Slides&lt;/em&gt;&lt;/a&gt; feature and link using &lt;code&gt;slides&lt;/code&gt; parameter in the front matter of the talk file&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Upload&lt;/strong&gt; an existing slide deck to &lt;code&gt;static/&lt;/code&gt; and link using &lt;code&gt;url_slides&lt;/code&gt; parameter in the front matter of the talk file&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Embed&lt;/strong&gt; your slides (e.g. Google Slides) or presentation video on this page using &lt;a href="https://wowchemy.com/docs/writing-markdown-latex/" target="_blank" rel="noopener"&gt;shortcodes&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Further event details, including &lt;a href="https://wowchemy.com/docs/writing-markdown-latex/" target="_blank" rel="noopener"&gt;page elements&lt;/a&gt; such as image galleries, can be added to the body of this page.&lt;/p&gt;
</description>
</item>
<item>
<title>41-女儿与我：岁月再走，而你依旧无忧无虑</title>
<link>https://liaolile.com/publication/41%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%B2%81%E6%9C%88%E5%86%8D%E8%B5%B0%E8%80%8C%E4%BD%A0%E4%BE%9D%E6%97%A7%E6%97%A0%E5%BF%A7%E6%97%A0%E8%99%91/</link>
<pubDate>Wed, 17 May 2023 13:19:23 +0000</pubDate>
<guid>https://liaolile.com/publication/41%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%B2%81%E6%9C%88%E5%86%8D%E8%B5%B0%E8%80%8C%E4%BD%A0%E4%BE%9D%E6%97%A7%E6%97%A0%E5%BF%A7%E6%97%A0%E8%99%91/</guid>
<description>&lt;p&gt;突然间看着你小时候的照片，想起了昨晚为了辅导课外舞蹈班作业在，自己还是按耐不住内心的焦虑，耐心已不断被你的表现冲破了。&lt;/p&gt;
&lt;p&gt;“我该不该这样对待你？”&lt;/p&gt;
&lt;p&gt;对于你无法完成或不明白为何坚持的事情，自认为陪着你一起练习，你不会耍赖。我总是秉着以身作则的教育理念，很多时候都语言暗示着让你教我，而不是我教你。可是，不断地拉锯练习中，我们互换了角色，从你主导变成了我主导，等我想再换过来的时候，你已经百般地不开心，而我无奈地讲着你听不懂的道理。好难，难于快乐教育，在我看来好像等不到你主动跟我提出要打卡，反而都是我追着你，这样更让你与舞蹈产生一种厌倦感。&lt;/p&gt;
&lt;p&gt;跳舞，本身是一件很身心愉悦的事情，为何就变成了这种“硝烟”，我百思不得其解。但当我看着你小时候的照片，我好似明白了。&lt;/p&gt;
&lt;p&gt;也许是你的不喜欢，是我的喜欢；也许是你的无忧，是我的顾虑。我真希望你可以向前无畏探索，无论无何我都应该成为你坚强的后盾，但这个盾一定也会破裂。所以，孩子，请你探索你想要的世界，而我可以做的，就是尽量营造你应该明白的因果关系。无论以后走的是坑坑洼洼还是平平坦坦，总会有我牵着你的手，重新走到你想要达到的目的地。&lt;/p&gt;
&lt;p&gt;但机会也许不多。&lt;/p&gt;
</description>
</item>
<item>
<title>40-女儿与我：你要第一个来接我放学</title>
<link>https://liaolile.com/publication/40%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%BD%A0%E8%A6%81%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%9D%A5%E6%8E%A5%E6%88%91%E6%94%BE%E5%AD%A6/</link>
<pubDate>Thu, 11 May 2023 13:24:28 +0000</pubDate>
<guid>https://liaolile.com/publication/40%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%BD%A0%E8%A6%81%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%9D%A5%E6%8E%A5%E6%88%91%E6%94%BE%E5%AD%A6/</guid>
<description>&lt;p&gt;“妈妈，你能今天接我放学吗？”自从小丫头上学以来，每每在电梯里或楼栋下都会问我这句话。&lt;/p&gt;
&lt;p&gt;“不行，妈妈还要上班”，话音刚落，小丫头立马熟练地说出了第二句，“那你送我到学校门口，好吗？”。有时候时间不赶是可以，但基本上除了下雨天或特殊情况，基本上都只是送到百般约定好的位置。而每次到了分手的地点，小丫头总会急忙说，“妈妈，你要早点回来啊，知道了吗？要坚持比爸爸早”，然后才摆摆小手。&lt;/p&gt;
&lt;p&gt;虽然可能无法实现，但还是答应了一声，“好”，便看着渐行渐远的小身影消失在我的视线里。&lt;/p&gt;
&lt;p&gt;有时候想想，每天都无法准点下班是为了什么呢？你说为了更好地多陪陪家人，但实际上陪家人的时间不多，只是创造了物质条件，可情感培养呢？也可能是说了太多“妈妈早点回来”的话语，让我很想平衡一把，或许偶尔请假去实现这个小小的恳请。&lt;/p&gt;
&lt;p&gt;正逢假期前，我知道机会来了，早早就心想着要不跟领导请假个半天吧。临近上午快下班，我去与领导交流工作的时候，顺便提了一下下午请假的事情，领导说下午没有什么安排，但今天需要把数据给出来。我明白，这意味着还需要一两个小时才可以下班。二话不说，把午饭时间省了，聚精会神地终于把数据算好并邮件给领导。&lt;/p&gt;
&lt;p&gt;有时候真的不逼自己一把，是会散漫惯了的，特别是工作时间久了会倦怠，就想着什么都往后拖一拖。内怀着约定，高效率完成了数据输出，邮件发送、关上电脑屏幕，瞬间整个人轻盈了许多 ， “小丫头，妈妈可以做到的”。也不知道从何时开始，所有的内驱力都不如小丫头给予的更强烈、更有效。&lt;/p&gt;
&lt;p&gt;我踏着轻快地步子回到了家中，用最快的速度囫囵吞枣地吃完一个苹果，便开始整理家里卫生，每半小时便看一下电子数字钟，“我可是要计算好时间，要在家长队伍中排在第一个”，小丫头上午是这么交代我的，我也答应了，作为家长绝不能食言。&lt;/p&gt;
&lt;p&gt;“竟然早了十分钟，不知道以什么方式接小丫头”，我心里默默地念叨，看着紧闭着的校门口外，已依稀可见不同姿势的家长，有骑着电动车等待的，有坐在石墩上望着的，有牵着岁数更小的孩子等待的……大多数不是爷爷奶奶，就是全职带娃娃的宝妈宝爸，不排除有类似我这种提前请假的。说起来还真的有点紧张，门关着我得站在哪里排队等着呢，略显得一点经验也没有。&lt;/p&gt;
&lt;p&gt;就在这时，东张西望的我从围栏外望见了小丫头，那机灵的小眼睛一下子也看到了我，“妈妈”，小丫头兴奋地跳了起来，迫不及待想跑过围栏跟我挥手。看得出来她很开心，只可惜我还是抢不过爷爷奶奶们，没排在第一，也生疏地递给老师接送卡（当时还在想是给接送卡流程是什么，还没等我大脑运转完，老师便呼喊了小丫头的名字。原来是点了名字小朋友才可以从队列中出来，然后家长把接送卡交到老师手上）。小丫头拍拍好朋友的肩膀，貌似自豪地告诉她们，“今天可是我妈妈来接我”，之后便自己拖着装午休被子的大袋子，一步步走向我面前。我也从来没发现，小丫头有这么大的劲儿。&lt;/p&gt;
&lt;p&gt;“妈妈，我今天好开心！”&lt;/p&gt;
&lt;p&gt;“为什么呀？”&lt;/p&gt;
&lt;p&gt;“因为上午妈妈送我去幼儿园，下午妈妈接我放学。”&lt;/p&gt;
&lt;p&gt;“妈妈也很开心！”&lt;/p&gt;
&lt;p&gt;“我今天吃了两碗炒饭，今天回去一定会长高的”……就这样，一路叽叽喳喳地沿着熟悉不过的路线走回家了。&lt;/p&gt;
</description>
</item>
<item>
<title>39-女儿与我：我想和你在一起</title>
<link>https://liaolile.com/publication/39%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%88%91%E6%83%B3%E5%92%8C%E4%BD%A0%E5%9C%A8%E4%B8%80%E8%B5%B7/</link>
<pubDate>Wed, 19 Apr 2023 23:52:36 +0000</pubDate>
<guid>https://liaolile.com/publication/39%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%88%91%E6%83%B3%E5%92%8C%E4%BD%A0%E5%9C%A8%E4%B8%80%E8%B5%B7/</guid>
<description>&lt;p&gt;曾经听大学的室友讲过，在小的时候，当我们生病时，特别特别想念身边的妈妈。那时候不太能理解，因为在我有记忆以来，好像并没有这么深刻体会过这句话的意思。然而有了小丫头后，我逐渐能理解，小朋友为什么在生病的时候这么想念自己的妈妈了。&lt;/p&gt;
&lt;p&gt;记得那一次，小丫头躺在床上望着急急忙忙回来的我，憋着嘴很委屈地哭着，好像在告诉我“妈妈，我生病了，你怎么还不回来照顾我”一般。殊不知，在办公室的我也着急得不行，恨不得马上、立刻回到家里照顾还烫呼呼、软绵绵的“小羊羔”。看着望着我的小丫头，内心里头瞬间被融化了，鼻子一酸，急忙响应伸手要抱抱的小丫头。&lt;/p&gt;
&lt;p&gt;也许真的就是想得到妈妈的安慰，哪怕是一个个抱抱，哪怕就只是倚靠着妈妈的肩膀，或者也就是简单的拉拉手，对于生着病的小丫头来说，心理上已经得到了治愈。所以，只要我可以陪伴，我就尽可能地抽出时间，如果错过了就觉得已经补不上这不可替代的空间了，也真的就是错过了就错过了。因为我总认为，等她长大了，也许就不再需要我的陪伴了。&lt;/p&gt;
&lt;p&gt;当然，这也许是孩子自我坚强或独立的心旅。我一直秉着这样的理念，给够足够的爱，才能从学会爱自己中爱别人。这里也提醒一下，并不是溺爱，溺爱是那种无条件给予，我还是有边界的。&lt;/p&gt;
&lt;p&gt;小孩子生来也不是勇敢无畏的，只有不断地尝试，知道了怎么去做也就不害怕了。但这种方式是温暖的，是让孩子知道无论怎么样，父母都是她的坚强后盾，并可以告诉她，以父母经历过的事情可能会有什么样的理解和选择，但不代表以父母的主意为主。毕竟人都不是不同的个体，只是一个家庭共同不断地磨合，在理念上相对来说比较容易接纳。&lt;/p&gt;
&lt;p&gt;这一次小丫头也如往常生病那样，也许是小小的身体再不断地练习与病毒或细菌做抗争，所以很需要妈妈的陪伴。从医院回来到午饭时间，都要拉着我的手，只要我稍微消失了会，她就不断地喊着“妈妈”，直到我答应了才放心。要不然，小眼睛都哭得跟核桃一样。我说要出下门去上班（因为没有带笔记本电脑，没办法在家里办公），小丫头就贴着我，还不断跟我说“妈妈，我要跟你在一起”。看着我真想感性地不上班了，但现实并不是这么如意。&lt;/p&gt;
&lt;p&gt;“你会用电脑打字吗？”&lt;/p&gt;
&lt;p&gt;小丫头点点头。&lt;/p&gt;
&lt;p&gt;“你会的话，妈妈才可以带你上班喔”，小丫头眼神很确定，“你带我去嘛，我就想跟你在一起”。&lt;/p&gt;
&lt;p&gt;说母亲和孩子心连心，对于母亲来说一点也不假。只要孩子翻来覆去睡不好，只要孩子说疼或不舒服，怎么的都要把原因找到，就算半夜不睡觉地焦急也要减少孩子的痛苦。&lt;/p&gt;
&lt;p&gt;我曾多少次半夜起来迷迷糊糊抓蚊子，就因为咬了小丫头无数个包，当然自己也不少包。现在都练就了抓蚊子高手。我曾多少次因为孩子生病，不断去搜索一般的护理方式，哪怕是身上起了什么不一样的东西，都不会放过，生怕自己出了什么疏漏，误了治疗的最佳时间。自己现在对一般感冒发烧的药是清清楚楚了，也不想再遇到什么新的药。以前药盒里都是过期了的创可贴，现在基本上都是常用的感冒药，有时真后悔自己不是护士或医生。&lt;/p&gt;
&lt;p&gt;上班的路上我一直想着，“妈妈也希望早点回来陪着你”。&lt;/p&gt;
&lt;p&gt;晚上回家后，当看到卧室的灯已熄灭了，确实有些失望，看来还是没能早些回家陪小丫头在睡前愉快地玩耍。看着熟睡的她，握着她的小手，说了声“妈妈回来了”。小丫头瞬间睁开眼睛看了下我，好似确认下自己听到的不是梦里。看清楚了，满意了，便扬起嘴角甜甜地入睡了。看着我真的很欣慰，原来小丫头一直都记得地在等妈妈，而妈妈也记得不让她等太久。&lt;/p&gt;
</description>
</item>
<item>
<title>38-女儿与我：鼓励才能事半功倍</title>
<link>https://liaolile.com/publication/38%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E9%BC%93%E5%8A%B1%E6%89%8D%E8%83%BD%E4%BA%8B%E5%8D%8A%E5%8A%9F%E5%80%8D/</link>
<pubDate>Sat, 22 Oct 2022 11:24:20 +0000</pubDate>
<guid>https://liaolile.com/publication/38%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E9%BC%93%E5%8A%B1%E6%89%8D%E8%83%BD%E4%BA%8B%E5%8D%8A%E5%8A%9F%E5%80%8D/</guid>
<description>&lt;p&gt;工作之余总是能听到同事在茶水间谈起辅导小孩学习的事情，往往以血压升高和不断研究解题思路而告终。说实在的，换做是我，估计也得捡捡在学校时学的语数外知识点了。&lt;/p&gt;
&lt;p&gt;先不说未来小学以上的教育陪伴了，眼下的我不知不觉就处于随波逐流的分水岭，对于幼儿教育如何应对？是跟大家一样报班学习？其实对于这一辈的父母来说，素质教育起跑线不算差的，毕竟小时候也是人手一门艺术课，只是坚持与否罢了。所以我想着对于几岁的幼儿来说，她就像是一张无限的白纸一样，后面能呈现青绿山水还是素描写真，就得看环境的烘培了，那最重要的就是家庭环境。但千万别偏激，若是你喜欢的课程，不是孩子的课程或想法，那请停止，因为孩子也是独立的个体，她需要有自己的选择。&lt;/p&gt;
&lt;p&gt;有时候想想，给小丫头学画画是因为我个人影响，还是她本身的兴趣呢？但从小的时候就喜欢乱涂乱画的她，也许也是因为我在她面前乱涂乱画，所以她觉得很熟悉。当然，画画本身也是我和小丫头建立信任桥梁的一项工程。&lt;/p&gt;
&lt;p&gt;无论选什么，学什么，需要倾听孩子的想法，比如允许她说不喜欢或不会。若孩子终于做到了，哪怕写了一个歪歪扭扭看起来都不知道是什么的字，也需要鼓励，只是鼓励中还得带上引导如何做才是对的。毕竟孩子怎么清楚她为什么要上学，为什么要学习，为什么要写字，一切都还没有搞明白为什么就已经上路了。懵懵懂懂，天真烂漫，好在没有深究所有的为什么，好在孩子对于除了玩耍以外的事物，都不算重要。&lt;/p&gt;
&lt;p&gt;“小丫头，我们好久都没有一起学习写字了，今天可以跟妈妈一起练练字吗？”我拉着刚蹦哒完的小手。&lt;/p&gt;
&lt;p&gt;“好！”&lt;/p&gt;
&lt;p&gt;“那我们今天练习哪个字呢？”我很想按照练字本一页页往下练习，但觉得由孩子自己选择，无论后面过程或结果如何，起码起步是发自内心的。&lt;/p&gt;
&lt;p&gt;“写这个十字吧，我会写”，小丫头像个大人一般对我说，斩钉截铁。&lt;/p&gt;
&lt;p&gt;刚开始我跟她描述着怎么写，拿着笔让她看着我怎么写，然后对于她写不对的地方，停下来再指导。可是只是口头指导作用不大，毕竟小丫头不明白为什么必须这么写，而且过程枯燥，写了一两行她就有点不愿意了。正想着如何是好，突然我看到练字本下面有三个表情，分别为“加油”、“不错”、“真棒”，那不如换一种方式也许更有效、有趣。&lt;/p&gt;
&lt;p&gt;“小丫头，我们玩一个游戏。你写完一行，妈妈对于写得好的在上面打个勾，这一页结束了，我们一起数数多少个勾，20个勾咱们就获得一个真棒的笑脸”，说完指着练字本页尾的三个笑脸。&lt;/p&gt;
&lt;p&gt;小丫头两眼放光，“好，我要真棒的笑脸！”，正合我意。&lt;/p&gt;
&lt;p&gt;小丫头每写一行我评价哪个字写得好，为什么写得好，然后打一个勾。对于写得不好的字，我也说明了为什么没获得一个勾，把写不好的地方画个圈圈。就这样，一转眼写完了，到了一起数数的环节了。每数一个勾，我都可以看出小丫头那期待的眼神，越来越觉得自己是做对了。&lt;/p&gt;
&lt;p&gt;虽然没有达到预期的20个勾，但已经接近了，而且过程中我没有“上火”，小丫头也没有委屈，很愉快的完成了一次学习，而且还易于下一次的配合，真是良性循环的开始。所以，有时候站在孩子的角度去有效激励，是一种事半功倍的方法，同时，静下心来你会发现，原来也是自己学习的一次次机会。&lt;/p&gt;
</description>
</item>
<item>
<title>37-女儿与我：长得还不够高的小朋友</title>
<link>https://liaolile.com/publication/37%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E9%95%BF%E5%BE%97%E8%BF%98%E4%B8%8D%E5%A4%9F%E9%AB%98%E7%9A%84%E5%B0%8F%E6%9C%8B%E5%8F%8B/</link>
<pubDate>Wed, 14 Sep 2022 23:23:26 +0000</pubDate>
<guid>https://liaolile.com/publication/37%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E9%95%BF%E5%BE%97%E8%BF%98%E4%B8%8D%E5%A4%9F%E9%AB%98%E7%9A%84%E5%B0%8F%E6%9C%8B%E5%8F%8B/</guid>
<description>&lt;blockquote&gt;
&lt;p&gt;从前有一个长得还不这么高的小朋友，没有洗手池这么好玩，所以每次都需要拿着小板凳站在洗手池边洗手、刷牙、洗脸，以及梳头发。
这个小朋友每天都喜欢跑到房间里的一扇门处，量着自己的身高，每次都说自己又长高了一点点。但其实这个量身高的尺子贴得有点点不同，从20厘米一直到120厘米之后，就直接变成了170厘米，总之数字贴得都不是这么准确。但是这个小朋友每天都满怀着期待，期待着自己又长高了一点点。可是这位小朋友一点也不满意地说，“我怎么还没有长大两米呀，总是到这个190呀”。
这个长得不这么高的小朋友，喜欢睡觉前抱着“棉花团”和新鲜的玩具，同时，还不断地跟妈妈说，“妈妈，可以给我讲一个小朋友衣服上的水变干了的故事吗？”……&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;以上就是今天小丫头让我即兴发挥的故事内容，我真的是天马行空、无任何逻辑地讲完了一则短短的故事。&lt;/p&gt;
</description>
</item>
<item>
<title>36-女儿与我：溃疡</title>
<link>https://liaolile.com/publication/36%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%BA%83%E7%96%A1/</link>
<pubDate>Mon, 12 Sep 2022 12:15:10 +0000</pubDate>
<guid>https://liaolile.com/publication/36%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%BA%83%E7%96%A1/</guid>
<description>&lt;p&gt;这假期也许是放任小丫头吃饼干或者零食，也没有顾上她是不是及时喝水了，所以第二天起床小丫头对着我说，“妈妈，这里有点疼”，用小手碰了碰嘴唇的地方。我还处于迷糊状态，说实在的，只要一遇到假期我感觉可以睡足整个假期。我并没有仔细瞧，以为只是晚上开空调，导致嘴巴有些干。&lt;/p&gt;
&lt;p&gt;等到起床洗漱的时候，我替她刷牙的时候，才发现原来她嘴里长了颗溃疡。这可麻烦了，要知道大人得了这个也受不了，吃一些刺激的食物，比如辣、咸的，那痛的滋味不是一点点。&lt;/p&gt;
&lt;p&gt;我还在想，小丫头是怎么获得这一枚溃疡的，想来想去也只有一开始的原因——少喝水了。得了，这几天吃东西有得磨性子的了。&lt;/p&gt;
&lt;p&gt;“妈妈，疼，太疼了”，正在吃饭的小丫头，才咽下一口就对我说，直接疼到眼泪直流，我知道小丫头是真的疼。&lt;/p&gt;
&lt;p&gt;我知道疼的滋味，但饭还是得吃，要不然没办法补充微量维生素，一样不能快速愈合。&lt;/p&gt;
</description>
</item>
<item>
<title>35-女儿与我：抱着日历</title>
<link>https://liaolile.com/publication/35%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%8A%B1%E7%9D%80%E6%97%A5%E5%8E%86/</link>
<pubDate>Sun, 11 Sep 2022 12:15:10 +0000</pubDate>
<guid>https://liaolile.com/publication/35%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%8A%B1%E7%9D%80%E6%97%A5%E5%8E%86/</guid>
<description>&lt;p&gt;自从小丫头认识了日期，知道每一天代表什么意思后，每次讲其今天是什么日子的时候，小丫头都会跑到床边的书架上，拿起年日历，用小小的手指指着，“妈妈，你看，今天是红色的，今天是周末吗？”。&lt;/p&gt;
&lt;p&gt;什么时候是特殊的日子，什么时候是可以有妈妈陪伴的日子，全然都被她在日历上看清了。&lt;/p&gt;
</description>
</item>
<item>
<title>34-女儿与我：卡片</title>
<link>https://liaolile.com/publication/34%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%8D%A1%E7%89%87/</link>
<pubDate>Sat, 10 Sep 2022 12:15:10 +0000</pubDate>
<guid>https://liaolile.com/publication/34%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%8D%A1%E7%89%87/</guid>
<description>&lt;p&gt;前一天就买好了小卡片，想着给小丫头写些什么比较好，但想着写得太多，现在也不一定完全认识，想好好久，便睡了。&lt;/p&gt;
&lt;p&gt;今早醒来，看着在身边的小丫头还在梦乡中，必须赶紧在卡片上写好。等她醒来之后，便可以给她一个惊喜。果真被我弄醒的小丫头，看到手里的粉色卡片，搓着还迷糊的眼睛，对我说“妈妈，这是什么”。&lt;/p&gt;
&lt;p&gt;“你看，这上面写的是不是祝我的小丫头呀……”我对这卡片一字一句地对着小丫头说。字数不多，卡片不大，但我想写下的日期足以留作往后的想念。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;祝我的小丫头：生日快乐！健康成长！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;小丫头也许还不能明白字里行间的意思，只知道今天是周末，妈妈会陪着她；只知道今天可以吃蛋糕，她自己选的小黄鸭蛋糕；只知道今天可以出去玩，玩她的娃娃机和电动车。&lt;/p&gt;
&lt;p&gt;一转眼间，小丫头也成为一个有自己脾气，会不停要求你讲故事的小朋友。&lt;/p&gt;
</description>
</item>
<item>
<title>33-女儿与我：她生气了</title>
<link>https://liaolile.com/publication/33%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%A5%B9%E7%94%9F%E6%B0%94%E4%BA%86/</link>
<pubDate>Sun, 04 Sep 2022 12:15:10 +0000</pubDate>
<guid>https://liaolile.com/publication/33%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%A5%B9%E7%94%9F%E6%B0%94%E4%BA%86/</guid>
<description>&lt;p&gt;“妈妈，躺下，躺下，再陪我躺下。”小丫头每次醒来都会这么对我说，只是如果告诉她今天不是周末的话，她会要求躺四分钟（有点好奇为何只提“四分钟”）。&lt;/p&gt;
&lt;p&gt;现在小丫头算是有点力气了，我不躺下她还不乐意，一定要起来将我放倒。但如果我不听从她的，她便会生气，独自一人坐在床边撇着小嘴，想哭想哭的样子。&lt;/p&gt;
</description>
</item>
<item>
<title>32-女儿与我：日常话包子</title>
<link>https://liaolile.com/publication/32%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%97%A5%E5%B8%B8%E8%AF%9D%E5%8C%85%E5%AD%90/</link>
<pubDate>Wed, 31 Aug 2022 12:15:10 +0000</pubDate>
<guid>https://liaolile.com/publication/32%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%97%A5%E5%B8%B8%E8%AF%9D%E5%8C%85%E5%AD%90/</guid>
<description>&lt;p&gt;“妈妈，你给我讲个叮当猫吃小鱼的故事吧。”&lt;/p&gt;
&lt;p&gt;“妈妈，你不要这样拿着，要像我这样……对，这样就对啦，你肯定很快就能学会。”&lt;/p&gt;
&lt;p&gt;“妈妈，我都说了，你看了吧，被你弄坏了吧。”&lt;/p&gt;
&lt;p&gt;不知道从何开始，小丫头就是这般与我交流。也不知道是哪一块基因链条影响的，小丫头真的太喜欢说话了。有时候自己一个人玩游戏，可以听到她对着玩具进行角色扮演，玩半个小时，就能说半个小时的故事，自编自导自演。&lt;/p&gt;
&lt;p&gt;只要她醒着，就满屋子回荡着她童真的话语，就连在饭桌上也不忘打开话匣子。记得有一个周末午饭时间，小丫头一如既往说了很多话，当我看着她示意吃饭不可以说话的时候，她来了一句，“爸爸，妈妈说吃饭不可以说话，所以我们不能说话”，说完用小手指比在嘴巴上。我以为奏效了，结果，刚吃下一口饭，又开始哔哩吧啦。&lt;/p&gt;
&lt;p&gt;是因为我把话匣子作为祖传，一并让小丫头打开了吗？确实我在家说话也并不是特别多。&lt;/p&gt;
&lt;p&gt;但有一点，我觉得她特别像我，那就是对人脸的识别能力（这么说有点像AI，不过确实AI技术在学习我们大脑分析的能力），或者说是认人吧。&lt;/p&gt;
</description>
</item>
<item>
<title>31-女儿与我：学会交流</title>
<link>https://liaolile.com/publication/31%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%AD%A6%E4%BC%9A%E4%BA%A4%E6%B5%81/</link>
<pubDate>Thu, 25 Aug 2022 12:15:10 +0000</pubDate>
<guid>https://liaolile.com/publication/31%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%AD%A6%E4%BC%9A%E4%BA%A4%E6%B5%81/</guid>
<description>&lt;p&gt;小丫头已经到了有自己思维逻辑和语言逻辑的阶段，从之前开启十万个为什么关卡以来，我就知道，小丫头的伶牙俐齿是不能随便敷衍的。随着她词汇量的剧增，很快，我即将面临相互合理交流的考验。&lt;/p&gt;
&lt;p&gt;“小丫头，这是你今天让妈妈买给你的彩虹蛋糕，好吃吗？”&lt;/p&gt;
&lt;p&gt;“好吃！可是我想吃那个冰袋”，小丫头因为看到我把装蛋糕的冰袋丢到了门口，顺口说了一句。我一下子没有反应过来，直接回了句，“冰袋不能吃的，那个是用来保温的，让蛋糕不会那么快融化”。&lt;/p&gt;
&lt;p&gt;等我关上门抬起头看着她时，才恍然大悟，原来小丫头说的不是冰袋，而是冰棒——她心心念着的小白兔牛奶味冰棒。&lt;/p&gt;
&lt;p&gt;刚开始我并没有直接同意给她吃，毕竟天气也不算热到非吃不可的地步，但小丫头不放弃的精神无时无刻不在线。&lt;/p&gt;
&lt;p&gt;“妈妈，我能吃冰棒吗”，小丫头靠着门边望着我说。&lt;/p&gt;
&lt;p&gt;“妈妈要是说不行，怎么办？”我边整理着洗漱用品边说道。&lt;/p&gt;
&lt;p&gt;“那就改天再吃呗”，一句听起来像个小大人的话语，一下子把我逗乐了。&lt;/p&gt;
&lt;p&gt;“那行，一会妈妈给你拿一根冰棒，但是只能吃一半，不能吃太多了。”&lt;/p&gt;
&lt;p&gt;这只是其中一角，对于生气中的小丫头，没想到也是很容易沟通交流的。只是一开始，她并不会听你的，而且还红着小眼睛看着你，时刻准备着嚎啕大哭或者委屈地哭。&lt;/p&gt;
&lt;p&gt;“小丫头，要去洗澡了，你已经看了好多集了”，我拿着她的浴巾和毛巾、睡衣准备引导她去洗澡。&lt;/p&gt;
&lt;p&gt;“再看一集”，小丫头盯着手机。&lt;/p&gt;
&lt;p&gt;“不行，你已经答应妈妈看了一集要去洗澡”，我稍微停顿了下便把手机拿到自己的手上，并关闭手机上的应用。&lt;/p&gt;
&lt;p&gt;“不行！”小丫头大声喊到，略显生气，之后便说，“讨厌！”。看着她的表现，我知道她已经在生气了，立马蹲下来看着她。&lt;/p&gt;
&lt;p&gt;“为什么不行呢，妈妈是不是之前就跟你说好了，看了一集咱们就去洗澡。可是小丫头每一次都说再看一集，你说行不行呢？”&lt;/p&gt;
&lt;p&gt;小丫头撇着嘴，泪眼汪汪，“不行！我不要！”，我知道她还是不能明白。&lt;/p&gt;
&lt;p&gt;“那如果小丫头每次都不断提出看一集，那洗澡就会变得很晚。我们为什么不能先洗澡再床上玩呢？”&lt;/p&gt;
&lt;p&gt;“不行”，这次语气稍微弱了点。&lt;/p&gt;
&lt;p&gt;“妈妈知道小丫头在生气，但你看，你想再看一集的时候，妈妈是这样生气的吗？有没有大声吼呀？”小丫头没有说话，但我知道这样交流对她来说应该是有效的。&lt;/p&gt;
&lt;p&gt;这一过程中我会让她坐在我的怀里，温柔地说，如果很严厉也许事情就不会这么顺利扭转到去洗澡。也有可能以后小丫头也会学着我对我大声训斥，所以我想我这么交流也是相对来说比较合适的。回头想想，也许第一步我拿过手机的方式有些不对，否则也不会激起她自我为中心的本能了。&lt;/p&gt;
</description>
</item>
<item>
<title>30-女儿与我：回家</title>
<link>https://liaolile.com/publication/30%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%9B%9E%E5%AE%B6/</link>
<pubDate>Sun, 21 Aug 2022 12:15:10 +0000</pubDate>
<guid>https://liaolile.com/publication/30%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%9B%9E%E5%AE%B6/</guid>
<description>&lt;p&gt;五周前的不舍，换成了这周末的依恋。五周前因为我工作的缘故，小丫头跟着我的母亲回了趟老家；五周后的周末，按照约定好的时间，一路狂奔，就为了将小丫头带回。当然，我也是想回去看看我熟悉的“家”。&lt;/p&gt;
&lt;p&gt;工作后，没有了学生时代的寒暑假，变成了十一或春节长假，每次回家也只是短短的一周时间；成家后，因为各种原因安排不过来，一年两次的短假也变成了春节里仅有的三天。&lt;/p&gt;
&lt;p&gt;姐姐的房间因为我家庭的缘故（因为有了小丫头，跟着母亲在一个大一点的房间比较合适），变成了我每次回家居住的房间。而我的榻榻米小房间，也就暂时变成姐姐落脚之处。&lt;/p&gt;
&lt;p&gt;每次从高铁站出站，总能看到亲爱的父亲探着头在看一拥而来的人群，看看哪个才是他的宝贝女儿们。我们还是那样，每次第一眼看到我的父亲，就急忙举起手挥来挥去，示意着我们的到来。而我的母亲，则是在家里忙着铺床、准备好洗漱用品，还有干净的拖鞋。&lt;/p&gt;
&lt;p&gt;这一次，除了等待着我的父亲母亲，还有我可爱的小丫头。当我出现在门口的那一刹那，小丫头兴奋地在原地跺脚，一直在说着“妈妈”。看着小丫头，我总觉得她还是这么的小巧，跟视频里的感觉不一样。不知道是五周没有天天瞧见了，还是在车上太累没休息好导致的眼神不对，总觉得有点不适应又非常熟悉。&lt;/p&gt;
&lt;p&gt;待可以坐在家里的沙发时，小丫头拉着我的手，一直在跟我讲自己正在做什么。看着小丫头叽里呱啦地说着，我已经顾不上她说的具体内容了，只想好好看着她。晚上睡前，小丫头还会跟我说“妈妈，今天是周末吗”，这是多么亲切的一句话，因为之前每天睡前都会问我，每次都以期待的眼神看着我，多么渴望我的回答是“对，今天是周末”。因为这样妈妈就可以陪她欢乐地玩耍，无论做什么，都可以跟着妈妈在一起。&lt;/p&gt;
&lt;p&gt;看着小丫头五周以来的成长，我以为她的伶牙俐齿也不完全是天赋，还有我父亲和母亲的功劳。她能够在任意时刻说着自己的想法，也因为给予了她足够的自由。&lt;/p&gt;
</description>
</item>
<item>
<title>备忘录</title>
<link>https://liaolile.com/post/tech/base/0/%E5%A4%87%E5%BF%98%E5%BD%95/</link>
<pubDate>Wed, 10 Aug 2022 12:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/base/0/%E5%A4%87%E5%BF%98%E5%BD%95/</guid>
<description>&lt;p&gt;&lt;strong&gt;好记性不如烂笔头。&lt;/strong&gt;&lt;/p&gt;
&lt;div class="hugo-encryptor-container"&gt;
  &lt;div class="hugo-encryptor-prompt"&gt;
    
      &lt;p&gt;文章的部分内容被密码保护：&lt;/p&gt;
    
  &lt;/div&gt;
  &lt;div class="hugo-encryptor-form"&gt;
    &lt;input
      class="hugo-encryptor-input"
      placeholder='请输入密码'
    /&gt;
    &lt;input
      class="hugo-encryptor-button"
      type="button"
      value='点击验证'
      onclick="_click_handler(this)"
    /&gt;
  &lt;/div&gt;
  &lt;div
    class="hugo-encryptor-cipher-text"
    data-password="leland"
    style="display: none;"
  &gt;
    &lt;span style="display: none;"&gt;--- DON'T MODIFY THIS LINE ---&lt;/span&gt;
    &lt;p&gt;1、再多申请一个台式机电脑，专用于代码应用相关&lt;/p&gt;
&lt;p&gt;2、参考相关内容进行gitlog生成changeme.log&lt;/p&gt;
&lt;p&gt;gitlog.sh &lt;a href="https://www.cnblogs.com/linkstar/p/10274943.html" target="_blank" rel="noopener"&gt;利用shell脚本生成CHANGELOG.md（包含git提交规范） - LinkinStar - 博客园 (cnblogs.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/LinkinStars/springBootTemplate" target="_blank" rel="noopener"&gt;LinkinStars/springBootTemplate: SpringBoot项目模版 (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Grid Router架构约束&lt;/p&gt;
&lt;p&gt;1、关于迁移涉及：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;GridRouter集群扩节点后怎么把nginx节点挂载到lvs，同时GridRouter扩集群的时候如何把新的域名注册到lvs上；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关于Grid节点扩容，GridRouter提供变更能力到对应的nginx upstream的node节点；扩Grid的时候类似与新增一个Grid upstream和新增Route；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2、关于测试效率的提升&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于验证可以通过脚本进行，脚本中就是检索日志，然后针对关键字进行识别判断，避免记忆；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3、关于Route去压缩，需要写代码开关主干配置（1-进行升级，2-进行数据清理，default 0-什么都不做），进行mds数据的升级（验证），避免手动操作写数据；&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;写数据前做检查，确保id无重复；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;数据升级，复制一份新的数据；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;数据验证，打印对应的日志；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;​	key：/r/servie_name/id&lt;/p&gt;
&lt;p&gt;​	value: gxxx1|tdomain&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新版本数据按照已有的格式进行入库存储；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4、关于cellid映射解耦&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;upstream名字怎么配置进入到数据库存储（提供界面）长期，短期基于数据库入库变更；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;新的upstream名字设计使用简短的id信息唯一信息，nginx.conf文件无需人看；upstream的唯一的displayName要带入到对应的boltdb，仅用于需要做日志记录的场景，从id -&amp;gt; upstream name&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;复制变更一份：regionLb的upstream变更（手动）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;删除废弃的upstream信息（手动）；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;api设计需要细分Http返回码&lt;/p&gt;
&lt;p&gt;-201 Created&lt;/p&gt;
&lt;p&gt;验证的过程&lt;/p&gt;
&lt;p&gt;1、reload过程中nginx是否有请求丢失&lt;/p&gt;

  &lt;/div&gt;
&lt;/div&gt;</description>
</item>
<item>
<title>29-女儿与我：视频里的她</title>
<link>https://liaolile.com/publication/29%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%A7%86%E9%A2%91%E9%87%8C%E7%9A%84%E5%A5%B9/</link>
<pubDate>Sun, 31 Jul 2022 12:15:10 +0000</pubDate>
<guid>https://liaolile.com/publication/29%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%A7%86%E9%A2%91%E9%87%8C%E7%9A%84%E5%A5%B9/</guid>
<description>&lt;p&gt;距离小丫头跟我母亲回老家到现在，也有两周了。这两周内每天的事情让我停不下来去想着，我和小丫头分开的日子是第几天。&lt;/p&gt;
&lt;p&gt;直到母亲发来的录像，以及视频通话中，我发现小丫头真的长大了，以至于我看到了一个更独立自理、因思念父母而表达的小丫头。何止两周呐，在个人成长上是又上了一个台阶。&lt;/p&gt;
&lt;p&gt;记得那天，我点了小龙虾的外卖作为晚饭，边开着边接通与小丫头通话的视频。手机那头的她，刚起床，母亲给她切了半边小西瓜，小丫头正用着小勺子认真地挖西瓜吃，见着视频里的我，还不忘开心地说着，“妈妈，我在吃西瓜碗”。我知道，头一次吃西瓜碗的时候，还是她跟我一起在家里的餐桌上吃，吃得满衣裳都是西瓜汁。当时的她还不会将西瓜子挖出去，现在却熟练轻巧。&lt;/p&gt;
&lt;p&gt;“小龙虾是什么颜色的呀，小丫头？”&lt;/p&gt;
&lt;p&gt;“红色，我的西瓜也是红色的。我的衣服也是红色的，你看，妈妈。”&lt;/p&gt;
&lt;p&gt;吃着聊着，小丫头停下了手中的勺子，换成驮着腮帮子，嘟着嘴巴对我说，“妈妈，我好想你呀！你什么时候来接我呢？我们这里好远的，你要做火车。”&lt;/p&gt;
&lt;p&gt;这句话一说，我顿时有点不知道如何回答，本因觉得自己会快速抢答“妈妈马上去接你”。鼻子有点酸酸的，“妈妈很快就去接你了，下周还有工作上的事情，小丫头还需要跟姥姥待一下哟”。&lt;/p&gt;
&lt;p&gt;“我吃完西瓜碗，就去你那边，好吗？”&lt;/p&gt;
&lt;p&gt;“好”，我只能这样答应她。&lt;/p&gt;
&lt;p&gt;说不想念那一定是假的，但所有都是为了让自己有更多的精力去应对工作上的调整，也为了自己以后更有能力陪伴着小丫头。当然，最主要的是，我母亲也有点累了，有父亲搭把手也许会轻松一点。&lt;/p&gt;
&lt;p&gt;此后，每几天视频，只要小丫头没有在专注玩玩具，她都会说“妈妈，我好想你”，妈妈又何尝不是呢。看着你已经有自己的想法、自己的小动作，可以顺畅地表达自己的心思，真的很是欣慰。不知道是不是长高了、变重了，下一次妈妈去接你的时候，会不会抱不动了……&lt;/p&gt;
</description>
</item>
<item>
<title>28-女儿与我：我们的影子</title>
<link>https://liaolile.com/publication/28%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%88%91%E4%BB%AC%E7%9A%84%E5%BD%B1%E5%AD%90/</link>
<pubDate>Fri, 08 Jul 2022 23:05:10 +0000</pubDate>
<guid>https://liaolile.com/publication/28%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%88%91%E4%BB%AC%E7%9A%84%E5%BD%B1%E5%AD%90/</guid>
<description>&lt;p&gt;开启周末的前期，最惬意的就是：天没黑，人到家，陪着我的小丫头一起散步、玩耍。是那段可以望着傍晚天空云朵的时候，是那段经历过就不会再重来的时刻。&lt;/p&gt;
&lt;p&gt;踏进家门的那刻，总会听到劈哩叭啦的脚步声由远及近，那是小丫头光着脚丫子向我奔来。&lt;/p&gt;
&lt;p&gt;已经习惯在公司将就着吃工作餐，也是想着从下班赶地铁回家，最早的也要六点半七点，也省得家里再准备饭菜了，也辛苦了自己的父母，回来闻闻家的味道就好了。&lt;/p&gt;
&lt;p&gt;急忙喝了一碗汤，就想着带着小丫头下楼做个核酸，因为明天外出需要使用。顺便让她在楼下玩一会，毕竟很少陪着她晚饭后在小区楼下玩耍，我也算是切换为母亲的角色，好好陪伴她最期盼的周末。&lt;/p&gt;
&lt;p&gt;“妈妈一会带你去核酸，好不好？”我拿着母亲煲好的一碗汤，望着在客厅正在玩的小丫头。&lt;/p&gt;
&lt;p&gt;“我不要去核酸，我不要出去，我就想在家里玩”，小丫头嘟着嘴对我说道。&lt;/p&gt;
&lt;p&gt;“那我们不去做核酸，去楼下玩，好吗？”，小丫头眼睛一亮，“我要去”，可分明刚刚还说不想下楼玩耍，孩子的心思真是单纯而简单。&lt;/p&gt;
&lt;p&gt;在电梯里，正巧有个一岁多的小朋友跟着爸爸一起乘上了。由于楼层比较高，过程中被众人分开了，一个在左下角，一个在右上角。小朋友被高于他海拔很多的人墙挡住了视线，他看不到爸爸了，失去了安全感而嚎啕大哭。看着这位父亲因为没办法穿越人墙过去，在角落里一直在说，“爸爸在这里，宝宝不要哭”。我也是着急，将手里的垃圾放在了电梯地面，让小丫头帮我拿着手机，以便于我可以将小朋友抱起递给这位父亲。但小朋友并没有接受我的善意，想来也是，毕竟我是陌生人，所以也就作罢了，一起等着到达到一楼打开电梯门的瞬间。&lt;/p&gt;
&lt;p&gt;小丫头看着这场景，显然内心也害怕了起来，伸出双手示意让我抱，刚好这时电梯门也开了，我牵着小丫头的手走出了电梯门口。想着刚刚她比较害怕，就一直牵着比较好，结果走到放垃圾桶的小路口，小丫头停住脚步，“你去丢垃圾吧，我一个人站在这里不害怕的，我也不会哭”。这丫头真有意思，刚还在电梯里害怕想要我抱，现在就这么勇敢。我快速将垃圾处理好，时不时转身看着在路灯下站着等我的小丫头，真的是一动不动地站着等着我，被灯光映射的身形镶上了一道银白色的边，闪闪发亮。&lt;/p&gt;
&lt;p&gt;我连忙跑去，蹲下来抱起我的小丫头，“你看，我说我没有哭吧”。&lt;/p&gt;
&lt;p&gt;搁着口罩真想亲她一口，“小丫头长大了，会自己等妈妈了”。正走向小区核酸检测点，小丫头可能发现有点不对劲，让我停下脚步并望着我说，“我们这是去哪里呀？不是要去玩吗？”&lt;/p&gt;
&lt;p&gt;“我们先去核酸，再去玩，好不好？”&lt;/p&gt;
&lt;p&gt;“我不想去做核酸”，不知道为何她这么不愿意去，我换了一个说法，“那我们一起去看看人多不多，人多的话，就不去了，好吗？”&lt;/p&gt;
&lt;p&gt;“好吧”，听上去有点勉强，但这种说法她还是接受了，那就继续将她放下来并牵着她的小手，本身目的就是去楼下做核酸，避免第二天无法出门。&lt;/p&gt;
&lt;p&gt;我们两个人的影子就在小区的路灯下，摇摇晃晃地走着，影子里小丫头的小手还是那么可爱。&lt;/p&gt;
</description>
</item>
<item>
<title>27-女儿与我：角色扮演</title>
<link>https://liaolile.com/publication/27%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%A7%92%E8%89%B2%E6%89%AE%E6%BC%94/</link>
<pubDate>Thu, 07 Jul 2022 23:04:18 +0000</pubDate>
<guid>https://liaolile.com/publication/27%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%A7%92%E8%89%B2%E6%89%AE%E6%BC%94/</guid>
<description>&lt;p&gt;角色扮演游戏有助于孩子的成长，主要在于思维上的成长、责任心的感受，以及权力的体验。作为父母，做惯了为孩子考虑任何一件事，总觉得是一种与生俱来责任感，但实际上让孩子偶尔切换角色，感受“父母的威力”，也许更能让孩子思维拓宽和掌控情绪。&lt;/p&gt;
&lt;p&gt;我和小丫头就喜欢玩角色扮演，让她扮演妈妈，我则是她的宝宝。&lt;/p&gt;
&lt;p&gt;“小丫头，现在你是妈妈，我是你的宝宝。现在是睡觉时间，妈妈是不是要带宝宝去刷牙呀？”&lt;/p&gt;
&lt;p&gt;小丫头一下子就明白开启了角色扮演游戏模式，“好，我带你去”。到了洗漱间，她很细心告诉我，“你要这么刷，这样牙齿就不会黑了”。听着这一句句说的，看着这神色，分明跟我平时是一个模子出来的。所以下一次我得好好说，要不然就跟照镜子一样回放妈妈的所作所为。&lt;/p&gt;
</description>
</item>
<item>
<title>26-女儿与我：弹力球</title>
<link>https://liaolile.com/publication/26%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%BC%B9%E5%8A%9B%E7%90%83/</link>
<pubDate>Sun, 03 Jul 2022 18:17:10 +0000</pubDate>
<guid>https://liaolile.com/publication/26%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%BC%B9%E5%8A%9B%E7%90%83/</guid>
<description>&lt;p&gt;因上一次去学画画前，在商场里多逗留了一个多小时，姨妈买了Meland的游戏币，让小丫头在娱乐设施里玩了半小时左右，还有许多币没有用完，又怕可惜了。这一次，打算提前半小时，让小丫头玩一下，毕竟周末前也答应过她要一起玩开车等游戏的。&lt;/p&gt;
&lt;p&gt;正巧遇上了台风“暹芭（xiān bā）”，但好在没有“山竹”猛烈，答应了便做好行程安排。&lt;/p&gt;
&lt;p&gt;专车将我们安全送到目的地，一路上还是雨水不断，但上下车全程都是抱着小丫头，对于她而言，坐上玩具车已经是迫不及待。&lt;/p&gt;
&lt;p&gt;因为平时周末来商场大部分是因为小丫头学画画，所以一般到达后都是直达教学地点，其余的不再多理睬，自然也就不熟悉Meland的准确位置。我们走了大半圈，终于按照入场的要求开启玩耍计划——扫码、测温、登记。&lt;/p&gt;
&lt;p&gt;小丫头首站选择了一辆粉色的救护车，她真的很喜欢车子和开车，从之前她独自尝试开卡丁车就知道了。车里由两部分组成，一个是模拟开车的车位，一个是后座上有个电子屏幕，用于玩反应游戏的。小丫头直接坐了开车位，我厚着脸皮坐在了后座的游戏位，入乡随俗地玩起了反应游戏，还因为得了三颗星而乐呵呵的。&lt;/p&gt;
&lt;p&gt;下一站本来想乘坐警车的（又是玩具车），因为有小朋友在玩，我们只要选择下一个了。对于抓娃娃机类似的电动玩具，我真的不擅长。为什么这么说呢，因为小丫头选择这类游戏后，一般都是让我代替她去玩，我只能接着这一重任，认真完成，并希望不要输得太“没面子”，毕竟在玩之前，小丫头以一种渴望我获得胜利的眼神看着我。&lt;/p&gt;
&lt;p&gt;游戏机呈圆周状，有很多投币口，也就意味着可以很多玩者一起参与。只见中间区域有很多浮在水面上的弹力球，还有水果样式的玩具。但这一块区域并不是固定的，通过机器驱动水流，让抓玩具的口没办法准确获取目标物品。&lt;/p&gt;
&lt;p&gt;“妈妈，要多少个硬币？”小丫头望着我。&lt;/p&gt;
&lt;p&gt;“4个”，紧接着小丫头便数了数手上的硬币，一个个递给我。&lt;/p&gt;
&lt;p&gt;“妈妈，我要这个紫色的葡萄。”小丫头指了指顺着水流转圈的“葡萄”。&lt;/p&gt;
&lt;p&gt;我也只好硬着头皮上阵了。Move按键按一次，Push按键按一次，我发现无法控制，也不知道怎么才能拿到小丫头指定的“葡萄”，还没研究透，我就得了四个弹力球，每次刚好只能抓起两个弹力球，为娘是已经尽力了，小时候也没玩过这么多抓娃娃的游戏机。&lt;/p&gt;
&lt;p&gt;小丫头看着手里握着的四颗弹力球，白色、蓝色、蓝色和绿色相间、蓝色和白色纹路的球，也有可能有点失望，毕竟不是她所需的葡萄玩具。&lt;/p&gt;
&lt;p&gt;在家第一次玩弹力球，也是下午时分了，小丫头原先不清楚弹力球可以弹起，就像拍皮球一样的好玩。我给她演示了一遍，双手举起，一下子快速将球往地上扔，只见四颗球向不同的方向弹跳着。小丫头顿时乐了，疯狂地追着四颗球，直到把每一颗重新握在手中。&lt;/p&gt;
&lt;p&gt;玩了几次，这四颗弹力球已经成为她本周末最佳玩具了，就连去姨妈家里串门吃饭，都要叮嘱我带上这四颗宝贝，揣在我衣服兜里。晚上睡前，还跟我这么描述，“球球跳得很高，跳起来的时候好会哈哈哈笑”。&lt;/p&gt;
&lt;p&gt;哪里是弹力球哈哈笑呢，这分明就是小丫头内心的写照呀。看到她的高度“评价”，我以这一周末捞出的这四颗球自豪。&lt;/p&gt;
</description>
</item>
<item>
<title>25-女儿与我：佩佩回家</title>
<link>https://liaolile.com/publication/25%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%BD%A9%E4%BD%A9%E5%9B%9E%E5%AE%B6/</link>
<pubDate>Wed, 29 Jun 2022 22:55:18 +0000</pubDate>
<guid>https://liaolile.com/publication/25%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%BD%A9%E4%BD%A9%E5%9B%9E%E5%AE%B6/</guid>
<description>&lt;p&gt;跟往常一样，为了让小丫头可以早点上床睡觉，想尽一切办法营造睡前环境，所有睡前活动都一一就绪。就在这时，小丫头突然说，睡前要给妈妈讲一个故事，叫做“佩佩回家”。也可能是因为看到她的小玩具，突发奇想地来了这么一个小插曲，她让我一边听，一边记录她讲的故事。&lt;/p&gt;
&lt;p&gt;“妈妈，你听我讲一个故事”，&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;佩佩去公园坐跷跷板，看到了很多蝴蝶，蝴蝶轻轻地亲了口美丽的花朵，将花朵的花蜜放在了小提桶里，然后飞回家了。&lt;/p&gt;
&lt;p&gt;佩佩看到小蜜蜂回家，她也想到了要做电梯回家。回到家以后，佩佩第一件事情就是跑去洗手间洗手，然后再去看电视、玩玩具。&lt;/p&gt;
&lt;p&gt;之后，佩佩就回房间睡觉了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我听着，她的逻辑挺有意思的，一下子觉得小丫头长大了，是一个有想法、有逻辑的孩子了。至少有一定的逻辑可以陈述一系列完整的事情，无论前后有没有强烈的逻辑。&lt;/p&gt;
&lt;p&gt;记得在早一年，我着对她的语言表达成长也是有益的，便尝试着引导着小丫头一起朗读两分钟内的寓言。那时候的小丫头吐字并不是这么清楚，但却非常喜欢学着读这些文字。也许是各种交流方式都体验过，所以小丫头在语言表达上特别游刃有余。&lt;/p&gt;
&lt;p&gt;我很喜欢小丫头跟我讲的这一则故事，也是她首个主动让我听的故事，哪怕不成文，也是一种无以伦比的体验。&lt;/p&gt;
</description>
</item>
<item>
<title>24-女儿与我：爸爸的肖像画</title>
<link>https://liaolile.com/publication/24%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%88%B8%E7%88%B8%E7%9A%84%E8%82%96%E5%83%8F%E7%94%BB/</link>
<pubDate>Sun, 19 Jun 2022 19:44:04 +0000</pubDate>
<guid>https://liaolile.com/publication/24%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%88%B8%E7%88%B8%E7%9A%84%E8%82%96%E5%83%8F%E7%94%BB/</guid>
<description>&lt;p&gt;从差不多两岁就看着小丫头非常喜欢画画，只不过是胡乱画，天马行空的用线条勾勒出一幅幅画。就因为认为小丫头非常喜欢，所以一次在逛商场的时候，无意间看中了一家画画教育机构，便给她报了十五节画画课程，认为还是得学些知识点，或者创造场景让小丫头在画画的路上看到更多的风景。&lt;/p&gt;
&lt;p&gt;迎着周末是父亲节，老师让小朋友们运用油画棒和平涂的方式表现色彩，画一幅主题为《爸爸的肖像画》的画。在绘画的过程中，回忆再现父亲的形象，目的是为了锻炼孩子的观察能力，也是增进亲子关系。&lt;/p&gt;
&lt;p&gt;周末在家，小丫头更贴着我，我也很好奇，在小丫头眼里的爸爸究竟是什么模样的。当然，在上课之前我不知道本节课的安排。而且小丫头这一次上课前，还牵着我的手不放，想必又有些希望我陪着她在教室里上课，鉴于上次的经验，我在她身后陪着，她不可能专心与老师互动，多半都是与我互动，那这样就失去授课的本意了。&lt;/p&gt;
&lt;p&gt;“妈妈去接爸爸了，小丫头跟着老师好好上课”，摸着小丫头的小脑袋，确定她不会嚎啕大哭，我便走出了教室门口。&lt;/p&gt;
&lt;p&gt;其实我仍旧不放心，小丫头的性格我太了解了，若没有忍住也许她真的会大哭，为了确保我的举动是正确的，我从教室外的玻璃墙看看她的表现。为了错开授课可视区（用磨面纸贴起来了，估计是担心商场的人来人往让孩子分心），我蹲着从缝隙中看到了小丫头，看上去她已开始投入课堂内容中了。这下，我真的可以放心到楼下与爸爸汇合，快到点的时候再来接小丫头。&lt;/p&gt;
&lt;p&gt;离下课时间还有二十分钟，我还是提前回来在教室外等候区坐着。想着上课前，小丫头一直说想要一个什么玩具来着，我得去给她找找，毕竟答应过的事情必须做到，这个是我告知她的，我也得以身作则。转了一圈，我找到可以购买这个玩具的地方，剩下的就是等下课后的小丫头自己来选。&lt;/p&gt;
&lt;p&gt;还是跟平时下课一样，我探着头确定是否已经下课，小丫头一下子便看到我了，很是兴奋，但是没有立马跑过来，因为她在等待老师的指令。每次下课前，老师会呼喊每个小朋友的名字，让她们自己把准备好的作品进行一个展示，由老师拍照。我认为这是一个很好的鼓励方式，让小朋友觉得画完之后还获得了心里的愉悦感和成就感。&lt;/p&gt;
&lt;p&gt;让我细品小丫头今天的作品，起初我不太明白。后来，等所有家长都到教室并听老师点评的时候，我才知道原来今天的主题是画爸爸。而且绘画的过程中，老师会让小朋友分享与爸爸的故事。小丫头说得不是很清楚，老师只记得说是跟爸爸玩什么游戏。看来爸爸还得好好与小丫头互动，让她更加记忆犹新。无论过程如何，小丫头的画令我刮目相看。&lt;/p&gt;
&lt;p&gt;我看着画，小声问小丫头，“爸爸的眼镜去哪里了”。小丫头并没有马上回答，而是微微一笑，“是爸爸刚睡醒吗？”她才肯点点头。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/26/EVJdmaXMtrgc9wZ.png" style="zoom:80%;" /&gt;
&lt;p&gt;粉色的衣服和粉色的头发，喏，原来爸爸在小丫头的心目中是这么的少女。&lt;/p&gt;
&lt;p&gt;亦或许，小女孩都希望爸爸是一个温柔，充满魔力的超人。是能够给她足够安全感的大力士，是能够给她足够肯定的鼓励者。希望我们家的粉红爸爸可以意会到，也永远保持着这份关爱。&lt;/p&gt;
</description>
</item>
<item>
<title>技术能力</title>
<link>https://liaolile.com/post/tech/base/%E6%8A%80%E6%9C%AF%E8%83%BD%E5%8A%9B/</link>
<pubDate>Fri, 17 Jun 2022 21:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/base/%E6%8A%80%E6%9C%AF%E8%83%BD%E5%8A%9B/</guid>
<description>&lt;p&gt;技术能力，什么才是技术能力？具有什么样的技术能力才能不丧失竞争力，这需要理解清楚技术能力的本质。&lt;/p&gt;
&lt;p&gt;解决一个技术问题的方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;就事论事，问题解决就万事大吉；当前只是解决了一个具体的问题，面临这同一个问题不同的人可能来问很多次。&lt;/li&gt;
&lt;li&gt;问题解决后立即整理成文档，并把排查方法及根因清晰的梳理，提升了后续自己和组内其他人的效率；&lt;/li&gt;
&lt;li&gt;将此排查问题的方法和逻辑固化为小工具给到具体求助的同学，以后其它人也可以自助使用该工具；解决了别人的问题，重新定义了效能问题并找到更好提效的办法；&lt;/li&gt;
&lt;li&gt;针对问题深挖，最后从业务原理以及产品功能上找到解决方案。同时技术工具抽象为功能完善了当前的业务。问题解决到当前的阶段，已经从某个具体问题看到了架构合理性的问题，并且彻底根治；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;上述都在一定程度上体现了技术能力，即便是一件繁琐的工作，也可以从扩大受益面的角度去提炼价值，并且寻求多个层次的解决方案，解决大多数利益相关者的关注点。同时，自己也锻炼了多层次的思考和抽象能力。往往很多事情也是如此递进的深入，解决具体问题-&amp;gt;总结深究-&amp;gt;工具提效-&amp;gt;融入产品，产品竞争力提升-&amp;gt;人人满意的结果。&lt;/p&gt;
&lt;p&gt;解决一个系统性/管理性等抽象问题的方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;面临着团队协作效率低下，发现抱怨的同学，然后问一问具体的问题，然后针对性解决；&lt;/li&gt;
&lt;li&gt;思考可能是一个普遍的问题，然后收集更广泛的问题，然后理出表格，归类分析并安排对应的人跟进和解决，最后定期跟踪进度；&lt;/li&gt;
&lt;li&gt;对于表格中的问题深入分析并且抽象，从架构调优、流程、产品功能角度寻找对应的原因，并寻求到最本质的原因，并确定解决这些问题带来的业务价值，然后按照目标进行拆解路径，向前向后补齐端到端，最后按照任务推进和跟踪进展；&lt;/li&gt;
&lt;li&gt;更全局角度思考此目标于年度目标的关系，团队组织的关系，思考如何扩大此事的效益，思考如何通过这些事情的解决锻炼和培养团队成员。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如何把问题解决到如何把事情做好，大多是时候是有迹可循的，按照自己的想法深入思考，按照特定的路径就已经在做好的道路上快步前进的。通过问题现象看到最终的本质，并能够通过对问题的抽象归纳进行技术架构层调优以解决同类的问题。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;技术能力&lt;/strong&gt;，就是一种以解决某种问题为目的的思路、方法与执行手段，其本质就是不论问题，解决问题的能力。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在编程领域，就是对遇到的业务问题进行抽象、提炼以及逻辑的构建，通过研发工具以提升解决问题的效能，减低人工低效的重复工作。&lt;/p&gt;
&lt;p&gt;技术能力模型的三个阶段体现：技术力、协作力（连接能力）和领导力。不管在哪个阶段，都要坚持长期主义，充分积累并利用时间的复利；总结的东西分类归类，越多，在时间上的复利就越能促进个人的成长。写下来你所想，讲出来你所想，验证出你所想。这就是提升技术能力的不二法则。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;技术力&lt;/strong&gt;，需要有扎实的技术基础（分布式技术、云原生技术、安全、质量等），对于自己的技能非常的娴熟。对于任务的使命必达、对于技艺的精益求精，对于新事物的好奇行，对于问题的攻坚克难。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;协作力&lt;/strong&gt;，更多的是技术架构能力，能够通过表层的问题现象深入到本质，通过模型的定义，原则的遵循来解决抽象复杂类的问题。需要通过问题发现，归纳定义问题，分析问题和问题本质解决的能力。体现在认知深度的能力，把难的事情做简单的能力，大白话清晰的思路讲清复杂的事情，从而对于这种简化的思维方式抽象为方法论。最终能够干成事，能够攻下城。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;领导力&lt;/strong&gt;，通过技术影响力去寻找团队的愿景和目标，带领组织占领战略高地，使用技术的思维解决超越技术领域的问题。需要对自身底层素质能力的提升，去从一些人与事之间最基本的内容中去领悟价值，从而赢得整个团队的向前的战斗力，力出一孔的必胜信念。&lt;/p&gt;
&lt;p&gt;任何人都是需要成长，才会逐步的提升。而自驱动力过程中要享受练习、思考、总结和感悟，而不是渴望得到别人的认可、反馈和评价。内心的强大才是真正的强大，而不是他人赞扬鼓励你牛逼你就牛逼。&lt;/p&gt;
&lt;p&gt;技术能力之&lt;strong&gt;讲清楚&lt;/strong&gt;，讲清楚是承接了你所想，和你想做的关键部分。&lt;/p&gt;
&lt;p&gt;方法论很多，5W2Y就是如此，但有时候还不够。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;少做预设多换位&lt;/p&gt;
&lt;p&gt;你的听众是去专业化的，对于专业的名词我们需要做到听众都理解，如果不能，那一个背景的描述是将所有人拉到一个水位上的好方法。另外类比/故事是讲述事情效果较好的办法，即使讲的故事并不是完全对等也没有关系。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在全局中找定位&lt;/p&gt;
&lt;p&gt;把你要讲的内容现在全局中找个位置，这个全局是什么意思呢，就是对于全局大家都会有一定的认知。比如说GridRouter架构，就应该先介绍华为云，然后阐明GridRouter在华为云中承担的业务具体是干嘛的，或者在架构图中凸显出我们要讲的对象。这样听众的理解也来得快。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;上天入地要搭配&lt;/p&gt;
&lt;p&gt;讲述的内容既要有上天的抽象观点，也要有入地的细节支撑的搭配。相反，对于细节的阐述最后也需要抽象来总结拔高，形成通用的原则和方法论，代表总结归纳可以看到类似的问题，提升讲述内容的深度。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;多维度多层次的思考&lt;/p&gt;
&lt;p&gt;讲的任何事情必然是多面的，有上有下，有左有右，而往往听众也是多层的。所以一般需要从多个维度讲多个层次，多维度就是一个问题看了哪几个面，多层次就是问题够不够深入，简单的就是多问几个why直到弄懂所有的内容。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;能定量就不定性&lt;/p&gt;
&lt;p&gt;定性的东西总让人觉得虚，而具体的数字，具体的动作，具体的关键点往往是某些人更加关注的更加可信的。比起没有说服力的侃侃而谈，更多人认为你做过什么，怎么做到的更能让人信服。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这也是技术能力中关键技术。&lt;/p&gt;
&lt;p&gt;接着再讨论下纯技术思维的不足，单纯只用技术思维来考量的话，就是考虑的维度过于单一，往往考虑的事情只是在how范围内。很多时候，更加重要的是what和why。what和why（0-1）是做一件事情how（0-100）的意义。&lt;/p&gt;
&lt;p&gt;技术思维往往是直线的，因为xx所以xx结果。而实际往往需要的是以&lt;code&gt;结果&lt;/code&gt;来看，影响结果的所有要素都考虑，建立关联后自然而言会思考更广的要素。避免在分析过程丢失结果的。&lt;/p&gt;
</description>
</item>
<item>
<title>23-女儿与我：你是我的力量和勇气</title>
<link>https://liaolile.com/publication/23%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%BD%A0%E6%98%AF%E6%88%91%E7%9A%84%E5%8A%9B%E9%87%8F%E5%92%8C%E5%8B%87%E6%B0%94/</link>
<pubDate>Sat, 11 Jun 2022 19:44:04 +0000</pubDate>
<guid>https://liaolile.com/publication/23%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%BD%A0%E6%98%AF%E6%88%91%E7%9A%84%E5%8A%9B%E9%87%8F%E5%92%8C%E5%8B%87%E6%B0%94/</guid>
<description>&lt;p&gt;短短几个月，这已经是第二次因感冒引起发高烧了。还是午休后收到幼儿园里老师的电话，还是那样起床后便出现发烧现象让我们早点接孩子回家休息。&lt;/p&gt;
&lt;p&gt;这一天我因为工作需要考试，不得不晚上十点多才能到家。回到家后，依旧不知疲惫地物理降温、搓手搓脚心、测量体温。夜深了，困倦中无意间碰到了小丫头的小脚丫，这温度，我知道，又是一个难眠之夜。&lt;/p&gt;
&lt;p&gt;第二天醒来看着温度已略微下降，叮嘱着母亲若温度升高继续降温，上一次感冒发烧的药还有，应该可以用上。谁知，到了下午时间，又被告知温度没有完全退下的38℃，让我们早点下班带她去医院看看。&lt;/p&gt;
&lt;p&gt;时间过得太快，晚上八点多才到家，推开门看到小丫头正坐在沙发上看电视，也许是被动画片里的内容吸引，看上去精神状态还可以，但是眼睛却是红肿的。我在想是不是她在家哭了好多次，因为我得上班，而小丫头生病的时候只要在视线范围内看不到我，必定不论原因梨花带雨地喊妈妈。也许看着心疼，我督促着孩子的爸爸赶紧收拾东西去医院，不希望反反复复发烧。但这次好在家附近的医院开了发热门诊，要不还得跑到较远的医院诊断。&lt;/p&gt;
&lt;p&gt;已经轻车熟路，发热门诊只能有一个家长陪护，一路上一直在跟孩子她爸讨论谁留下来。因为这一去就会是四到六个小时，算一下起码到凌晨一两点，但孩子她爸担心我没有这么多体力，但由于我执意要陪小丫头，所以还是我留下来了。&lt;/p&gt;
&lt;p&gt;着急之余，且又不是这么熟练医保卡挂号和付费一系列操作，总显得脑袋愚钝、手忙脚乱的。抱着小丫头跑到问诊台问了好几次，怕是待诊室外区的动画片声音覆盖了叫号声而过号了。护士小哥说并没有，可看着电子屏幕并没有我的号，索性直接抱着小丫头在儿科诊室外等候，看着空闲了就直接进去问医生是不是过号了。结果医生说我挂的并不是她的号，但好在可以帮我的小丫头问诊。也许是生物钟告诉我得休息了，平时做事雷厉风行的我，在这里显得有点不及格了。&lt;/p&gt;
&lt;p&gt;为检测是不是流感，还得抽血化验，个人感觉对于小孩看病必备一道程序——扎手指（末端）采血。小丫头虽在问诊的过程中不怎么说话，但一听要扎手指，立马哇哇大哭，并对着我说，“妈妈，我不要扎手指”。&lt;/p&gt;
&lt;p&gt;“不扎手指化验不了，怎么知道小丫头因为什么生病呢？”我抱紧她，并轻轻抚摸她的小脑袋瓜子。只想着安慰她，并告诉她不要害怕。&lt;/p&gt;
&lt;p&gt;“我们扎完手指，妈妈给你看手机里的宝宝巴士（从小陪伴她的认知启蒙应用，对小丫头非常好使），好不好？”&lt;/p&gt;
&lt;p&gt;小丫头终于肯停止哭声，但还是有点没办法不得不接受的感觉，“只能扎左手，右手会好疼”。或许上一次扎手指是右手指吧，就记着一晚上都用自己的小手保护这那一小团棉花。&lt;/p&gt;
&lt;p&gt;当护士小哥贴完条码，说让小丫头把手伸出来，小丫头确实把左手伸过去了，而且还指伸出了一根食指。其实我以为任何一根手指都可以，但细心的护士小哥对着小丫头说，“食指会很疼的哟，我们换其他的手指，好吗？”。这并不是护士小哥乱说，后来我查了下，确实医生们都建议使用无名指，原因是避免使用最灵活、最敏感的手指，可以有效减少感染几率和疼痛感。于是乎，小丫头又哭了，这一晚上不知道哭了多少回。&lt;/p&gt;
&lt;p&gt;化验结果需要两个小时后可以获取并拿着医生看、开药，才算是一个完整的问诊过程。然而当前时间也将近十二点了，我知道小丫头肯定是很困的，但是因为在医院里，并且还有动画片看，所以她没有想着睡觉。我抱着她，就像一岁不到的时候悠着她，只不过现在我没办法横着抱她了，太重、太长了，我只能让她靠在我的肩头上。&lt;/p&gt;
&lt;p&gt;本身腰部肌肉有些劳损的我，也顾不上这么多了，只想着她可以睡上一觉。&lt;/p&gt;
&lt;p&gt;“妈妈，我要下来。”小丫头蔫蔫地说。&lt;/p&gt;
&lt;p&gt;“是不想睡觉了吗？”&lt;/p&gt;
&lt;p&gt;“不是，我太重了，妈妈会抱不动我的。”我可以感受到她的体恤，不得不说小丫头从出生到现在，一直都是我心目中的天使宝宝，没有让我特别艰辛。&lt;/p&gt;
&lt;p&gt;“好，那妈妈帮你拿凳子拼成个小床，好不好？”只见小丫头点点头，但是无论怎么躺，小丫头好似都无法安稳入睡，等待报告的时间真的挺难熬的。&lt;/p&gt;
&lt;p&gt;不知道是多少回，终于等到了可以取报告的时间，而小丫头在椅子上看上去即将入睡了。本来想着打印报道就在几步路的隔板后面，可谁知，那边的打印机只能挂号，不能打印报告，然后我按着工作人员的指示跑到就诊室旁边打印。&lt;/p&gt;
&lt;p&gt;就在这时，我听到了熟悉的哭声，对，是小丫头哭了。小丫头肯定是调整位置的时候没看到我，起身立马哭了，一个小人儿盘腿坐在椅子上。我举足无措，只想着我可以快速拿到报告，没想到也就几分钟的疏忽。连忙抱起小丫头，并迅速将衣服手进背包里，边安慰小丫头，边跑进就诊室。&lt;/p&gt;
&lt;p&gt;还好只是普通的感冒，开了点药就可以结束了。我抱着小丫头前往智能机位进行缴费，小丫头很乐意使用自己的医保卡并协助我完成缴费过程。一切都好像安静了下来，我们只需要静静等待核酸检测结果即可出院。&lt;/p&gt;
&lt;p&gt;我还是抱着小丫头，只不过这一次我让她在我怀里入睡，果真她已经累的不行了，很快便在我怀里睡着了。为了让她睡得舒坦一些，我让她枕在我的手臂上，拿着她的外套做被子盖好。&lt;/p&gt;
&lt;p&gt;睡眼朦胧中，小丫头还不忘问我，“妈妈，我们可以回去了吗”。&lt;/p&gt;
&lt;p&gt;“再等一会，很快我们就可以回家了。”&lt;/p&gt;
&lt;p&gt;当得知我们可以出门诊时，我二话不说，背起小背包，将熟睡的小丫头调整好睡姿，让她的头靠在我的肩膀上，省力。看着走路回去也就十几分钟，想着不打车也罢了，就直愣愣地两个人走在寂静的路上。&lt;/p&gt;
&lt;p&gt;按照她的重量，我顶多能走到路口，而且夜深人静，没有路灯的天桥和停着车的区域，都会让我害怕。时不时有路过的电瓶车或者摩托车，有的是为了搭车，有的真的只是路过。但我全程都不敢去做任何反应，只想着自己快点走，只想着自己可以坚持将小丫头抱到家门口。越是害怕走得越快，越不敢放下熟睡的小丫头。我感觉这一路走的时间变得越来越漫长。&lt;/p&gt;
&lt;p&gt;或许是有摩托车的喇叭声，再或许我抱得她太紧，小丫头恍然间醒了，第一句话就说着，“我们可以出去了吗”。&lt;/p&gt;
&lt;p&gt;“是的，妈妈抱你回家，我们很快就到家了”，我尽量少地说话，担心没有足够的体力达到目的地。&lt;/p&gt;
&lt;p&gt;走到路灯下，我实在已经达到极限了，只好换成背着小丫头。夏季的深夜一般都比较凉爽，而且这阵子还下了暴雨，让夜晚温度很适宜。但我的汗珠还是不断地往外冒，顿时间觉得我的体温比小丫头还要高。&lt;/p&gt;
&lt;p&gt;当打开家门口时，孩子她爸还惊讶地说怎么不叫他来接，取下口罩才发现我已是满头大汗，脸颊上全都是大颗大颗的汗珠。&lt;/p&gt;
&lt;p&gt;想想其实挺后怕的，若路上遇到什么危险，毕竟一个弱小的妇女抱着一个幼儿。一路上若不是小丫头，也许我没办法走完那段漫长的路。&lt;/p&gt;
</description>
</item>
<item>
<title>22-女儿与我：一起写文章</title>
<link>https://liaolile.com/publication/22%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99%E6%96%87%E7%AB%A0/</link>
<pubDate>Sun, 05 Jun 2022 19:44:04 +0000</pubDate>
<guid>https://liaolile.com/publication/22%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99%E6%96%87%E7%AB%A0/</guid>
<description>&lt;p&gt;小丫头说，“妈妈，我们一起来写文章，好吗？”&lt;/p&gt;
&lt;p&gt;今天我们的写作方式有些不一样，我怀抱着小丫头，手里捧着手机，双手快速地在键盘上打字，而我的小丫头，边看我打字，边让我教她新的文字，还时不时提醒我她即将要从我腿上滑落到床面上。&lt;/p&gt;
&lt;p&gt;“妈妈，这个字怎么读？”小丫头指着刚写出来的一行字说道。&lt;/p&gt;
&lt;p&gt;“这个读“字”，还有什么不知道的字呢？”小丫头用小小的手指尖，又指着一行字。就这样，我们俩写着念着完成了首个百来字的小短文。&lt;/p&gt;
&lt;p&gt;现在的小丫头正处于识字阶段，小眼睛跟吸尘器一样，把每日所见的文字，只要能认识的，都会一一读出来。有一次我们出去玩，小丫头在地铁里一字一顿地念着，我以为又是她在幼儿园学的歌曲，没想到读的却是地铁广告屏幕下方一行流动的字幕。一顿是因为她只认识个别字，还不能完整地读完一整句，但已经非常接近了。&lt;/p&gt;
&lt;p&gt;记得前些日子，我在房间里看书，而小丫头则拿着一只马克笔和一本爸爸不看的书本，也悄然坐在我身边，学着我静静地看书。不一会，小丫头敞亮着嗓门，“妈妈，你看，这些字我都认识”。我定睛一看，这小丫头把自己认识的文字都用短线画了出来，粗略看了下，都是“一、二、石、手、口、上、出、榴、中”等文字。&lt;/p&gt;
&lt;p&gt;我不禁一乐，一两页书本上，都是她画的小短线，“还认识不少呀！”&lt;/p&gt;
&lt;p&gt;小丫头也笑了笑，“是呀，这些都是我认识的字呀。”&lt;/p&gt;
&lt;p&gt;就在这时，小丫头还提醒了我一句，“妈妈，你多写一点吧，我还想看好多好多的文字”。&lt;/p&gt;
</description>
</item>
<item>
<title>21-女儿与我：第一次</title>
<link>https://liaolile.com/publication/21%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%AC%AC%E4%B8%80%E6%AC%A1/</link>
<pubDate>Sat, 04 Jun 2022 19:44:04 +0000</pubDate>
<guid>https://liaolile.com/publication/21%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%AC%AC%E4%B8%80%E6%AC%A1/</guid>
<description>&lt;p&gt;孩子在成长的每一个阶段都会有突破性的第一次，有时候需要父母引导并创造机会，有时候则是无意间的尝试。&lt;/p&gt;
&lt;p&gt;立夏之后，夏天所拥有的炎热已经闯入我们的生活之中，各种消暑的方式已熟练开启。我最梦寐以求的温度状态就是待在26℃的空调房里，拿一听汽水一饮而尽……&lt;/p&gt;
&lt;p&gt;对于小丫头，则是光着脚丫在房间里到处跑。不，今天最喜欢的就是在浅水区里游泳——玩水。这也是她这么大以来，在户外与水进行首次互动。&lt;/p&gt;
&lt;p&gt;小的时候害怕在水里着凉了，害怕皮肤免疫力不健全导致在婴儿游泳池里会过敏等等，其实想来之前过于在意，在我肚里就已经喜欢与水交互，对于她们而言，最熟悉不过的场景了。也因此，小丫头迟迟没有感受到夏日在游泳池里打水仗的快乐。&lt;/p&gt;
&lt;p&gt;泳衣是两岁不到的时候买的，而游泳圈是早一个月买的，完事具备只欠东风了。这一次，也是晚饭时听到小区楼下小型游泳池的嬉戏声才决定的。急急忙忙地准备，出发前手工给游泳圈打气，结果被小丫头在客厅里玩了一个月的游泳圈还破了个洞，只能用强力胶先打了补丁。也没有准备泳帽，到了水池边，被救生员警告了一次，我们只能体面地解释这次不游，只是让小孩在水里玩。&lt;/p&gt;
&lt;p&gt;不过这些并不影响小丫头第一次游泳的欢乐体验，从下水的那一脚开始，整个水池就像是由无数个快乐的水宝宝组成，牵着她们的小手，去拥抱着每一个入水的小朋友。当听到小丫头在水池中央呵呵地笑声，我就知道这一次，她肯定非常喜爱。&lt;/p&gt;
&lt;p&gt;还好水并不深，小丫头可以站在里面拍着水花玩耍。出来之后还不断跟我说，“妈妈，太好玩了，我喜欢游泳，我还要来一百次”。对于执行力超强的我来说，必须满足小丫头第一次游泳体验后的感受，游泳帽立马在网上购买，为下一次下水做足充分地准备。&lt;/p&gt;
</description>
</item>
<item>
<title>20-女儿与我：多些信任</title>
<link>https://liaolile.com/publication/20%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%A4%9A%E4%BA%9B%E4%BF%A1%E4%BB%BB/</link>
<pubDate>Fri, 03 Jun 2022 19:44:04 +0000</pubDate>
<guid>https://liaolile.com/publication/20%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%A4%9A%E4%BA%9B%E4%BF%A1%E4%BB%BB/</guid>
<description>&lt;p&gt;孩子的成长就像是雏鹰展翅，要有机会才能知道飞得有多高。对于小丫头，我发自内心地想履行这个观念，但发现喜欢亲力亲为的我，有时候并没有完全做到。&lt;/p&gt;
&lt;p&gt;之前担心小丫头没办法自己把牙齿刷得很干净，所以每次她一撒娇，我就直接冲过去帮她仔细刷洗牙齿。正巧今天有序忙着家务，与她刷牙时间错开了，我只能语音指挥她自己到洗漱间漱口。&lt;/p&gt;
&lt;p&gt;“带上你的冰墩墩们，排队刷牙。”&lt;/p&gt;
&lt;p&gt;“好”，小丫头一下子抱起四个冰墩墩玩偶，比我预期完成得还要快。&lt;/p&gt;
&lt;p&gt;很主动将自己的牙刷、牙膏、小漱口杯从柜子里拿下来，并且小丫头自己挤好了牙膏。我以为这一次小丫头还是和往常一样，等待我前来帮忙。也许是我在整理她学校要求换洗的被子，也忘了这道“程序”，等我回过头来发现，小丫头已经自己在刷牙了。&lt;/p&gt;
&lt;p&gt;看到我迎面走来，小丫头还对着我说，“妈妈，你看我刷得干净吗？”说完还张开嘴给我看还有泡泡的牙齿。之后，还自己洗脸，将洗脸巾挂好。&lt;/p&gt;
&lt;p&gt;我终于可以躺在卧室里，等待她汇报成果，“妈妈，我刚刚还会洗脸，我洗了脸、耳朵、脖子，你看干不干净呀？”&lt;/p&gt;
&lt;p&gt;我一把抱着眼前这个又长大一步的小丫头，“你已经学会自己刷牙、洗脸了，妈妈真为你高兴！”&lt;/p&gt;
&lt;p&gt;相比以前，我担心小丫头这也不会做，那也不会做的心态略显多余了，如果不放手让她去尝试，也许只能收获到理所应当的结果，甚至小孩永远都不会在不断尝试中独立做力所能及的事情。&lt;/p&gt;
&lt;p&gt;多一点耐心和信任，要做出妈妈的周全和爸爸的态度带娃，才能如雄鹰展翅那般高飞。&lt;/p&gt;
</description>
</item>
<item>
<title>19-女儿与我：花式入睡法</title>
<link>https://liaolile.com/publication/19%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%8A%B1%E5%BC%8F%E5%85%A5%E7%9D%A1%E6%B3%95/</link>
<pubDate>Sun, 29 May 2022 19:44:04 +0000</pubDate>
<guid>https://liaolile.com/publication/19%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%8A%B1%E5%BC%8F%E5%85%A5%E7%9D%A1%E6%B3%95/</guid>
<description>&lt;p&gt;小朋友的精力就跟一直连着充电器充着电一样，永远播放着高动感音乐节目。但是一旦超越他们需要睡眠的最低要求，他们便能够迅速入睡，堪称为“秒睡”。&lt;/p&gt;
&lt;p&gt;我见过小丫头看着电视并靠在沙发上睡着的，我见过小丫头闹着说玩这个那个玩具，结果才扛在肩上一会睡着的……&lt;/p&gt;
&lt;p&gt;以上都是入睡后无论怎么呼喊、怎么推摇，都不会醒的深度入眠。而今天，遇到了另一种方式。&lt;/p&gt;
&lt;p&gt;小丫头在出官场之前几分钟，拿到了展示台的一只气球，爱不释手，不允许任何人拿走。然而我们正步行走向地铁站，坐过地铁的都清楚，气球是不允许带进车厢内的，所以我和爸爸轮流式说明为什么不能带上地铁。小丫头听后双眼显露出疑惑和迷离，“为什么不可以？在家里的气球都不好玩，我会丢掉的”，显然她开始任性了。&lt;/p&gt;
&lt;p&gt;当看到无神的小眼睛，我得知了另一个信号，小丫头肯定困到即将入睡的状态了。&lt;/p&gt;
&lt;p&gt;小丫头一直紧紧握着她银白色的小气球，宛如夏日里的一道光。本想着到了地铁站再苦口婆心再说一次，也许小丫头会接受。可没想到，一转眼，便看到小丫头闭着眼睛在“小鸡啄米”，但手上还是紧握着绑着气球的塑料杆。&lt;/p&gt;
&lt;p&gt;这样都能睡？真的是可爱不已。我结果她小手上的气球时，她还不忘跟我轻轻说，“不要跟地铁拿走”。只可惜太困太累，没有再与我“斗智斗勇”。&lt;/p&gt;
&lt;p&gt;这不由得想起我小的时候，为了看喜欢的动画片，中午没有休息，下午上课的时候真的是“小鸡啄米”，完全听不清老师讲的是什么，自己笔下写得是什么字，等下课后再醒来，只见课本上全是天书。&lt;/p&gt;
&lt;p&gt;也许孩童时期就是这样，玩与乐，才是最大的成长印记。&lt;/p&gt;
</description>
</item>
<item>
<title>Kubernetes</title>
<link>https://liaolile.com/post/tech/cloudnative/kubernetes/</link>
<pubDate>Sun, 29 May 2022 12:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/cloudnative/kubernetes/</guid>
<description>&lt;h3 id="0-kubernetes是什么"&gt;0. Kubernetes是什么&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Kubernetes(K8s)&lt;/strong&gt; is a portable, extensible, open source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kubernetes为云原生应用提供了定义规范。&lt;/p&gt;
&lt;p&gt;Kubernetes 已经成为云时代的操作系统。我们可以对比一下经典的 Linux 和 Kubernetes 的概念模型，他们都是定义了开放的、标准化的访问接口；该通用API接口在类Unix下称为POSIX&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;Portable Operating System Interface&lt;/strong&gt; (&lt;strong&gt;POSIX&lt;/strong&gt;) is a family of &lt;a href="https://en.wikipedia.org/wiki/Standardization" target="_blank" rel="noopener"&gt;standards&lt;/a&gt; specified by the &lt;a href="https://en.wikipedia.org/wiki/IEEE_Computer_Society" target="_blank" rel="noopener"&gt;IEEE Computer Society&lt;/a&gt; for maintaining compatibility between &lt;a href="https://en.wikipedia.org/wiki/Operating_system" target="_blank" rel="noopener"&gt;operating systems&lt;/a&gt;.  POSIX defines both the system- and user-level &lt;a href="https://en.wikipedia.org/wiki/Application_programming_interface" target="_blank" rel="noopener"&gt;application programming interfaces&lt;/a&gt; (API), along with command line &lt;a href="https://en.wikipedia.org/wiki/Unix_shell" target="_blank" rel="noopener"&gt;shells&lt;/a&gt; and utility interfaces, for software compatibility (portability) with variants of &lt;a href="https://en.wikipedia.org/wiki/Unix" target="_blank" rel="noopener"&gt;Unix&lt;/a&gt; and other operating systems.POSIX is also a &lt;a href="https://en.wikipedia.org/wiki/Trademark" target="_blank" rel="noopener"&gt;trademark&lt;/a&gt; of the IEEE. POSIX is intended to be used by both application and system developers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kubernetes定义了云的分布式系统的API。如下是linux同kubernetes之间的类比：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;内容&lt;/th&gt;
&lt;th&gt;Linux&lt;/th&gt;
&lt;th&gt;Kubernetes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;隔离单元&lt;/td&gt;
&lt;td&gt;进程&lt;/td&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;硬件&lt;/td&gt;
&lt;td&gt;虚拟机/物理机&lt;/td&gt;
&lt;td&gt;数据中心&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;并发单元&lt;/td&gt;
&lt;td&gt;线程&lt;/td&gt;
&lt;td&gt;容器进程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;资源管理&lt;/td&gt;
&lt;td&gt;进程内存及CPU&lt;/td&gt;
&lt;td&gt;内存、CPU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;存储&lt;/td&gt;
&lt;td&gt;文件&lt;/td&gt;
&lt;td&gt;ConfigMap，Secrete，Volumn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;网络&lt;/td&gt;
&lt;td&gt;访问端口&lt;/td&gt;
&lt;td&gt;Service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;终端控制台&lt;/td&gt;
&lt;td&gt;shell，bash&lt;/td&gt;
&lt;td&gt;kubectl&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;网络安全&lt;/td&gt;
&lt;td&gt;Iptables&lt;/td&gt;
&lt;td&gt;NetworkPolicy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;权限管理&lt;/td&gt;
&lt;td&gt;用户、文件权限&lt;/td&gt;
&lt;td&gt;UserAccount，ServiceAccount，RBAC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Linux和kubernetes作为操作系统，体现在向下封装资源，向上支撑应用。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/04/s6pCo18ZjVHDt2Y.jpg" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;它们都提供了对底层计算、存储、网络、异构计算设备的资源抽象和安全访问模型。可以根据应用需求进行资源调度和编排。Linux 的计算调度单元是进程，调度范围限制在一台计算节点。而 Kubernetes 的调度单位是 Pod，可以在分布式集群中进行资源调度，甚至跨越不同的云环境。其主要业务是调度和管理容器服务。&lt;/p&gt;
&lt;h3 id="1-kubernetes架构"&gt;1. Kubernetes架构&lt;/h3&gt;
&lt;p&gt;一个高层级的Kubernetes架构图如下：分为控制面Master和数据面Node节点池；集群上可以是一主多从和多主多从的架构；&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/04/2tZKCeJ491qjN5y.jpg" style="zoom: 33%;" /&gt;
&lt;p&gt;Kubernetes 的控制平面包含四个主要的组件：API Server、Controller、Scheduler 以及 etcd。如下是其与数据面的交互图，均通过API server同kubelet交互实现的。同时数据面提供loadbalancer给到终端用户请求。K8s 可以在 IDC、云端、边缘等不同场景进行统一部署和交付。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/04/JTma7KdVspOqSFW.png" alt="img" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 id="11-容器相关概念"&gt;1.1 容器相关概念&lt;/h4&gt;
&lt;p&gt;如下图介绍了Kubernetes以及docker中最核心的一些概念。&lt;/p&gt;
&lt;p&gt;CRI是kubernetes定义的容器运行时接口，具体的实现由两个，一个是来自于docker的containerd，另一个是来自于RedHat的CRI-O。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Docker，Kubernetes 等工具来运行一个容器时会调用容器运行时（CRI）比如 containerd，CRI-O&lt;/li&gt;
&lt;li&gt;通过容器运行时来完成容器的创建、运行、销毁等实际工作&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Docker 使用的是 containerd 作为其运行时；Kubernetes 支持 containerd，CRI-O 等多种容器运行时&lt;/li&gt;
&lt;li&gt;这些容器运行时都遵循了 OCI 规范，并通过 runc 来实现与操作系统内核交互来完成容器的创建和运行&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="3"&gt;
&lt;li&gt;CRI（容器运行时接口）是 Kubernetes 用来控制创建和管理容器的不同运行时的 API，它使 Kubernetes 更容易使用不同的容器运行时。它一个插件接口，这意味着任何符合该标准实现的容器运行时都可以被 Kubernetes 所使用。&lt;/li&gt;
&lt;li&gt;OCI 开放容器倡议，是一个由科技公司组成的团体，其目的是围绕容器镜像和运行时创建开放的行业标准。他们维护容器镜像格式的规范，以及容器应该如何运行。&lt;/li&gt;
&lt;li&gt;runc 是轻量级的通用运行时容器，它遵守 OCI 规范，是实现 OCI 接口的最低级别的组件，它与内核交互创建并运行容器。runc 为容器提供了所有的低级功能，与现有的低级 Linux 功能交互，如命名空间和控制组，它使用这些功能来创建和运行容器进程。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;具体详细内容参考下述图表&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/04/fNnYTSmP4OhJr7U.jpg" alt="img" style="zoom:67%;" /&gt;
&lt;h4 id="12-kubernetes设计理念"&gt;1.2 Kubernetes设计理念&lt;/h4&gt;
&lt;p&gt;Kubernetes 在容器编排中有几个关键设计理念：&lt;/p&gt;
&lt;p&gt;**容错性：**容错性是保证K8s集群系统稳定性和安全性的基础，确保系统不崩溃，不出现业务错误，不做坏事。&lt;/p&gt;
&lt;p&gt;**易扩展性：**易扩展性是保证K8s友好，后续快速迭代增加新功能的基础，让系统可以在用户看到的时间内做好事。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;声明式 API&lt;/strong&gt;：开发者可以关注于应用自身，而非系统执行细节。比如 Deployment（无状态应用）、 StatefulSet（有状态应用）、Job（任务类应用）等不同资源类型，提供了对不同类型工作负载的抽象；对 Kubernetes 实现而言，基于声明式 API 的 “level-triggered” 实现比 “edge-triggered” 方式可以提 供更加健壮的分布式系统实现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可扩展性架构：&lt;strong&gt;所有 K8s 组件都是基于一致的、开放的 API 实现和交互；三方开发者也可通过 CRD（Custom Resource Definition）/Operator 等方法提供领域相关的扩展实现，极大提升了 K8s 的能力。Operator 是 Kubernetes 里面的一个核心思想，它代表着我的任何一个应用和它所需要的能力都可以定义成为一个 Kubernetes 的 API 对象，通过一个叫做 Controller 的机制让你去使用云的能力，再让你接入到各种各样的基础设施里面。这个 Operator 化带来的一个直接结果就是，我的应用本身是高度自动化的，包括&lt;/strong&gt;自愈、健壮性、可靠性、运行的确定性&lt;/strong&gt;，这些在今天都可以交给 Kubernetes去解决。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可移植性&lt;/strong&gt;：K8s 通过一系列抽象如 Loadbalance Service（负载均衡服务）、CNI（容器网络接口）、CSI（容器存储接口）、CRI（容器运行时接口），帮助业务应用可以屏蔽底层基础设施的实现差异，实现容器灵活迁移的设计目标。&lt;/p&gt;
&lt;h4 id="13-kubernetes核心概念"&gt;1.3 Kubernetes核心概念&lt;/h4&gt;
&lt;p&gt;Kubernetes中核心对象类型包括：资源对象、配置对象、存储对象、策略对象，详细的对象类别中包含一些核心概念。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/04/LypNOxkQGh9tC4H.jpg" style="zoom: 50%;" /&gt;
&lt;p&gt;上述对象均可理解为Kubernetes API Objects，每个对象包含三大类属性：&lt;strong&gt;元数据metadata，规范spec和状态status&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;元数据&lt;/code&gt;用来标识对象，至少包含三个元数据：namespace，name，uid；除此一般还有label，可以用来标识和匹配不同的对象；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;规范&lt;/code&gt;描述了用户期望kubernetes集群中分布式系统达到的理想状态；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;状态&lt;/code&gt;描述了当前系统实际达到的状态&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kubernetes中所有的配置都是通过API对象的spec去设置的，也就是用户通过配置系统的理想状态来改变系统，所有的API均是声明式的。&lt;/p&gt;
&lt;h5 id="131-资源对象"&gt;1.3.1 资源对象&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pod&lt;/strong&gt;，Kubernetes中最小的部署应用或服务单元，可以支持部署多容器；同一个Pod中共享网络地址和共享文件，可以通过进程间通信组合完成服务。目前Kubernetes业务主要包括：long-running、batch、node-deamon、stateful application，分别对应的控制器为Deployment，Job，DeamonSet，StatufulSet。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;**Deployment **，表示对集群的Kubernetes的一次更新操作，比RS应用模式更广的API对象，可以是创建一个新的服务，更新一个新的服务，也可以是滚动升级一个服务。滚动升级实际是创建一个新的RS，逐步增加到理想的副本个数，旧的RS逐步减小到0的符合操作；以 Kubernetes 的发展方向，未来对所有长期伺服型的的业务的管理，都会通过 Deployment 来管理。Master 节点的中有一个子系统叫做 Deployment Controller，负责实际执行并使当前状态不断趋向于所需状态。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Replication Controller&lt;/strong&gt;， 副本控制器RC, 用来保证Pod高可用的API对象，通过监控运行中的Pod个数来保证集群中运行指定数目的Pod副本。RC是Kubernetes早期技术概念，只适用于long-running业务类型，目前已经使用RS替代。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Replica Set&lt;/strong&gt;， 副本集 RS，RS是新一代RC，提供同样高可用能力，支持更多种类的匹配模式，副本集对象一般不单独使用，而是作为Deployment的理想状态参数使用。ReplicaSet 是管理 pod 生命周期的组件，监控活动副本，当收到指令时或 pod 离线或意外停止时启动 pod，也会在收到指示时杀死 pod，也许是因为用户负载减少。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Job&lt;/strong&gt;, Job是K8s中用来控制批任务的API对象。Job管理Pod根据用户的设置把任务成功完成就自动退出了。成功完成的标志根据不同的spec.completions策略而不同；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deamon Set&lt;/strong&gt;，后台服务集，重点关注K8s中的节点，确保每个节点上均有此类Pod（包括存储、日志、监控等）运行。节点可能是所有集群节点，也可能是通过NodeSelector选定的一些特定节点。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;StatefulSet&lt;/strong&gt;，有状态服务集，RC和RS主要控制的是无状态服务集，其所控制的Pod名字是随机设置的，1个Pod出故障了就被丢弃了，而另个地方重启的Pod名字就变了。对于无状态服务集重要的是数量，而不是名字和在哪。StatefulSet中每个Pod的名字都是事先确定的，不能改变的，用于后续关联Pod的状态。StatefulSet中的Pod每个独立挂载自己的独立存储，Pod出现故障后，还得挂载上原来的存储继续提供有状态服务；StatefuleSet做的事情是将确定的Pod和确定的存储关联起来保证状态的连续性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id="132-配置对象"&gt;1.3.2 配置对象&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Node节点&lt;/strong&gt;, K8s中的计算能力，是所有Pod运行所在的工作主机，可以是物理机也可以是虚拟机，均需要基于kubelet管理节点上的容器。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service服务&lt;/strong&gt;， RC/RS/Deployment只是保证了Pod的数量，没有解决如何访问这些服务的问题。由于Pod的调度机制决定了服务实例不能以确定的IP和端口来提供服务，需要依赖服务端的服务发现和负载均衡能力。在K8s内部，客户端需要访问的服务就是Service对象，每个Service对象都会有一个集群内部的虚拟IP，集群内部通过虚拟IP访问服务；Kube-proxy是K8s中的负载均衡器，在K8s的每个节点上都有一个，这是一个分布式的代理服务，需要访问的节点服务越多，提供负载均衡能力的kube-proxy就越多，高可用节点也越多。 另外，Service 是一组逻辑上的 pod分组，对提供同一个服务的多个Pod进行聚合；它提供了一个单一的虚拟的Cluster IP 地址和 DNS 名称，后端对应1个或多个提供服务的Pod，你可以通过它访问服务内的所有 pod。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secrete 密钥对象&lt;/strong&gt;， 用来保存和传递密码、密钥、认证凭据等敏感信息。在对应的配置文件中通过Secrete对象应用敏感信息。这种方式的好处是：意图明确，避免重复，减少暴露机会。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UserAccount用户账户 &amp;amp; ServiceAccount服务庄户&lt;/strong&gt;, 用户账户为个人提供账户标识，服务账户为计算机进程和K8s集群中运行的Pod提供账户标识。用户账户与下述的服务命名空间无关，而服务账号的是运行绑定在某个命名空间下的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Namespace命名空间&lt;/strong&gt;，提供集群虚拟的集群隔离作用，K8s初始由两个命名空间，1个是默认命名空间default，1个是系统命名空间kube-system。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ingress/Egress&lt;/strong&gt;，Kubernetes pod 的流量称为 Ingress，而从 pod 到集群外的出站流量称为 Egress。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom Resource Definition&lt;/strong&gt;, CRD自定义的资源对象，需要满足K8s API定义规范；
&lt;ul&gt;
&lt;li&gt;apiVersion，自定义资源对象的版本号&lt;/li&gt;
&lt;li&gt;Kind，自定义资源对象的名称，用户可以通过kubectl get ${kind_name}来获取对应的资源对象&lt;/li&gt;
&lt;li&gt;Metadata，继承了原生的K8s的metadata，用于添加lable/annotation等元数据&lt;/li&gt;
&lt;li&gt;Spec，可自定义设计的服务配置参数，如镜像版本号，节点数据量等&lt;/li&gt;
&lt;li&gt;Status，定义资源的相关状态&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id="133-存储对象"&gt;1.3.3 存储对象&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Volumn存储卷&lt;/strong&gt;, Docker存储卷作用范围为一个容器，而K8s的存储卷作用范围为一个Pod，每个Pod申请的卷由Pod中所有容器共享。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PersistentVolumn&lt;/strong&gt;持久存储卷 &amp;amp; &lt;strong&gt;PersistentVolumnClaim&lt;/strong&gt;持久存储卷声明， PV和PVC使K8s具有存储的逻辑抽象能力，使得配置Pod的存储卷时候可以忽略对应的存储技术配置。PV和PVC的关系类比于计算的Node和Pod，PV和Node是资源提供者，PVC和Pod是资源使用者。&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id="134-策略对象"&gt;1.3.4 策略对象&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Federation集群联邦&lt;/strong&gt;， K8s最初的设计是单一集群在同一个地域内，同一个地区的网络性能才能满足K8s调度和计算存储连接要求。Federation就是让K8s有跨Region和跨服务商的能力。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RBAC访问授权&lt;/strong&gt;，RBAC中引入角色Role和角色绑定RoleBinding，访问策略是可以和某个角色绑定，具体的用户再和1个或多个角色绑定；&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="14-kubernetes和服务网格servicemesh"&gt;1.4 Kubernetes和服务网格ServiceMesh&lt;/h4&gt;
&lt;p&gt;将应用程序的功能划分为单独的进程运行在同一个最小调度单元中（例如 Kubernetes 中的 Pod）可以被视为 &lt;strong&gt;sidecar 模式&lt;/strong&gt;。如下图所示，sidecar 模式允许您在应用程序旁边添加更多功能，而无需额外第三方组件配置或修改应用程序代码。而通过sidecar模式的组网即为服务网格架构形态。Sidecar 应用与主应用程序松散耦合。它可以屏蔽不同编程语言的差异，统一实现微服务的可观测性、监控、日志记录、配置、断路器等功能。&lt;/p&gt;
&lt;p&gt;中间件实际上是大量的通过 Sidecar 方式去被使用到的，所以我的应用本身不需要再去引入一个库，或者引入一个特定的框架来去做很多事情，我甚至都不需要感知。应用跟云的交互，就通过一个叫 Sidecar 的一个旁路容器，让这个容器去代理应用本身所需要的进出流量，所以云就可以非常容易地通过这样一个代理，调节流量、做流量切分、网络管控，这就是非常简单的 Service Mesh 的原理。如下是两种形态的Sidecar模式。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/04/izHEBdmqC3rNkZ8.png" alt="img" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;使用容器作为Service和Sidecar进程的承载；&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/04/uHVP5LsACQvYktd.png" alt="img" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;使用Function作为Servcie和Sidecar逻辑的承载；&lt;/p&gt;
&lt;h3 id="2-kubernetes原理机制"&gt;2. Kubernetes原理机制&lt;/h3&gt;
&lt;h4 id="21-kubernetes服务之间通信"&gt;2.1 Kubernetes服务之间通信&lt;/h4&gt;
&lt;h5 id="211-clusterip"&gt;2.1.1 ClusterIp&lt;/h5&gt;
&lt;p&gt;在K8s中，Service对应提供一个虚拟的ClusterIp，通过ClusterIp即可访问到服务对应的Pod。而负责这一转发的模块是Kube-proxy。在该场景下，ClusterIp和PodId都是K8s集群内部的访问地址；&lt;/p&gt;
&lt;p&gt;Kube-proxy是一个运行在K8s每个节点上的Go应用程序，支持三种工作模式：userspace、iptables、ipvs。后端选择pod进行转发的时候依赖Label Selector。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;userspace&lt;/p&gt;
&lt;p&gt;该模式下kubep-proxy为每个service创建一个监听端口，发向ClusterIp的请求被iptables规则重定向到Kuber-proxy监听的端口上，Kube-proxy依据LB算法选择一个服务的Pod进行请求转发。该模式下，Kube-proxy是4层loadbalancer。但是由于在用户空间，数据拷贝效率较低。后端Pod不可用时，kube-proxy会重试其他的pod。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;​		&lt;img src="https://s2.loli.net/2022/06/13/b9uRs8KvqFeIPUH.jpg" style="zoom: 50%;" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;iptables&lt;/p&gt;
&lt;p&gt;kube-proxy为service后端的每个pod创建对应的iptables规则，直接将发向ClusterIp的请求重定向到一个Pod Ip。该场景下，避免了数据的用户空间和内核空间的拷贝，kube-proxy不充当4层负载均衡，而只负责创建iptables规则。但是当后端pod故障后，无法进行重试；&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/13/XoxSaHyWi4UgmkQ.jpg" style="zoom: 50%;" /&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ipvs&lt;/p&gt;
&lt;p&gt;kube-proxy监控pod的变化并且创建对应的ipvs rules。ipvs是在kernel模式下通过netfilter实现，采用hash table存储规则，支持更多的loadbalance的算法，依赖在操作系统中安装ipvs内核模块。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/13/RdfguQyJe6DEFnz.jpg" style="zoom: 50%;" /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="212-nodeport"&gt;2.1.2 NodePort&lt;/h5&gt;
&lt;p&gt;NodePort在集群中的主机节点上为Servcie提供一个代理端口，允许从主机网络对Service进行访问。&lt;/p&gt;
&lt;p&gt;在创建NodePort时，kube-proxy也会同时为Service创建Cluster Ip相关的iptables规则，kube-proxy并不不会直接接受主机的端口进入的流量，而是创建相应的iptables规则，通过从该带瘤端口收到的流量直接转发到后端的Pod中。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/13/OQMLzIygXrJE7da.jpg" style="zoom: 50%;" /&gt;
&lt;h5 id="213-loadbalancer"&gt;2.1.3 LoadBalancer&lt;/h5&gt;
&lt;p&gt;K8s支持将Service定义为LoadBalancer类型；LoadBalancer类型的Service创建后，Cloud Provider Controller会将配置下发到Cloud Provider网络中的&lt;strong&gt;四层负载均衡器&lt;/strong&gt;，该负载均衡器负责将外部的流量分发到后面多个节点的NodePort端口上。也就是说外部流量需要依赖NodePort端口才能把流量转发到K8s内部。而LoadBalancer需要依赖各个云服务商提供支持。&lt;/p&gt;
&lt;h5 id="214-ingress"&gt;2.1.4 Ingress&lt;/h5&gt;
&lt;p&gt;当一个应用需要对外提供多个服务时，需要借用Kubernetes Ingress来统一网络入口。其声明了一个应用层的负载均衡器，可以根据HTTP请求的内容将来自同一个TCP端口的请求分发到不同的Kubernetes Service。支持按Http URL进行路由，同时也支持按照请求的Host进行路由。&lt;/p&gt;
&lt;p&gt;Kubernetes使用Ingress Controller来监控Ingress规则，并通过一个七层网关来实现这些要求，一般可以使用Nginx，HAProxy等；由于Ingress是不是在K8s集群中，对外部流量来说，需要配合NodePort和LoadBalancer才能提供对外的流量入口。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/13/tPm73usSKd21DUp.jpg" style="zoom:33%;" /&gt;
&lt;p&gt;在NodePort，Ingress，Pod等不同的接入层面都可以对系统进行水平扩展，以应对不同的外部流量要求。详细的局部细节图如下：&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/13/oAVIRh3PYZHWxpy.jpg" style="zoom: 50%;" /&gt;
&lt;p&gt;&lt;strong&gt;REFERENCE&lt;/strong&gt;:&lt;/p&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/POSIX" target="_blank" rel="noopener"&gt;POSIX - Wikipedia&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://zhuanlan.zhihu.com/p/490585683" target="_blank" rel="noopener"&gt;Docker，containerd，CRI，CRI-O，OCI，runc 分不清？看这一篇就够了 - 知乎 (zhihu.com)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>Kubernetes上的分布式系统</title>
<link>https://liaolile.com/post/tech/distributesystem/kubernetes%E4%B8%8A%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/</link>
<pubDate>Sat, 28 May 2022 16:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/distributesystem/kubernetes%E4%B8%8A%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/</guid>
<description>&lt;p&gt;分布式系统不仅仅是运行时，还是&lt;strong&gt;开发时、构建时、运维时&lt;/strong&gt;；分布式系统需要4个方面的能力，包括生命周期的管理、网络通讯能力、资源绑定能力以及有状态逻辑的处理。&lt;/p&gt;
&lt;p&gt;系统的生命周期能力，我们需要一个可靠且&lt;strong&gt;全自动化的打包和部署、回滚、健康检查&lt;/strong&gt;。能够实现应用在不同节点的分发，且资源隔离、扩展、配置可管理。这些能力就是第一位的基础。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/09/12/RQO89TrqgJL2C4B.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;网络的连接能力&lt;/strong&gt;是分布式系统的第二要素。可靠韧性的连接到其他的服务，无论集群内还是集群外，分布式系统预期有服务发现、负载均衡等能力。同时由于不同的流量策略，需要具备流量转移的能力。服务的韧性在网络方面体现在超时重试、断路器等。围绕网络还要有安全保障，足够的监控、追踪和可观察性。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/08/03/rDEnmNFXhZcy3Kz.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;分布式系统的有能力与不同的API和端点交互，即&lt;strong&gt;资源绑定与其协议不同的数据格式交互&lt;/strong&gt;，甚至从一种数据格式到另外一种数据格式的转换。对于消息数据的点对点pub/sub交互，以及数据的过滤，数据的路由；&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/08/03/CHJf8shcnWpGUIk.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;关于&lt;strong&gt;依赖状态&lt;/strong&gt;的开发人员抽象，分布式系统需要有工作流的管理能力，管理长进程以及短周期的调度任务，依赖分布式缓存，需要具有幂等性和支持回滚。这些均需要考虑系的同内部的已有状态的处理，依赖于开发人员的抽象。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/09/12/noBu75Wh3dNAxOY.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;技术架构的演进从单体到微服务再到云原生架构；&lt;/p&gt;
&lt;p&gt;按照业务领域进行划分出现了微服务，容器和Kubernetes是管理这些微服务的优秀平台。Readiness和Liveness探测在kubernetes对于容器的生命周期管理至关重要，一个是确定应用在启动期间何时可以接受外部流量，一个是检查服务的健康状况；&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LivenessProbe，判断容器是否存活running状态，如果不健康会kill后重启处理；&lt;/li&gt;
&lt;li&gt;ReadinessProbe，判断容器服务是否可用ready状态，ready后的pod才接受来自外部的数据。Service同Pod Endpoint之间的关联关系基于该Pod的Ready状态进行设置；&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="D:\0_leland\blog\blog-image\distributed\distributedSystem-architectrue-history.png" style="zoom:80%;" /&gt;
&lt;p&gt;Kubernetes 可以启动你的应用；它可以将其关闭，然后在不同的节点上移动它。为此，你必须正确执行平台在应用启动和关闭期间告诉你的事件。围绕声明式部署，声明资源需求，部署策略，应用程序同时需要执行来自环境的事件（健康检查、应用就绪度等）；实现整个部署的资源隔离、配置管理、故障隔离；&lt;/p&gt;
&lt;p&gt;Kubernetes中的Pod有两个约束：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pod的部署会确保所有的容器均在同一个节点；各个容器间可以通过localhost进行通信，也可以通过其他的类似文件共享/IPC机制等；&lt;/li&gt;
&lt;li&gt;Pod中的容器生命周期可以不同，分为Init容器和应用容器，Pod启动时，Init容器按顺序一个一个运行，仅前一个成功后一个才运行；应用容器是并行运行的，在整个Pod生命周期中运行；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;K8s内部依赖调谐循环来确保状态和声明一致，将期望的状态驱动到与实际状态。&lt;/p&gt;
&lt;h4 id="ref"&gt;REF&lt;/h4&gt;
</description>
</item>
<item>
<title>云原生可观测性理解</title>
<link>https://liaolile.com/post/tech/cloudnative/%E4%BA%91%E5%8E%9F%E7%94%9F%E5%8F%AF%E8%A7%82%E6%B5%8B%E6%80%A7%E7%90%86%E8%A7%A3/</link>
<pubDate>Tue, 24 May 2022 21:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/cloudnative/%E4%BA%91%E5%8E%9F%E7%94%9F%E5%8F%AF%E8%A7%82%E6%B5%8B%E6%80%A7%E7%90%86%E8%A7%A3/</guid>
<description>&lt;h3 id="0-可观测性"&gt;0 可观测性&lt;/h3&gt;
&lt;p&gt;复杂度以及数据处理量不断增长，为了了解系统的负载状态，我们需要系统有更好的可观测性。出现故障的时候必须要更快的找到问题根本原因并且解决，以满足更严格的服务水平要求。&lt;/p&gt;
&lt;p&gt;越来越多的新应用基于云原生的方式而构建，提高了韧性、性能和安全性，但是同时失去了对于运行这些软件基础设施的控制的风险成本。作为系统owner必须要同时理解应用程序以及基础设施的运行状态。对于系统自身来说，其它均是外部实体，而系统在开发的时候就应该考虑给外部实体的可观测提供便利。这往往意味着编写更多的代码、自动化基础设施的操作并且监控关键的指标。&lt;/p&gt;
&lt;p&gt;一旦系统的可观测能力能够达到一个令人满意的水平，这带来的益处是显而易见的。做到知其然，知其所以然，一切的信息都在掌控之中。这些观测能力的建设，依赖工作理念的改变、工具、目标、工作方法的变化。&lt;/p&gt;
&lt;p&gt;对于可观测系统，其设计和开发中需要依赖遥感数据并且从这些数据中提取加工出有意义的信息。当前&lt;strong&gt;遥感数据&lt;/strong&gt;主要包括：&lt;strong&gt;metrics，logs，traces，events，profiles和crash dumps&lt;/strong&gt;，我们也把这些内容叫做&lt;strong&gt;观测信号&lt;/strong&gt;。每种数据都有它自己的意义和最佳处理方式，如果处理不当就会产生各种新的问题，比如监控的频繁误报、故障扩容等。&lt;/p&gt;
&lt;p&gt;控制论中的Controllability和Observability表示的是&lt;code&gt;可控性&lt;/code&gt;，控制量对状态变量的控制能力，&lt;code&gt;可观测性&lt;/code&gt;，输出量对状态变量的反应能力。可观测性是衡量一个系统仅凭其外部输出来判断其内部运行状态的精确度的指标，给外部实体往往是人，用来观察理解系统状态并且做出反应的功能。&lt;/p&gt;
&lt;p&gt;可观测性是可以用在系统生命周期内的所有阶段，测试新功能、监测环境的韧性，了解你的用户，以及后续产品的路线图。对于观测信号都有不同的收集和测量方法，花费不同的资源来获取、存储和分析，同时提供不同的方法来观测相同的系统，以提供不同的视角来观察同一个技术，它们之间是互补的。&lt;/p&gt;
&lt;p&gt;Metrics以实时、可靠、廉价的监控为中心，是支持快速、可靠告警的基础。Logs是为了更加深入了解系统运行细节，以便获取更多上下文的内容。更多时候的细节来自于请求书，也就是distributed tracing，支持了跨进程的context传播效应和串联效应。同时，也可能通过profiles来检查哪些代码效率低下并且使用了超出预期的资源。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Metrics&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;metrics是数据的数值表现，主要分为已经是数值的数据和被转化为数值的数据。前者比较典型的就是温度、高度等。后者转化为数值的数据，在转化的时候旧丢失了细节，比如计数，其统计的是某个周期的，对于特定的增量发生时间是丢失的。领域专家需要明确选择提取什么，如何提取，这对于数据的如何保留、转化、传输、存储和处理数据的负担大大减少，人们可以借由该metrics指标了解当前的状况。&lt;/p&gt;
&lt;p&gt;metrics最常见的是构建概览和各项细节指标的图表集，每个指标都是一个逻辑计量单元，体现了一段时间之内相关指标的状态。&lt;/p&gt;
&lt;p&gt;进而发出告警或自动化通知到人员或者其他自动化系统。另外也可用于长期的趋势分析和长期计划，同时也能够在时候提供解决和监控潜在问题的建议。&lt;/p&gt;
&lt;p&gt;metrics更多的时候告诉我们“发生了什么”，衡量了关于系统的整体行为和健康状态。但是metrics往往不能告诉我们“为什么”，而是提供了相关问题定位的思路信息，并作为深入排查问题产生原因的出发点。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Logs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;logs是在操作系统、应用程序中执行的过程、活动和操作的一系列文本类的对象流，是离散事件，具备结构化，人类可读的细节数据。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用logs，可以帮助开发者理解和衡量应用程序在开发中及后续发布后的行为方式；&lt;/li&gt;
&lt;li&gt;系统logs，可以记录操作系统本身的事件，可用于相关系统资源类的状态查看；&lt;/li&gt;
&lt;li&gt;安全logs，是为了响应系统上发生的安全事件而创建的。对于系统中关键的内容均可以把其记录进入到安全logs中，往往系统管理员可以配置安全logs中包含哪些类型的事件；&lt;/li&gt;
&lt;li&gt;审计logs，本质上是事件和变化的记录，代表着过程中的谁在什么事件进行了哪些动作，并且响应结果的记录。通常系统管理员会根据业务的需要而决定审计logs搜集什么。&lt;/li&gt;
&lt;li&gt;基础设施logs，在本地或者云上，涉及管理影响组织IT基础的物理设备和逻辑设备，并且可以通过API、系统logs或者其他使用基于主机之上的代理收集的方式。比如往往很多主机上会安装有agent，做大量的数据搜集并且分析。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;logs里的数据也可以转化成其他的可观测信号，包括metrics和traces，同时也可以使用logs分析技术来进行可视化和分析。logs级别是用来表示每条logs数据的重要性，一般常见的ERROR, WARNING, INFO和DEBUG。&lt;/p&gt;
&lt;p&gt;ERROR往往报告的是故障的发生及其原因细节；WARNING是一个需要注意的消息，虽然可能这并不是一个故障；INFO适用于帮助理解系统是怎么运行的；DEBUG是用于每个操作非常详细信息的，其数据量较大，往往仅在故障排查时使用，避免影响存储空间和性能；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Trace&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Traces通常是一组“tracing数据点”或者是一组可以用甘特来表示被称作为span。spans间是高度上下文相关的，并且包含 了初始化它的span信息。这使得分布式系统中不同的参与者（服务、队列、数据库）之间能够建立因果关系。各个参与者之间往往会定义一套标准的trace context进行信息的透传，W3C trace context定义了包含标准HTTP Header和值的格式来传播context信息，context信息唯一标识了分布式系统内的各个请求，还定义了通过添加和传播provider-specific的context信息。&lt;/p&gt;
&lt;p&gt;组件埋点在分布式追踪系统中扮演中扮演重要的角色，负责创建数据点本身以及将context在服务间进行传递。没有context的传播，就无法将传入的HTTP请求与它下游HTTP请求或消息的生产者及消费者关联起来。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Profiles&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;随着云原生应用程序的不断优化，对于细粒度上理解性能指标也愈发重要，一些工具通常会帮我们发现存在的性能问题，而持续收集profiles使我们可以更深入理解某个特定系统遇到某个问题的原因，这些profiles聚焦在理解资源是如何在系统中被分配的，包括CPU Profilers，Heap Profilers，IO Profilers等。Profiling由于消耗太大，之前被认为是不适合在生产系统中添加。随着采样profiling技术的普及，在云环境中变得越来越普遍，而仅仅只是消耗很少的性能。&lt;/p&gt;
&lt;p&gt;tracing是应用于理解应用程序的哪个部分导致延迟问题发生，profiling可以更加深入挖掘并理解那些导致延迟问题存在的原因，另外还可以知道哪些代码使用了最多的服务器资源。运行期生成的profiling数据通常包括精确到行号的统计，是回答从“是什么”到“为什么”的重要数据。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dumps&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;软件开发中，当应用进程异常挂掉后会产生dump文件用于排除程序故障。通常，操作系统会根据一些配置，把进程崩溃时的内存镜像写入dump文件，以便后续分析。Linux内核2.6后，dump文件的收集工作不是操作系统完成，而是 崩溃的进程输出推送到负责写入文件的应用程序的标准输入流中，这个应用程序就是核心dump处理程序，在ubuntu下可以在systemd支持下完成。&lt;/p&gt;
&lt;p&gt;云原生环境下，应用和基础设施的所有者角色不是那么明确，有特权的去访问系统全局配置的权限较低。另外一方面需要给崩溃的应用在pod重启之前就收集核心dump文件并写入持久卷时提供帮助。&lt;/p&gt;
&lt;p&gt;往往系统中的一个事件会产生多个信号，产生metrics增量、出发logs日志记录和开启一个新的span追踪。这意味着与当前特定事件有关的元数据和context在整个系统中都是重复的。对于多信号，我们希望理想的结果是一个整体的互补的可观测系统，希望使用来自另外一个信号的额外信息来补充，而不仅仅是增加了整个系统的数据量和数据的处理难度。&lt;/p&gt;
&lt;h3 id="1-构建可观测系统"&gt;1 构建可观测系统&lt;/h3&gt;
&lt;p&gt;前提条件是：一致的目标元数据被附加到所有的信号内。&lt;/p&gt;
&lt;p&gt;不一致的元数据对于可观测系统是灾难的，即使label之间最微小的差别也会造成很大的麻烦。重新标记或默认是用pull模式会对这有所帮助。&lt;/p&gt;
&lt;p&gt;建立可观测的目的是确保系统的高可用。对于高可用的衡量一般使用如下几个概念：&lt;/p&gt;
&lt;p&gt;SLI 服务水平指标：服务水平精确的量化定义的指标；&lt;/p&gt;
&lt;p&gt;SLO 服务水平目标：能够承受的系统故障频率目标，由SLI服务数据平指标的目标值或者目标区间组成；&lt;/p&gt;
&lt;p&gt;SLA 服务水平协议：规定由SLO不达标造成的后果的商业协议。&lt;/p&gt;
</description>
</item>
<item>
<title>可观测性系统建立</title>
<link>https://liaolile.com/post/tech/cloudnative/%E5%8F%AF%E8%A7%82%E6%B5%8B%E6%80%A7%E7%B3%BB%E7%BB%9F%E5%BB%BA%E7%AB%8B/</link>
<pubDate>Tue, 24 May 2022 21:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/cloudnative/%E5%8F%AF%E8%A7%82%E6%B5%8B%E6%80%A7%E7%B3%BB%E7%BB%9F%E5%BB%BA%E7%AB%8B/</guid>
<description>&lt;p&gt;Prometheus&lt;/p&gt;
&lt;p&gt;Zipkin&lt;/p&gt;
&lt;p&gt;Skywalking&lt;/p&gt;
&lt;p&gt;OpenResty xray&lt;/p&gt;
</description>
</item>
<item>
<title>分布式系统的设计</title>
<link>https://liaolile.com/post/tech/distributesystem/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E7%9A%84%E8%AE%BE%E8%AE%A1/</link>
<pubDate>Tue, 24 May 2022 12:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/distributesystem/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E7%9A%84%E8%AE%BE%E8%AE%A1/</guid>
<description>&lt;p&gt;分布式系统应该具有的架构特性（设计方向）：高并发、可扩展性、高可用性、高性能。同时分布式系统中存在的一致性问题，也需要有对应的解决方案。&lt;/p&gt;
&lt;p&gt;高并发并不是一种技术，而是系统要面临的技术技术场景。在这个场景下，确保高并发时的用户体验，系统不应该出现错误且以极快的速度给用户响应。可用性、可扩展性、高性能就是用于定量分析高并发系统的3个视角。&lt;/p&gt;
&lt;h4 id="分布式系统的高可用性"&gt;分布式系统的高可用性&lt;/h4&gt;
&lt;p&gt;目标是为了让系统尽可能不发生错误，或者发生错误后的损失降到最低。系统运行时间是定量，不可用时间是变量。&lt;/p&gt;
&lt;p&gt;发布/故障/压力/外部依赖导致可用性问题&lt;/p&gt;
&lt;p&gt;变化数量*变化产生故障的比例*故障的影响*故障持续的时间&lt;/p&gt;
&lt;p&gt;初始设计按照20/10/5来分别设计、开发、发布，这里说的数字是实际流量的倍数。&lt;/p&gt;
&lt;p&gt;容错设计，单点故障、特性开关、服务分级、降级设计、超时重试&lt;/p&gt;
&lt;p&gt;隔离策略：进程、用户、集群、租户、物理、逻辑&lt;/p&gt;
&lt;p&gt;熔断：失败时候主动切断避免灾难发生&lt;/p&gt;
&lt;p&gt;流控：流控算法/流控策略（在什么地方做流控）&lt;/p&gt;
&lt;p&gt;容量预估：全链路压测明白系统的当前能力现状，而不是单接口、单业务，生产环境直接压；&lt;/p&gt;
&lt;p&gt;故障演练：故障模式梳理以及实践验证容灾方案&lt;/p&gt;
&lt;p&gt;数据迁移：逻辑分离/物理分离&lt;/p&gt;
&lt;h4 id="分布式系统的高性能"&gt;分布式系统的&lt;strong&gt;高性能&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;目标是为了让尽可能多的用户，用尽可能少的时间得到系统的响应。任务目标是定量，任务完成耗时是变量。&lt;/p&gt;
&lt;p&gt;内存IO时间+网络IO时间+CPU时间+磁盘IP时间+等待时间&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;响应时间/吞吐量/负载敏感度/可伸缩性&lt;/p&gt;
&lt;p&gt;附在敏感度为系统响应是随时间变化的程度，需要可量化。用户请求过多的时候，系统响应时间是如何的一个衰减速度。&lt;/p&gt;
&lt;p&gt;可伸缩性为系统扩容增加资源对于性能的影响，可量化衡量，即吞吐量扩1倍，需要多少服务资源的衡量；&lt;/p&gt;
&lt;h4 id="分布式系统的可扩展性"&gt;分布式系统的&lt;strong&gt;可扩展性&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;目标是为了支撑可用性和高性能，在一些特殊情况下，不得不对系统系统进行调整时，能够以低成本的方式完成的能力。&lt;/p&gt;
&lt;p&gt;AKF扩展立方体&lt;/p&gt;
&lt;p&gt;可以沿着X/Y/Z轴三个方向进行扩展。&lt;/p&gt;
&lt;p&gt;X轴扩展也叫水平扩展/横向扩展，通过复制实例（往往无状态），前端对流量进行负载均衡，分摊整体压力为目的进行扩展。&lt;/p&gt;
&lt;p&gt;Y轴扩展依据服务或者资源扩展，依据服务拆分，各个微服务依据当前能力独立进行横向扩展，降低当前系统的复杂度&lt;/p&gt;
&lt;p&gt;Z轴扩展依据当前的业务查询或计算结果进行拆分，即分片的思想。基于分区扩展，扩展性更强，突破单张表的数据规模上限，但是对于数据迁移复杂；&lt;/p&gt;
&lt;p&gt;数据库的X/Y/Z轴扩展：主从复制、分库/分表、分片sharding&lt;/p&gt;
&lt;h4 id="分布式系统的一致性设计"&gt;分布式系统的&lt;strong&gt;一致性设计&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;事务：原子性、一致性、隔离性、持久性&lt;/p&gt;
&lt;p&gt;CAP定理：一致性/可用性/分区容错性，三选二&lt;/p&gt;
&lt;p&gt;BASE理论：强一致性、弱一致性、最终一致性；依据业务的考量来决策，不一致性场景下时候是基本可用、不可用、可接受；&lt;/p&gt;
&lt;p&gt;Quorum机制：强一致性的保障在写入数据的时候，所有节点成功后才算成功，此时写性能较差；转变思路为在读的阶段再决策，确保每次均能读到最新的数据。Quorum机制满足公式：备份个数N&amp;lt;成功写入W个+读取R个备份&lt;/p&gt;
&lt;p&gt;租约机制Lease：为了实现一致性，确保节点中有一个leader，leader负责数据写入、follower负责数据读取，管理节点M通过心跳判断各个节点，指定Leader，Leader故障后重新选取Leader。&lt;/p&gt;
&lt;p&gt;脑裂：Paxos、Raft、Lease算法确保&lt;/p&gt;
&lt;p&gt;分布式系统最终体现在&lt;em&gt;数据的一致性&lt;/em&gt;（严格一致性、顺序一致性、因果一致性）：&lt;/p&gt;
&lt;p&gt;X轴扩展数据可以是多个副本，多个副本不同的物理存储，故障时可以访问正常的副本数据；需要解决数据写入性能问题&lt;/p&gt;
&lt;p&gt;Z轴扩展对数据进行分区，即Sharding；&lt;/p&gt;
&lt;p&gt;分布式系统的用户（泛化）一致性模型（需要有标识，且唯一）：&lt;/p&gt;
&lt;p&gt;单调读一致性，单调写一致性、写后读一致性、读后写一致性&lt;/p&gt;
&lt;p&gt;弱一致性：写入一个数据成功后，在数据副本上可能读出来，也可能读不出来，不保证每个副本的数据一定一致；&lt;/p&gt;
&lt;p&gt;最终一致性：写入一个数据后，在其他副本有可能读不到最新值，单在某个时间窗口之后保证能最终读到；（重试机制、本地日志复制如binglog、可靠事件模式、Saga事务模型，TCC事务模型）&lt;/p&gt;
&lt;p&gt;强一致性：数据一旦写入成功，任何副本上在写入后的任意时刻都能读到最新值；实现模型：两阶段提交/三阶段提交&lt;/p&gt;
&lt;h4 id="分布式系统中的八大谬误"&gt;分布式系统中的八大谬误&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;网络是可靠的&lt;/p&gt;
&lt;p&gt;实际不是可靠的，应用系统中需要做的事情可能有：retry，acknowledge import messages, identify/ignore duplicates, record messages, verifiy message integrity。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;传输是无延迟&lt;/p&gt;
&lt;p&gt;延迟指数据从一个地方传递到另一个地方需要的时间，这中间带宽决定了同时可以传输多少数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;带宽是无限的&lt;/p&gt;
&lt;p&gt;其实不是，随着带宽的增长，我们传输的数据量也在增加，同时传输就存在丢包的问题。在信息的传递和延迟之间是要trade-off。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;网络是安全的&lt;/p&gt;
&lt;p&gt;通往网络的安全是多层的，包括基础设施、网络传输和应用层等；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;拓扑是不变的&lt;/p&gt;
&lt;p&gt;系统中不应该依赖特定的路由或节点，需要同时提供位置透明性和发现服务&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;传输是无成本的&lt;/p&gt;
&lt;p&gt;我们从应用层到传输层的数据传递，需要对数据进行编码，这需要消耗时间和计算资源。而设置和运行网络都是需要代价，需要金钱购买。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;网络是同构的&lt;/p&gt;
&lt;p&gt;不应该在应用层去依赖一些自营的协议，而是通用的协议。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;只有一个管理员&lt;/p&gt;
&lt;p&gt;当没有出现问题的时候，我们不需要管理员。但是一旦问题发生，就会抓狂的需要。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="ref"&gt;REF&lt;/h4&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/jboner/2841832" target="_blank" rel="noopener"&gt;Latency Numbers Every Programmer Should Know (github.com)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>18-女儿与我：神奇妙招（下）</title>
<link>https://liaolile.com/publication/18%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%A5%9E%E5%A5%87%E5%A6%99%E6%8B%9B%E4%B8%8B/</link>
<pubDate>Mon, 23 May 2022 21:48:04 +0000</pubDate>
<guid>https://liaolile.com/publication/18%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%A5%9E%E5%A5%87%E5%A6%99%E6%8B%9B%E4%B8%8B/</guid>
<description>&lt;p&gt;对于喂药，“老母亲”心态崩了。我曾经就为了喂那几勺药水，就跪着她坐得椅子旁，差点抬不起身子。当她吃完所有药水，我也觉得值得，毕竟生病的时候关键还看药效，父母的急切之心，并不允许光靠孩子自身熬出免疫球蛋白。&lt;/p&gt;
&lt;p&gt;当数数不管用了，还有什么招式能让小丫头认同且又可以达到我的目的？在还没解锁新招数前，我巴不得每天请假在家护送每一次药水进到小丫头肚里。可生活还得继续呀，正愁着如何是好，结果我的母亲发来了一条视频。&lt;/p&gt;
&lt;p&gt;“妈妈，你看小丫头今天自己吃药了。”只见我母亲戴着口罩（在照顾小丫头时被传染了，为了不再二次传播，在家里也戴着口罩），左手抱着小丫头放在腿上，右手拿着勺子准备喂药吃。&lt;/p&gt;
&lt;p&gt;小丫头泯着嘴摇摇头，略有想说些什么的样子。&lt;/p&gt;
&lt;p&gt;“还有什么要谁给妈妈的？”我母亲似乎看出了小丫头的心思。&lt;/p&gt;
&lt;p&gt;小丫头开始咿咿呀呀，估计是表达自己也不是很情愿，但只能这样视频外的妈妈才会放心。&lt;/p&gt;
&lt;p&gt;第一勺，苦得皱起了眉头，立马伸出舌头，要求喝一口凉白开。&lt;/p&gt;
&lt;p&gt;第二勺，小丫头开始能接受，并主动拿着小水杯喝白开水。&lt;/p&gt;
&lt;p&gt;第三勺、第四勺……&lt;/p&gt;
&lt;p&gt;“太棒了，全部喝完了，给妈妈看看舌头还黄不黄？”小丫头古灵精怪地伸出伸头对着视频笑。&lt;/p&gt;
&lt;p&gt;我反复看着，内心充满着欣慰之情。说是小丫头一夜长大了，还是说这个拍视频给我看的招数生效了呢？暂且就认为是后者罢了。&lt;/p&gt;
&lt;p&gt;因为小丫头对我的信赖，希望让妈妈放心，所以明白了生病了要吃药。再次之后，若我生病了，小丫头还会对我说，“你是不是严重了？要吃药才能好。”&lt;/p&gt;
&lt;p&gt;“我现在不怕吃药了，我不怕苦，我很勇敢。”&lt;/p&gt;
&lt;p&gt;你确实很勇敢，妈妈看到了你在每一天的日子中不断地接受新的事物和认知，不断向前冲。&lt;/p&gt;
</description>
</item>
<item>
<title>17-女儿与我：神奇妙招（上）</title>
<link>https://liaolile.com/publication/17%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%A5%9E%E5%A5%87%E5%A6%99%E6%8B%9B%E4%B8%8A/</link>
<pubDate>Sat, 21 May 2022 11:54:04 +0000</pubDate>
<guid>https://liaolile.com/publication/17%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%A5%9E%E5%A5%87%E5%A6%99%E6%8B%9B%E4%B8%8A/</guid>
<description>&lt;p&gt;“再不来，我要是数数了。”&lt;/p&gt;
&lt;p&gt;“1，2…”&lt;/p&gt;
&lt;p&gt;每一对父母与孩子之间总是会有只可意会，不可言传的沟通方式，这是实战经验总结的智慧。&lt;/p&gt;
&lt;p&gt;我的做法确实会有悖于理论上对孩子的最优方式，相比不少育儿的公众号推送内容，是不建议在小孩不听话的时候数数的，因为这样带给孩子的有效信息很少，只是记得数数就是一件很严重的事儿。&lt;/p&gt;
&lt;p&gt;我也了解，但在与孩子的想法有冲突的时候，必须先传递你站在个人的角度觉得现在这件事情做得不对，你已经在变得严肃了，若孩子跑到离你很远的地方是没办法进一步有效沟通的，所以我得先把这个信号发出去给小丫头。&lt;/p&gt;
&lt;p&gt;“再不过来刷牙，妈妈就要数数了。”并且表情很夸张的严肃。&lt;/p&gt;
&lt;p&gt;“1…”&lt;/p&gt;
&lt;p&gt;刚开始还没数到数字三，你便会听到小脚丫从远到近短促的吧嗒吧嗒跑来你身边，说明我的招数生效了，小丫头被我“骗”来了。之后你就可以长篇大论告诉她，“妈妈很生气，因为你没有及时过来刷牙，所以感到生气了，才数数叫你过来，如果你马上过来或者自己主动刷牙，妈妈就不用数数了。”&lt;/p&gt;
&lt;p&gt;看到她认可的眼神，我知道我又得逞了，用孩子可以理解的语言和逻辑持续灌输，“小丫头，知道我们为什么要刷牙吗？因为我们吃的山楂（选择她最近感兴趣的食物效果更好）、饭菜被牙齿咬碎之后，大的吞下去到肚子里了，但是还有很多小小的留在了牙齿上，然后牙齿上会有小细菌就吃这些碎碎碎碎的食物。”&lt;/p&gt;
&lt;p&gt;小丫头一脸好奇的看着我，半信半疑的感觉，不过我想着她肯定在联想是哪个动画片段里有说过。&lt;/p&gt;
&lt;p&gt;“你看，吐出来的泡沫为什么会有泡泡啊？”我指着小丫头刚吐出来的牙刷泡沫。&lt;/p&gt;
&lt;p&gt;“是”，小丫头完全相信了。&lt;/p&gt;
&lt;p&gt;“那我们要不要刷牙呀？”&lt;/p&gt;
&lt;p&gt;“要，要不然小细菌在牙齿上吹泡泡。”&lt;/p&gt;
&lt;p&gt;“对呀，刷第二次的时候，是不是泡泡越来越少了呀？”我再次指着盥洗池里的牙膏泡泡。&lt;/p&gt;
&lt;p&gt;“是。”&lt;/p&gt;
&lt;p&gt;“因为刷了牙，牙齿上的细菌会越来越少，所以没办法吹这么多泡泡，所以泡泡就越来越少了。”&lt;/p&gt;
&lt;p&gt;在孩子的世界里，没有所谓，并很快正确逻辑，任何语言里提及到的都会是真的。他们相信小细菌可以欢乐的吹泡泡，就像他们在公园里买的泡泡机一样，此时的小细菌就是小朋友。&lt;/p&gt;
&lt;p&gt;不过也有失灵的时候，比如说小朋友最不喜欢的吃药。前段时间小丫头因为细菌感染引起的感冒发烧，医生开的药都是苦的，所以让她直接吃药真的宛如到天上摘星星。&lt;/p&gt;
&lt;p&gt;“123”，在这个场景下完全不起作用，哪怕你重新数数，数到一百都没有用。&lt;/p&gt;
&lt;p&gt;也因此另一个招数解锁了。&lt;/p&gt;
</description>
</item>
<item>
<title>16-女儿与我：这么近，那么远</title>
<link>https://liaolile.com/publication/16%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%BF%99%E4%B9%88%E8%BF%91%E9%82%A3%E4%B9%88%E8%BF%9C/</link>
<pubDate>Sat, 07 May 2022 23:55:04 +0000</pubDate>
<guid>https://liaolile.com/publication/16%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%BF%99%E4%B9%88%E8%BF%91%E9%82%A3%E4%B9%88%E8%BF%9C/</guid>
<description>&lt;p&gt;从小丫头生病的这些天，感觉我就是她的精神支柱，哪怕是被湿的毛巾敷着额头，都偏着头看向我。那湿润的小眼神，足以说明“妈妈”在她心目中的地位。但唯一有一点，不允许我离开她半步，哪怕她已经昏昏欲睡，也要靠在我身边，好似偏离主航道轨迹，无法安心入睡。&lt;/p&gt;
&lt;p&gt;想着生病了一天的小丫头，我在悉心照顾一天，说不定便痊愈了。索性请了假，坚定自己的选择，这个时候就应该陪伴最重要的人。&lt;/p&gt;
&lt;p&gt;从晨起到午休，由于小丫头一定要我出现在她的视线范围，若看不到便会嚎啕大哭。我可经不起她激动哭泣，避免又因为情绪的原因导致体温升高，所以我把便携式电脑搬到了卧室边，一边处理工作上的事情，一边让她看到我在她身边。小丫头也很乖，她跟我说“妈妈，你做事，我就在你旁边，不会打扰你的”。转头往向这病怏怏的小丫头，依旧是这么乖巧。“妈妈提高效率，赶紧陪我的小丫头，好不好”，她很认真的点点头。&lt;/p&gt;
&lt;p&gt;可就是这样，一旦开始执行工作任务，就像一个黑洞，让你没办法逃离。小丫头在我身后趴着，估计也有好一会，也不知道什么时候睡着了。&lt;/p&gt;
&lt;p&gt;由于项目点有关键任务，我不得不组织拉会讲解方案，为了不打扰已熟睡的小丫头，我便转向了书房。期间也就一个小时不到，小丫头可能是因为不舒服醒了，看到我不在身边，以为我又离她而去 便在卧室里委屈地哭。我母亲赶紧放下手中的活儿，去哄小丫头了，也许是说了什么，书房的门轻轻地打开了，一个小小的头探了进来，双眼眶红红的，就想看我一眼，确认我还在家里。&lt;/p&gt;
&lt;p&gt;迟钝的发现我应该向小丫头汇报我的行程并经过她准许比较好，下一次再去书房的时候，小丫头还特别叮嘱我，“你不要关门，开着门，让我看到你，啊”。&lt;/p&gt;
&lt;p&gt;这让一天下来我感觉，我和小丫头就像被一条线牵着，彼此这么近，不允许超出半步。我去哪里，小丫头都跟着去哪里。也许是建立了最高的信任，小丫头中午再次高烧的时候，终于肯自己主动吃药了，颤抖的小手拿着小药瓶盖，倔犟地要求必须妈妈抱着才吃，只要能吃我去摘月亮都行。&lt;/p&gt;
&lt;p&gt;吃下了药，温度慢慢降下来，我也就舒心了。可我还是高兴太早，晚上九点左右再次升温，着急的我完全不知道如何是好，干脆直接去发热门诊，不管核酸还是什么，这次一定要去，不能拖了。&lt;/p&gt;
&lt;p&gt;到了指定医院的发热门诊，我就像是个没见过世面的路人甲，一个小孩只能由一个陪同者问诊。毕竟发热门诊就是管控区，没有专业的核酸检测结果是不允许出来的（核酸检测结果以踏入管控区的那一刻做的为准），也就意味着整个问诊和治疗过程需要四到六个小时，那么小丫头回到家也就是凌晨四五点了。&lt;/p&gt;
&lt;p&gt;没有任何经验的我们，只带了一件外套、一壶水、一袋纸巾，还在门外讨论是否要去问诊，就纠结了半天。后来还是以治病为主，让小丫头的爸爸带着，而我和我的母亲则回家等待。因为是发热门诊，不允许其他人在外逗留的。&lt;/p&gt;
&lt;p&gt;在决定的那一刻，小丫头被爸爸抱着，缓缓走去门诊入口，而我和我的母亲就这么看着走进去的身影，第一次我离我的小丫头那么远。每一次生病我都陪着她，只要我在，小丫头就会变得很勇敢，那这一次呢？她会不会一样勇敢？会不会靠着我的肩膀上娇气地哭着？会不会想我呢？&lt;/p&gt;
&lt;p&gt;不过我等着也是徒劳，说不定也只是我的多虑，小丫头无论在爸爸还是妈妈身边，都一样勇敢和坚强，而我这个时候就是做最好的后盾，保护好自己才可以保护好我的小丫头。&lt;/p&gt;
</description>
</item>
<item>
<title>15-女儿与我：我们一起生病</title>
<link>https://liaolile.com/publication/15%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%88%91%E4%BB%AC%E4%B8%80%E8%B5%B7%E7%94%9F%E7%97%85/</link>
<pubDate>Fri, 06 May 2022 22:31:04 +0000</pubDate>
<guid>https://liaolile.com/publication/15%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%88%91%E4%BB%AC%E4%B8%80%E8%B5%B7%E7%94%9F%E7%97%85/</guid>
<description>&lt;p&gt;前几天还说着立夏了，可以凉爽一番，结果还没开始享受夏天的酷爽，我和小丫头就手拉着手躺在了床上。&lt;/p&gt;
&lt;p&gt;前几天口干舌燥，自以为是的认为是节气带来的“福利”，实际上是，我们感冒了。也许是前几天降温受凉了，也许是太着急拥抱冰棍，总之，现在我和小丫头手拉着手躺在了床上。&lt;/p&gt;
&lt;p&gt;晨起后，用手探测小丫头额头上的温度，不冷不热，没有继续发热的迹象，只是有点赖床，那就让她在家多休息一天再去幼儿园吧。我也有点咽喉不适，估摸着扁桃体发炎，但没有发热，曾经也出现过这种情况而“失声”的。努力喝了很多降火的冲剂，才麻溜地说话了。&lt;/p&gt;
&lt;p&gt;这个时候的普通感冒，都足以让身边的人感到恐惧，并划清界线。不仅如此，就连我自己都默默看了几回手中刚出来的核酸检测结果。&lt;/p&gt;
&lt;p&gt;中午吃饭时间，母亲的一个电话，让我得知小丫头发热到39摄氏度，还是那样不肯吃药，只吃了点点白馒头和半个猕猴桃。正通电话下来一会切换父亲的声音，一下子是母亲，然后大部分都是他们在劝小丫头吃药的说话声和来回拿手机的摩擦声。估计俩老是凌乱了，不吃药的小丫头让他们不知所措，“我们已经把接待发热病历的医院找好了，若还是持续发热，那必须得去趟医院了，哪怕吊针也好”。&lt;/p&gt;
&lt;p&gt;母亲说小丫头只听我的，所以想着让我电话里好好跟她说说，我从语音切换成视频通话，画面里的小丫头额头上敷着为了降温的湿棉纺布，衬托着小丫头的脸更消瘦了。小小的眼睛一动不动地看着我，泪汪汪的，小嘴撅着。估计灌药后的她很委屈，但是又没有精神说话，只是听着我扯着嗓子说“吃药了就不用去医院扎手指、打针”。&lt;/p&gt;
&lt;p&gt;说实话，不是因为小丫头，估计我不会准点下班。急切地心情和呆滞的头脑形成鲜明对比，我想陪着她，我感受到中午她需要我的小眼神，虽然我不是医生，也不是护士，更不是灵丹妙药，但也许我的陪伴和鼓励，是小丫头最需要的。所以，我和小丫头手拉着手躺在了床上。就这样陪着她躺着，她在我身边玩着贴纸，而我牵着她的小手睡着了，温度越来越接近。&lt;/p&gt;
</description>
</item>
<item>
<title>14-女儿与我：三色车</title>
<link>https://liaolile.com/publication/14%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%B8%89%E8%89%B2%E8%BD%A6/</link>
<pubDate>Sat, 30 Apr 2022 19:30:04 +0000</pubDate>
<guid>https://liaolile.com/publication/14%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%B8%89%E8%89%B2%E8%BD%A6/</guid>
<description>&lt;p&gt;今天在商场的装饰品，更具体的说是玩具店里陈列了好多辆不同形态或色号的模型车。&lt;/p&gt;
&lt;p&gt;小丫头就只是在这家店门前走了两回，便看中了一辆由红、黄、蓝三种颜色装饰的玩具车。最后一次经过的时候，我还看了一眼，心里想着，说不定小丫头喜欢。&lt;/p&gt;
&lt;p&gt;果真，我们进入餐馆就餐时，小丫头便开始哭着对我说，“妈妈，我想要那辆车车”。&lt;/p&gt;
&lt;p&gt;“我们吃完饭再去，好不好？”&lt;/p&gt;
&lt;p&gt;小丫头不肯，一定要马上去。我便想起了小的时候，我跟妈妈手拉着手饭后散步，路上经过一家布艺玩具店，橱窗上的一只黑白相间的布娃娃特别吸引我，这是一只斑马布偶。&lt;/p&gt;
&lt;p&gt;不太记得是什么原因，我的母亲没有在当时给我买下这个布娃娃，也许对于那个时候经济、家庭情况，不允许再额外支付非必需品。我也许是在店门口闹过，跟母亲提过必须要买的诉求，第二天我还是坚持要买下这只布娃娃，也许我母亲有批评过我，但拿到斑马布娃娃的时候，我记得那份喜悦，对我而言独一无二的珍贵。这也是长大后母亲告诉我的故事。&lt;/p&gt;
&lt;p&gt;而我的小丫头无疑完美复制了我的基因，我明白小丫头的心思，估计和我小时候一样的。&lt;/p&gt;
&lt;p&gt;我还在纳闷是什么时候车子，只记得是名牌车子的模型车。再仔细一想，明白了，应该也是我青睐的那家店里陈列的玩具模型车。&lt;/p&gt;
&lt;p&gt;二话不说，牵着小丫头的手奔向了那家店，我相信她在奔跑的瞬间是愉悦并期待着的。果真她选择了陈列在架子上的三色车，我果然了解小丫头。之后我告诉她，“要好好爱惜这独一无二的车子，因为你而独一无二”。&lt;/p&gt;
&lt;p&gt;这是一款据了解号称是可以玩一辈子的玩具车，我并没有在意物品本身的创作意图，但此刻对于小丫头来说，这是她在塑造自己最初爱好的模样。&lt;/p&gt;
&lt;p&gt;晚上临睡前，小丫头还特意提醒我，要把她的赛车拿给她，她想抱着一起睡。也不愿意把这辆赛车分享给其他小朋友，可见她是有多喜爱。&lt;/p&gt;
</description>
</item>
<item>
<title>13-女儿与我：生病了</title>
<link>https://liaolile.com/publication/13%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%94%9F%E7%97%85%E4%BA%86/</link>
<pubDate>Tue, 26 Apr 2022 23:18:04 +0000</pubDate>
<guid>https://liaolile.com/publication/13%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%94%9F%E7%97%85%E4%BA%86/</guid>
<description>&lt;p&gt;折腾了一晚上，小丫头还是生病了。&lt;/p&gt;
&lt;p&gt;细数从第一次生病到现在，小丫头还真没有吃过药，都是倔犟地扛着，直到昨天吐得难受（听我母亲描述，吐了两次，眼泪鼻涕都出来了），对着我母亲说“姥姥，我还是吃药吧”。想必小丫头一定是很难受了，要不然怎么会改口。&lt;/p&gt;
&lt;p&gt;昨晚从接到母亲电话后，那回家的路途让我觉得走得那么长，恨手里拿着的就是让小丫头舒服的药盒，恨不得飞快赶到家里。&lt;/p&gt;
&lt;p&gt;回到家后，只见我母亲一人在清理家里的沙发，小丫头应该是睡了，心里的石头才肯放下。急忙走进房里，看着小丫头翻了个身，睁开了黑黝黝的小眼睛望着我，慵懒无力地看着我，“妈妈，抱抱”。&lt;/p&gt;
&lt;p&gt;我赶忙地陪她躺着，抚摸着她的小脑袋瓜子，轻轻地说，“妈妈回来了”。&lt;/p&gt;
&lt;p&gt;孩子在生病的时候，好似特别依恋妈妈。小丫头就是这样的孩子，示意着让我陪她躺着，小手搂在我的肩膀上，也许还是肚子胀或者吐完后肚子饿了，几分钟内不断翻来覆去 每次都要确认一下我是否还在她的身边躺着，生怕我一下子消失了。&lt;/p&gt;
&lt;p&gt;有几次，我看着她已经睡熟了，就想着赶紧帮母亲做完家务、洗个澡，好好陪着小丫头睡上一觉。母亲在家估计也忙坏了，她可是最怕在带小丫头的时候生病，一是担心我们责怪，二是护理相关的经验也觉得赶不上时代，生怕出错。这些我一直看在眼里，所以只要我在家能多做就多做，且也是本来应该的劳动主体。折着衣服，突然听到小丫头“哇”地哭了，我连忙跑到昏暗的卧室里，只见小丫头坐在床上，戳着眼睛哭。喔，她定是觉得我上班去了，说好陪着她一起睡的，一转眼又看不到我的她，很慌张。&lt;/p&gt;
&lt;p&gt;稍作安抚后，这次小丫头直接用小手紧紧拉着我粗糙的手，只要一动，她便会睁眼看着我。“我不能动，会影响她休息的”，我只好心里不断提示自己，等找到合适的机会再继续忙活手头上的家务活吧，这个时候小丫头在心理上，是很需要妈妈的安抚的。&lt;/p&gt;
&lt;p&gt;隔了一宿，第二天看着精神状态很好，并且是小丫头叫我起床的，“妈妈，我们起床吧”。&lt;/p&gt;
&lt;p&gt;我以为一切都往更好的方向发展，比如小丫头一下子痊愈了。可惜在吃过早餐后，小丫头还是吐了，吐出的是白稀饭，却点触着我内心的疼痛。&lt;/p&gt;
&lt;p&gt;“我不上班了，马上带你去医院。”必须，马上，出动。&lt;/p&gt;
&lt;p&gt;在问诊的时候，医生问“肚子疼不疼，哪里会感觉不舒服”，小丫头虽然是患者，但全程她始终只看着我，不说话。我从她的眼神中知晓了，我现在就是她的代言人。这也是成为妈妈后的一个天生具备的能力，孩子的事情就是自己的事情，描述得天衣无缝，宛如我就是当事人。&lt;/p&gt;
&lt;p&gt;去医院检查，必定会抽血，这也是几次经历无厘头的总结。这不，小丫头本次还是要验血，且是扎手指的那种末梢采血方式。&lt;/p&gt;
&lt;p&gt;在走到采血窗口的时候，小丫头还一个劲的对我说要用针管的方式抽血，因为上一次她勇敢地经历过。她很果断把小手伸出来，并且要求我抱着她，“妈妈，你要抱住我”。结果护士抓着手指的时候，她觉得不对劲了，完全不是她想要的采血方式，一下子就哇哇哭了起来。安慰了好久，她才肯停止哭声，可能也是在怪我为何没有按照她的意思执行，虽百般不愿意，但是仍旧很听医生和护士的话，无名指紧紧压着一小团白色棉花，一动也不动。&lt;/p&gt;
&lt;p&gt;拿到化验结果后，回到问诊室给医生查看化验报告。因为有人问诊，所以我特意在门外等候着，被我抱着的小丫头说，“好奇怪呀，我们为什么要站在这里呀？”&lt;/p&gt;
&lt;p&gt;“因为一个房间里只能有一个小朋友，我们进去后，就有两个小朋友了。医生只能给一个小朋友看病噢。”&lt;/p&gt;
&lt;p&gt;“我不要看病，我想回家。”看得出来小丫头还是挺害怕的，担心医生又给她抽一次血。&lt;/p&gt;
&lt;p&gt;回去的路上，小丫头一直很口渴，因为从呕吐完到在医院问诊，已经有一个小时了，忙着咨询的我忽略了喝水的事情。这次是小丫头主动对我说，“妈妈，我想喝水”，平时都是定时提醒她喝水，她是被动喝水。&lt;/p&gt;
&lt;p&gt;小丫头依旧记得医生的叮嘱，一次喝几口，一次不能喝太多水，避免再次呕吐。她真的是一点点地喝，间断性地喝。原来在小丫头眼里，医生的话还是很好使的，至少中午和晚上吃饭的时候，她还记着自己不能一次吃太多，对着我母亲说小“医生说了，一次不能吃太多。我吃了米饭，肚子会痛的”，好吧，就算是一个非常适宜的借口吧。&lt;/p&gt;
&lt;p&gt;我只希望小丫头能快快好起来，健康快乐成长是一辈子父母对孩子的期许。&lt;/p&gt;
</description>
</item>
<item>
<title>12-女儿与我：打电话</title>
<link>https://liaolile.com/publication/12%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%89%93%E7%94%B5%E8%AF%9D/</link>
<pubDate>Sun, 24 Apr 2022 20:24:04 +0000</pubDate>
<guid>https://liaolile.com/publication/12%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E6%89%93%E7%94%B5%E8%AF%9D/</guid>
<description>&lt;p&gt;小朋友是一个善于创造与魔法的群体，他们会让你的烦恼烟消云散，会让你对世间万物又充满着美好的向往；还会让你想回到过去，试着将你所有爱的人定格在永恒之中。&lt;/p&gt;
&lt;p&gt;周末在家只要闲下来，我便会黏着小丫头。如果她坐在沙发上，我便会坐在她旁边的位置，为了更方便地与她玩玩具；如果她坐在她专属的书桌旁，我便会坐在她身后，为了更好地教她画画。看上去是小丫头跟着我屁股后面转，实际上我才是她的“跟屁虫”。&lt;/p&gt;
&lt;p&gt;我的母亲也如小时候一般疼爱我，每到周末都恨不得给我做可口的饭菜。我享受着这般母爱，便又将自己的这份爱传递给我的小丫头。&lt;/p&gt;
&lt;p&gt;这个周末也不例外，小丫头坐在我的身边玩着玩具车，一个电话打破了我们玩游戏的节奏。&lt;/p&gt;
&lt;p&gt;“您好，您的生鲜已经送到小区门口，麻烦尽快下来获取。”因为疫情防控，快递物件只能放在小区正门口外，由快递小哥电话知会收件人下楼取快件。&lt;/p&gt;
&lt;p&gt;全然不知快递来路的我，条件反射想到了肯定是我母亲网购的东西，“老妈，又是什么快递，怎么会有生鲜？”&lt;/p&gt;
&lt;p&gt;“可能是你爸寄过来的鸡肉，你打个电话问问。”还在厨房里忙着洗菜、备菜的母亲给我下了个电话指示。&lt;/p&gt;
&lt;p&gt;等待亲人接电话，是一种说不出的幸福感，当然要是一直不接电话也会产生焦虑不安。“老爸，你寄了鸡肉过来？”&lt;/p&gt;
&lt;p&gt;“是的，你看看有没有坏，拿到后要立马放冰箱，用水煲汤吃很鲜美。”这是我父亲对我和小丫头的爱。&lt;/p&gt;
&lt;p&gt;“来，跟姥爷说说。”紧接着我把电话贴在小丫头的耳边。&lt;/p&gt;
&lt;p&gt;小丫头直接抢了过来并对着电话说，“姥爷是什么？”&lt;/p&gt;
&lt;p&gt;“姥爷是妈妈的爸爸。”已经听到我父亲在电话里的大嗓门。&lt;/p&gt;
&lt;p&gt;“爸爸出去啦。”小丫头跟个小大人似的，不紧不慢回答着。&lt;/p&gt;
&lt;p&gt;“哈哈哈哈哈哈哈哈…”当时电话里、厨房间都笑不成活了，我母亲还重复了几次小丫头的回答内容，我也是捧腹大笑，一下子眼里充满了激动的泪水。&lt;/p&gt;
&lt;p&gt;小丫头非常娴熟地回答，看似平凡，却惹人喜爱。她在向我们抛出神奇的魔力，让我们在不同空间用心连成了一条线。说罢，小丫头看着我们，自己也乐了起来，无论她是不是真的知道我们在乐什么，只要此刻小丫头也是开心快乐的，就足矣。&lt;/p&gt;
</description>
</item>
<item>
<title>11-女儿与我：吃药</title>
<link>https://liaolile.com/publication/11%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%90%83%E8%8D%AF/</link>
<pubDate>Sat, 23 Apr 2022 17:59:04 +0000</pubDate>
<guid>https://liaolile.com/publication/11%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%90%83%E8%8D%AF/</guid>
<description>&lt;p&gt;沿着人类群体生活自然发展规律，我也顺利地步入为人之母。&lt;/p&gt;
&lt;p&gt;从怀胎十月，到神奇的小生命伴着哇哇哭声降落到人世间。当护士将这可爱的小天使包裹着襁褓放在我的左手臂上的瞬间，就像是被定格了一般。第一次感受到一个生命在我的手臂上悦动，很暖和、很真实，黑黝黝的小眼珠像是在试探世界的温度，是否跟妈妈肚子里一般温暖。&lt;/p&gt;
&lt;p&gt;这就是我的小宝贝吗？实在太可爱了，跟第一次B超结果报告里的小眼睛一样，只是眼前的更加清晰，我想我永远都记住这黑黝黝的小眼睛。&lt;/p&gt;
&lt;p&gt;看着她极力吮吸着襁褓，突然地哇哇哇哭了起来。我慌了，着急了，不知道怎么样才能让这手臂上的小天使安静下来，直接靠着她的小脸，轻轻地、温柔地说：“妈妈在，妈妈在，不哭，不哭！很快我们就有牛奶喝了，乖乖！”果然，小天使安静了下来，好似能听懂我说的话，顿时幸福极了。就这样自然而然切换了角色，一点也不生疏和羞怯。&lt;/p&gt;
&lt;p&gt;被推出手术室的那个清晨，我没有入睡，一直看着在婴儿床上的小天使，看着她手舞足蹈，是在找妈妈吗？眼睛真的太像我了，该给她起什么名字好呢？之前想的那些没有一个派得上用场。还是静静欣赏这可爱的唯一属于我的小天使，渐渐地我被困意和疲惫合上了双眼，进入了幸福的梦想……&lt;/p&gt;
&lt;p&gt;一页页记忆犹新的片段，宛如播放电影般快速出现在我的眼眸中。&lt;/p&gt;
&lt;p&gt;想要以文字的方式记录起与女儿一起成长的点点滴滴，生怕以后来不及回忆，生怕太多想要记住却只留下最珍贵的一幕幕。心心念叨了许久，迟迟没有行动。就现在，就再次提起的这时，索性开启了这一篇篇生活节选。&lt;/p&gt;
</description>
</item>
<item>
<title>10-女儿与我：妈妈给你道歉</title>
<link>https://liaolile.com/publication/10%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%A6%88%E5%A6%88%E7%BB%99%E4%BD%A0%E9%81%93%E6%AD%89/</link>
<pubDate>Tue, 19 Apr 2022 13:40:04 +0000</pubDate>
<guid>https://liaolile.com/publication/10%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%A6%88%E5%A6%88%E7%BB%99%E4%BD%A0%E9%81%93%E6%AD%89/</guid>
<description>&lt;p&gt;梳妆台前照的是自己的面容，你可以用化妆品来不断修饰自己的妆容以达到最好的状态，悦人其实是悦己。而在教育上，孩子就是你行为举止的镜子，只不过在落下不良影响之前，你并没有察觉到有一只小眼睛在看着、效仿着。&lt;/p&gt;
&lt;p&gt;前天晚上因为小丫头把我“打入冷宫”，内心迟迟不能平缓，以为说今天回到家后我还是可以得到小丫头快乐、激动地拥抱，结果等来的是小丫头的一句句“不要”。&lt;/p&gt;
&lt;p&gt;“我就要姥姥抱我出浴盆！”在浴室里玩水的她一看到我拿着浴巾，说出了这句话。&lt;/p&gt;
&lt;p&gt;“我就要姥姥，要不然我会用水搞湿你了！”小丫头说这句话的时候，我就已经很生气了，为了控制自己将要接近抓狂的情绪，立马关上了浴室的门，走到阳台把衣服都收回了卧室，做什么都好，就是要给自己缓冲器，避免情绪上升太快。&lt;/p&gt;
&lt;p&gt;因为我母亲要外出做核酸，再不出门社康医务人员就要下班了。我再次进入浴室，毕竟小丫头在里面也玩了许久了，再不出来洗澡水会导致她感冒的。&lt;/p&gt;
&lt;p&gt;门一关，小丫头就立马说“我要姥姥”，然后一直在哭。&lt;/p&gt;
&lt;p&gt;“小丫头，你什么意思？”这个时候的我已经忍不住了，好像从来也没有这样对她发过火。&lt;/p&gt;
&lt;p&gt;“嘣”地一声，应该是大门口被关上的声音，母亲应该是外出了，小丫头哭得更厉害。&lt;/p&gt;
&lt;p&gt;再也忍不住了，直接吼着，“谁抱你不一样？你为什么这样对妈妈呢？你这样迟早会感冒的。”也许是因为真的太凶了，小丫头不但没有停止哭声，反而愈来愈厉害。&lt;/p&gt;
&lt;p&gt;我直接把她从水里抱出，熟练地用浴巾直接裹着她的身躯，一把又抱到了她的小马桶上。一边快速擦干湿漉漉的头发和身体，一边涂着护肤品。一心只想着“不要感冒”，哭不哭、闹不闹都无所谓了，看着她哭到小眼睛一圈都红了，我还是很后悔，终究还是没有控制好自己的情绪。&lt;/p&gt;
&lt;p&gt;“到底是谁错了？”我皱着眉头对着她说。&lt;/p&gt;
&lt;p&gt;一只小小的手指从浴巾中间冒了出来，指向了我。&lt;/p&gt;
&lt;p&gt;“我哪里错了？”&lt;/p&gt;
&lt;p&gt;“我不要妈妈这么凶。”说完还带着委屈的哭声。&lt;/p&gt;
&lt;p&gt;“你知道妈妈为什么这么生气吗？为什么妈妈在家了，你不需要妈妈抱你，你知道妈妈很难过吗？”&lt;/p&gt;
&lt;p&gt;小丫头好似听懂了这句话一般，看了看我，“我不要妈妈生气。”&lt;/p&gt;
&lt;p&gt;全球知名的TED演讲中，有这么一句话：&lt;/p&gt;
&lt;p&gt;“情绪是人成长过程中重要的组成部分，不能控制情绪会阻碍我们成为成熟且成功的人。”&lt;/p&gt;
&lt;p&gt;小丫头说的没错，我确实是对她生气了，就好像谈恋爱的一对情侣再闹别扭。也许正因为小丫头在我的心目中占据了太重要的位置，我才会患得患失。&lt;/p&gt;
&lt;p&gt;“妈妈，我要抱抱。”小丫头依旧这么会哄我，我知道本身也是我错在先，却不愿意承认。&lt;/p&gt;
&lt;p&gt;“好了，妈妈抱抱。妈妈也不对，不应该对你生气。小丫头也原谅妈妈，好不好？”此刻，我觉得我们就是两个小孩子，不，我应该更像孩子一般需要小丫头给我安全感。&lt;/p&gt;
&lt;p&gt;当我再抬起头看着小丫头的时候，她已经不再哭了，还会对我笑并要求让我再抱抱她。小丫头，你可知道，你在我面前就像是给我阳光雨露的太阳，不断地照耀我内心深处，不断让我感知到我也是需要成长的。而不是因为我是成人，你是孩子。&lt;/p&gt;
</description>
</item>
<item>
<title>9-女儿与我：独立</title>
<link>https://liaolile.com/publication/9%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%8B%AC%E7%AB%8B/</link>
<pubDate>Mon, 18 Apr 2022 13:14:04 +0000</pubDate>
<guid>https://liaolile.com/publication/9%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E7%8B%AC%E7%AB%8B/</guid>
<description>&lt;p&gt;怀胎十月开始，就没有让小丫头离开过我的身边。在互联网上也看过不少关于孩子什么时候开始分床分房睡，那时候的我认为等孩子自己提出来再让她在自己的房间里睡吧，不做指令性的要求。看上去我很坦然接受，实际上我感觉更多还是来自于我对小丫头的依赖。&lt;/p&gt;
&lt;p&gt;当这一天要到来之时，没有做好准备的却是我。很肯定，是我离不开小丫头，不是小丫头离不开我。&lt;/p&gt;
&lt;p&gt;从未发现小丫头这么喜欢我的母亲，想想我是在“吃醋”。以前每天“妈妈，妈妈”地喊，今天我就被小丫头“打入冷宫”了？好委屈、好不服气，但事实确实就如此。&lt;/p&gt;
&lt;p&gt;把镜头拉回到晚上喂药时间，因为小丫头的皮肤总是不能自愈过敏源带来的反应，所以必须采取吃药措施 而且还是去医院医生叮嘱的。拿着小勺子细心地把药片切成两半，多了或少了都担心用量不对。确认过很多次，每次都拿小块一点的药片，想着少总比吃多了好。&lt;/p&gt;
&lt;p&gt;只是我顾虑了，小丫头看着我提起勺子准备喂药的架势，愣是不吃。我的母亲（小丫头称为“姥姥”）在旁边推了糖衣炮弹，小丫头才肯用手拿着药片放嘴里，但只是放，根本不肯咽下去，含着含着就直接吐出来了。&lt;/p&gt;
&lt;p&gt;着急的我一下子火冒三丈，“你想到处长包包吗？明天上不了幼儿园了怎么办？”&lt;/p&gt;
&lt;p&gt;“妈妈，我不会的。我不会用手挠，不会痒的。”之前提醒过不能用手抓，反而会因为抓伤，难以用药处理（医生不建议抓破的地方涂炉甘石）。&lt;/p&gt;
&lt;p&gt;僵持了一会，姥姥抱着小丫头本来想着跟她以故事的方式讲，结果小丫头以为在姥姥怀里就可以不吃药。我除了无奈，就差点想抓狂了。很明白的体现了，若要做好教育和规则，必须只能有一个口径，多的人就会分叉，结果什么都达不成。&lt;/p&gt;
&lt;p&gt;此刻，小丫头和我的关系是“破裂”的，她只听自己的，也只会觉得姥姥是陪她玩的、是爱她的，所以她不让我抱，也不让我督促她刷牙。我竟第一次感受到她不需要我了，内心波澜起伏，开始构筑起防御模式。&lt;/p&gt;
&lt;p&gt;“我今天要跟姥姥睡！”&lt;/p&gt;
&lt;p&gt;“那你跟姥姥睡吧，一会也不要来找我了。”之前确实出现过一下子又跑来跟我一起睡的经历，我以为小丫头这次也会这样。&lt;/p&gt;
&lt;p&gt;虽然关着房门，但还是可以听到隔壁房间里没睡着的小丫头在跟我母亲说话，渐渐地有些听不清，不知道是真的没有在互动了，还是门的隔音效果变好了。我起身多次，特意把自己房间门打开，并探着头仔细听有啥动静。结果我什么都没听到，估计是真睡着了。等了一个小时，也没有听到脆脆的脚丫子在瓷砖地上小跑的声音，我想她应该不会过来找我了。此时我也正疲惫着，就这样也睡着了。&lt;/p&gt;
&lt;p&gt;第二天早上起来第一件事，就是急忙帮还在赖床的小丫头换衣服裤子，要不然上学可就来不及了。小丫头很习惯听着我的指令，还搓着眼睛，迷迷糊糊地问“姥姥呢？”&lt;/p&gt;
&lt;p&gt;“姥姥在外面准备早餐。”&lt;/p&gt;
&lt;p&gt;“我要姥姥！”说罢便把我推开，直呼要姥姥抱。&lt;/p&gt;
&lt;p&gt;我特别失落，这原来第一位优等待遇的，现在变得不再需要了，此刻我真的很能感受爸爸之前的地位。&lt;/p&gt;
&lt;p&gt;坐在地铁上还在回忆，这丫头变化也太快了，还是我忽略了什么。罢了罢了，一宿没有睡好的我，还有很多事情等着我去处理，还是等晚上回家后再说吧。说不定对于我或小丫头来说，都是件好事。只是我需要时间去认同她的选择，再或许这就是她开始独立的象征，或者是让我适应她独立的开始吧。&lt;/p&gt;
</description>
</item>
<item>
<title>8-女儿与我：再看一分钟</title>
<link>https://liaolile.com/publication/8%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%86%8D%E7%9C%8B%E4%B8%80%E5%88%86%E9%92%9F/</link>
<pubDate>Sun, 17 Apr 2022 17:09:04 +0000</pubDate>
<guid>https://liaolile.com/publication/8%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%86%8D%E7%9C%8B%E4%B8%80%E5%88%86%E9%92%9F/</guid>
<description>&lt;p&gt;在这个电子产品已经成为家常便饭的时代，在孩子教育上必然要面对“是否给小孩看手机、iPad、电视、电脑等电子产品，看多久？怎么看？”一系列问题。&lt;/p&gt;
&lt;p&gt;我没有在任何育儿或者家长群里去深入研究或探讨过这个问题，毕竟每个人对于上述命题的解决方案不同，理解也不一样。&lt;/p&gt;
&lt;p&gt;对于我而言，自己工作的伙伴就是电脑，每天面对电脑、笔记本、手机屏幕，至少超过十个小时，当然，厚厚的眼镜是少不了。按照小丫头之前的读本来说，“妈妈带着一个大怪兽”。&lt;/p&gt;
&lt;p&gt;我们大人都离不开手机，不用说现在的小朋友了，但很奇怪的是，我们作为大人却要限制孩子的行为。对于老一辈，就是不允许看，只能在户外玩，但老人却可以戴着老花镜在家看电视。大人可以躺在床上玩手机，却不允许孩子玩iPad？&lt;/p&gt;
&lt;p&gt;我不是很理解，在家里我可能扮演的是一个重容小丫头的角色。我能理解的时，大人已经破罐子破摔了，只是这份悔过需要孩子铭记在行动上。那为何以身作则，在家陪伴的时候，用游戏的方式暂时远离这些电子产品呢？&lt;/p&gt;
&lt;p&gt;其实我觉得让孩子接触这些东西并没有什么，只需要掌握好使用的时长即可。毕竟动画教育说的内容，活跃的卡通人物，比我们大人如念经般的说辞要有效果，而且孩子们能一下子就认同和记住了。作为大人，我们只需要预先了解视频的内容即可，毕竟价值观念不同。&lt;/p&gt;
&lt;p&gt;小丫头有不少安全知识、生活常识、颜色和形状认知，都是通过iPad进行学习的，也不是家里没有读本，一排排摆着，画了不少，也撕烂了不少。有时候小丫头还是经常自己去拿绘本，拉着大人的手一定要读完。&lt;/p&gt;
&lt;p&gt;在这事情上，我和小丫头之间有很多约定。&lt;/p&gt;
&lt;p&gt;每当系统到了休息时间或睡觉时间，都会提示需要家长输入图形认证或算术题认证，这个时候小丫头就回来找我。&lt;/p&gt;
&lt;p&gt;“妈妈，帮我输数字。”&lt;/p&gt;
&lt;p&gt;“妈妈，这个题目是什么？”&lt;/p&gt;
&lt;p&gt;“妈妈，我可不可以再看一分钟？”&lt;/p&gt;
&lt;p&gt;一般这种时候，如果是爸爸，则一下子抢过孩子手中的iPad，然后讲一堆“要睡觉啦，再看眼睛就坏了”什么的道理，任凭小丫头哭着喊妈妈。而我，则不是这么做，我比较希望是小丫头自己提出来什么时候睡觉，顺便这个时候可以传递一下“时间”是什么概念，我们需要什么规则去遵守。&lt;/p&gt;
&lt;p&gt;“小丫头，你看，妈妈手机上变成11，就要关掉iPad并去睡觉了，好不好？”再或者“我们再看两分钟或者这集看完就关掉并睡觉了，好不好？”&lt;/p&gt;
&lt;p&gt;“好”，小丫头肯定毫不考虑地完全接受，结果她确实如实按照约定关闭iPad，并跑到我怀里说了句，“我最爱妈妈了”。&lt;/p&gt;
&lt;p&gt;作为母亲，我自然爱我的孩子，也不希望她近视或各种导致身体不健康。但是成长也需要时间，也需要给孩子多一些时间去理解，在一定范围和距离给他们保护，这才是我们做家长最应该做的。&lt;/p&gt;
</description>
</item>
<item>
<title>7-女儿与我：勇敢</title>
<link>https://liaolile.com/publication/7%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%8B%87%E6%95%A2/</link>
<pubDate>Fri, 15 Apr 2022 21:13:04 +0000</pubDate>
<guid>https://liaolile.com/publication/7%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%8B%87%E6%95%A2/</guid>
<description>&lt;p&gt;所谓无知者无畏，这在孩子的身上提现得淋漓尽致。&lt;/p&gt;
&lt;p&gt;因近段时间不知明的原因，皮肤总是起着类似被蚊虫叮咬后很痒的包，一起就是一串。在网上查询过，与因过敏引起的荨麻疹症状相似，吃了抗组胺药，是抑制住瘙痒的症状了，但没办法根治，总是反反复复。先是我发起，过了一段时间，小丫头也出现类似的症状了。所以还是下定决心请个假，带着小丫头一起去医院检查一下，至少查一下过敏源吧。&lt;/p&gt;
&lt;p&gt;春季末尾的太阳在珠三角的地区已经显得有些烈了，但路边的花草倒显得很好看。想着，确实埋头苦干久了，都不知道办公室外还有这么美丽的一幕。&lt;/p&gt;
&lt;p&gt;工作日正午的地铁站，人流稀少，显得很安静，路边的车流就像被按下暂停键一样，几乎没有。&lt;/p&gt;
&lt;p&gt;回到家推开门，“妈妈，你怎么这么早就回来了？天还是亮的呀。”&lt;/p&gt;
&lt;p&gt;说来也惭愧，工作日几乎早出晚归的我，这个点出现确实让小丫头有点惊讶，不过小丫头灿烂如旧，非常快速地跑过来抱大腿。&lt;/p&gt;
&lt;p&gt;“是的，妈妈回来了，下午我们一起去检查身体，好不好？”&lt;/p&gt;
&lt;p&gt;“为什么？”这句话果真问倒我了。&lt;/p&gt;
&lt;p&gt;稍作午休后，我带着小丫头和她心爱的小红推车出门了，沿着熟悉的人行道快速走着。遇到走天桥的时候，由于左手拖着车，右手拉着小丫头走台阶，还得到了一位老爷爷的帮助，帮我把推车推上了桥并顺利走到马路对面。挺不好意思地对老爷爷道谢，便望着老爷爷的身影愈走愈远。&lt;/p&gt;
&lt;p&gt;本次去检查身体，肯定会抽血。为了不让小丫头觉得恐惧，则必须让她完全参与整个挂号、开单、问诊等所有过程，让她觉得是件很好玩的事情，就像两个小朋友在玩耍一般。&lt;/p&gt;
&lt;p&gt;我尝试让她自己拿着医保卡，在智能机上挂号、取单，并等待机器退卡取卡的过程。她很乐意效劳，并且每次都要求我不要插手，只能她亲自来。包含问诊前在门口等待，小丫头也跟着我抢着门外的座位。我心里想着，“我得逞了，就看一会问诊的表现了”。&lt;/p&gt;
&lt;p&gt;记得小丫头从有认知开始，看到带着白色帽子医生或护士就会哭，估计是小时候疫苗打怕了。所以我不清楚一会在问诊室会不会不愿意走进或者委屈地哭起来。当电子屏显示我的名字时，小丫头居然一下子站起来，并拿着她自己的挂号单自如、大胆的走进去，直接坐在木凳子上，并对我说，“妈妈，这里有好多形状”。&lt;/p&gt;
&lt;p&gt;看来一天一个样，她已经向往着和大人一样。果真我们得开单抽血查过敏源，小丫头和我牵着手又来到智能机上操作一番。&lt;/p&gt;
&lt;p&gt;“好了，一会妈妈和你都要去抽血。我们一起，好不好？”&lt;/p&gt;
&lt;p&gt;“我要去抽血，我先来！”&lt;/p&gt;
&lt;p&gt;这后半句有点惊讶，小丫头居然自告奋勇争第一个。当护士问，“是小孩先，还是大人先”，我毫不犹豫回答道，“小孩先”，成全小丫头的第一次勇敢，毕竟如果我先在她面前抽一管子血，也许她便怕了。&lt;/p&gt;
&lt;p&gt;把小丫头一把抱上采血室的圆凳子上，护士扫完码之后便麻利地拿着消毒工具和采血针。只见小丫头自己直接把左手平放在桌子平面上，听着护士的指示，握起小小的拳头。这一举动，引来另一个路过的护士，“这小孩几岁了？应该上幼儿园了吧，要不然这么听话”。&lt;/p&gt;
&lt;p&gt;小孩子的喜怒哀乐常常很直白简单地表现出来，这采血针才开始工作，小丫头开始拉警报了，在我怀抱里哭得稀里哗啦，小眼睛瞬间红了一圈。但我发现，小丫头用于采血的小手臂始终没有动过，这不同于其他时候的注射疫苗和拇指采血的表现。&lt;/p&gt;
&lt;p&gt;原本护士想等我安抚一下小丫头再抽我的血，我直接示意“直接来吧”，其主要是为了让小丫头看着妈妈如何面对采血的。&lt;/p&gt;
&lt;p&gt;“妈妈好勇敢啊，没有哭。”护士也非常配合我的表现，对着小丫头说。&lt;/p&gt;
&lt;p&gt;“对呀，你看，妈妈哭了没有？妈妈是不是特别勇敢？”小丫头停顿了一下看了一眼，又继续哭。&lt;/p&gt;
&lt;p&gt;“你看，妈妈的红细胞坐滑滑梯到管子里了，好多好多红细胞。”小丫头又停了一下，这次稍微停顿长了点，估计小丫头在想，这跟书本上的红细胞不一样，根本看不到他们圆圆的身体和小手小脚，然后还是继续哭，口罩都接上了好几滴泪珠子。&lt;/p&gt;
&lt;p&gt;其实采血的时候我也害怕，毕竟还是戳了一个小孔，真空压力下会有些许疼痛。但为母则刚，在孩子面前顾不上害怕，要不然孩子更加不可能勇于去尝试她自个的第一口螃蟹了。&lt;/p&gt;
&lt;p&gt;抽完血我也不顾棉签是否压在针孔上，抱着小丫头让她坐在我的腿上，先让她委屈地哭一会，以表达确实很疼。&lt;/p&gt;
&lt;p&gt;“今天，你非常勇敢，自己提出来要第一个抽血！虽然还是因为好疼哭了，但是妈妈还是要奖励你一个东西。是小汽车？还是冰淇淋？”&lt;/p&gt;
&lt;p&gt;这奖励貌似更吸引小丫头，话音刚落，她立马停止哭声。&lt;/p&gt;
&lt;p&gt;“什么小汽车？”&lt;/p&gt;
&lt;p&gt;“挖掘机。”&lt;/p&gt;
&lt;p&gt;“我要冰淇淋，白色的冰淇淋。”早猜到小丫头会选择冰淇淋。&lt;/p&gt;
&lt;p&gt;“那我们得找个地方一起吃冰淇淋，不能被奶奶发现了。”说实话，在哪里吃都觉得会被发现，只是我觉得若成为和小丫头的小秘密会让她更期待。&lt;/p&gt;
&lt;p&gt;“好！”小丫头站起，双手打开示意着抱一抱。我想着此刻的回应不是溺爱，而是鼓励和安慰。&lt;/p&gt;
&lt;p&gt;任务比我预期完成得更顺利，为这过程中小丫头的表现而感慨。走出医院的大门，我推着小丫头最爱的小红车，小车子载着又经历一次成长的我最爱的小丫头。傍晚的阳光已经不这么明媚，恰恰好适合此刻的悠闲漫步。&lt;/p&gt;
&lt;p&gt;也许，成长的过程就是这般有趣，虽不可预测，但收获的一定是美好的结果。我在成长，小丫头也在成长。&lt;/p&gt;
</description>
</item>
<item>
<title>6-女儿与我：认真</title>
<link>https://liaolile.com/publication/6%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%AE%A4%E7%9C%9F/</link>
<pubDate>Tue, 12 Apr 2022 22:02:03 +0000</pubDate>
<guid>https://liaolile.com/publication/6%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%AE%A4%E7%9C%9F/</guid>
<description>&lt;p&gt;忙碌了一天的工作，终于可以抱着鲜艳的花束坐在地铁上，开始翻阅微信里的未读消息。&lt;/p&gt;
&lt;p&gt;因为没有提前在微信群里接龙报名，看到小丫头参加轮滑课感到有些惊喜。少许交代上课签到后，便认真地看起了视频的每一帧。&lt;/p&gt;
&lt;p&gt;在视频里，小丫头应该是被教练安排独立练习在指定区域来回练习走步。看着小丫头仔仔细细、缓慢的移步，然后去拾地上摆放的物品，来回进行了两次，直到教练顾得上她，让她坐在塑料凳上休息，她才肯听话坐下。过程中，边步移，边看着旁边在滑翔的小哥哥姐姐们。因为我知道，她太想和他们一样飞翔。&lt;/p&gt;
&lt;p&gt;不知怎么，我看到这里觉得小丫头有一种骨子里的较真和坚持。就好像她一岁多在家里练习跳跃的那个夜里，也是不断练习，直到我上前告知她要休息了才肯放下这件事。不禁地有点儿感动，是不是所谓的初心，就如这般纯洁而简单。就是因为喜欢，所以坚持。&lt;/p&gt;
&lt;p&gt;每每看到我女儿，我总自愧不如。很多喜欢的事情，随着年龄的增长，好像便开始褪去了颜色，推脱已经成为了保护自己的措辞。&lt;/p&gt;
&lt;p&gt;我也曾喜欢过画画，想成为一个画家；我也曾喜欢过设计，想成为一名服装设计师；我也曾喜欢过写作，想成为一名文学创作者；我也曾喜欢过阅读，想成为一名朗读者……太多太多的喜欢，却没有勇气认认真真地坚持下来。如果多了一份小丫头认真，也许现在的我是一个全新的我。&lt;/p&gt;
&lt;p&gt;不过好在，从现在开始也不晚。认定要做的事，就全力以赴，无论自己是否达到了要求或定义，只要不断练习、不断尝试，走过，总比停滞不前要好。&lt;/p&gt;
</description>
</item>
<item>
<title>5-女儿与我：讲故事</title>
<link>https://liaolile.com/publication/5%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%AE%B2%E6%95%85%E4%BA%8B/</link>
<pubDate>Mon, 11 Apr 2022 22:46:04 +0000</pubDate>
<guid>https://liaolile.com/publication/5%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E8%AE%B2%E6%95%85%E4%BA%8B/</guid>
<description>&lt;p&gt;“妈妈，你给我讲个故事吧。”小丫头满眼期待地看着我，这是每日睡前必要的环节。&lt;/p&gt;
&lt;p&gt;“讲什么故事呀？”&lt;/p&gt;
&lt;p&gt;“讲妈妈小时候的故事，讲妈妈会不会跳？”&lt;/p&gt;
&lt;p&gt;我一般都会借此机会传递安全知识，毕竟现在的她要会探险，也要学会保护自己。&lt;/p&gt;
&lt;p&gt;“妈妈小时候也跟你一样，喜欢跳。有一次，跟带妈妈的阿姨在床上玩，也是看到大人的脚，就想着跳来跳去。结果，妈妈不小心被阿姨的脚绊倒了。脑门被撞了个大包，妈妈哭了好久好久，姥姥、姥爷轮流抱妈妈都止不住疼痛。”&lt;/p&gt;
&lt;p&gt;“为什么妈妈会摔跤？”&lt;/p&gt;
&lt;p&gt;“因为阿姨的腿腿会动呀，一动，妈妈就被绊倒了。所以你要跳的话，必须告诉大人或者小朋友脚脚不许动，要不然很容易摔跤。但是如果有软绵绵的被子像棉花糖一样保护我们，我们就不会受伤了。”&lt;/p&gt;
&lt;p&gt;“就像雪融融一样的棉花糖吗？”小丫头指着姥爷（北方人称外祖父为“姥爷”）刚快递寄过来的吉祥物。&lt;/p&gt;
&lt;p&gt;“是的，软绵绵的，像雪融融一样。”&lt;/p&gt;
&lt;p&gt;小丫头还是那样地认真看着我，并且会举一反三向我提问，我几乎不能分神，避免被她带偏了而无法讲完自编的一则故事。&lt;/p&gt;
&lt;p&gt;记得有一天，无意中听到小丫头自己拿着小玩具车自言自语 ，“有一天，小青蛙想过河摘花，可是呀，小青蛙看不到荷叶，不能跳过去摘花。于是呀，见到小金鱼。小金鱼对小青蛙说，我们可以帮你跳过去……”&lt;/p&gt;
&lt;p&gt;我听着窃喜，这小丫头什么时候有自己的逻辑去讲述她天马行空的故事，还有模有样的。虽然一点逻辑都没有，但从她口中吐出来的都是可爱的字眼，我满是喜欢。&lt;/p&gt;
&lt;p&gt;这或许就是有样学样，我算是明白了为什么育儿教科书会说，培养孩子有好的学习能力，需要父母营造读书的氛围。哪怕你是假装看书，也要在孩子面前完成。这样久而久之，孩子就会形成习惯。就像小丫头开始讲故事一样，是自然而然的。&lt;/p&gt;
&lt;p&gt;看着小丫头听着我的故事，渐渐地闭上眼睛睡着了。我很有成就感，爱抚着她的脑袋瓜子，又忍不住亲吻一口小脸蛋。晚安，我亲爱的小丫头！&lt;/p&gt;
</description>
</item>
<item>
<title>4-女儿与我：为什么</title>
<link>https://liaolile.com/publication/4%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%B8%BA%E4%BB%80%E4%B9%88/</link>
<pubDate>Sat, 09 Apr 2022 17:14:04 +0000</pubDate>
<guid>https://liaolile.com/publication/4%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%B8%BA%E4%BB%80%E4%B9%88/</guid>
<description>&lt;p&gt;“妈妈，为什么这个是圆形？”&lt;/p&gt;
&lt;p&gt;“妈妈，为什么小鱼要在水里游泳？”&lt;/p&gt;
&lt;p&gt;“妈妈，为什么水是这个颜色的？”&lt;/p&gt;
&lt;p&gt;“为什么……”&lt;/p&gt;
&lt;p&gt;不知从何时开始，小丫头一天的对话里，有60%的话语都会带上一个“为什么”后缀。我开始接受十万个为什么的挑战，开阔我三十左右的智力上限。&lt;/p&gt;
&lt;p&gt;我一度在琢磨，为什么小丫头这么喜欢说着“为什么”呢？想必因为小孩就是小孩子，很多事情不懂，很多事情都不会，很多事情会好奇。换一个角度，我则当做提升自己思想的边界或广度吧。毕竟这些问题，在成年人的世界里不会遇到。何尝不是一种奇妙的体验呢？&lt;/p&gt;
&lt;p&gt;“妈妈，为什么我要喝水？”&lt;/p&gt;
&lt;p&gt;“因为喝水可以让我们身体里的白细胞变大，消灭小细菌。就像这样。”&lt;/p&gt;
&lt;p&gt;我用双手比划着，左手比个大圈圈表示白细胞，右手比个小圈圈表示细菌，左手的大圈圈越来越大，右手的小圈圈越来越小。让她感受到这个变化的过程，越夸张越好，因为这样会更吸引她的关注，会如拍照一般印在她的脑海里。下一次若出现同样的场景和问题，小丫头便会自己脱口说出这个比喻。&lt;/p&gt;
&lt;p&gt;跟孩子在一起，不用刻意讲理论、大道理，因为他们毕竟是孩子，不知晓“规章制度”、“道理”，只知道什么事情让他们快乐、有趣。适当做一些夸张有趣的比喻，比苦口婆心说大道理，效果好得太多了。&lt;/p&gt;
&lt;p&gt;也借用“为什么”向自己提问，为什么我们要向孩子说这么多他们无法理解和消化的道理呢？为什么不转换成孩子的视角，让她们快乐成长呢？&lt;/p&gt;
&lt;p&gt;孩子是我们的期望，但不是刻意变成我们的希望。快乐健康成长，才是我们父母给予最重要的智慧。&lt;/p&gt;
&lt;p&gt;为什么不能简单快乐和孩子一起完成每一件事情？让他们体会到真正的成长快乐，在一定安全可靠的条件下去探索。&lt;/p&gt;
&lt;p&gt;比起“我要你做”，我更想变成“我想去做”。&lt;/p&gt;
</description>
</item>
<item>
<title>3-女儿与我：不断练习</title>
<link>https://liaolile.com/publication/3%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%B8%8D%E6%96%AD%E7%BB%83%E4%B9%A0/</link>
<pubDate>Fri, 08 Apr 2022 20:27:04 +0000</pubDate>
<guid>https://liaolile.com/publication/3%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E4%B8%8D%E6%96%AD%E7%BB%83%E4%B9%A0/</guid>
<description>&lt;p&gt;人们都说一岁前的小孩，每天都在生长；三岁前的小孩，每天都在成长。而成长黄金期最关键的就是性格养成。&lt;/p&gt;
&lt;p&gt;回忆起来，在陪伴的过程中，我并不清楚女儿的性格会是什么样的？一直以为秉着放养策略，也是希望可以让女儿自己探索成长路线，当然我作为最佳距离的保护而不干扰。&lt;/p&gt;
&lt;p&gt;记得还是元旦节期间，由于部分原因，一个月前将女儿送到我母亲家里。乘坐了当天首班高铁的我，抗不住路途的疲惫，晚上早早就躺在床上，眼看就要睡着了。还想牵着我一个多月都没有拉的小手入睡，结果女儿一下子蹦到被子外，用我的腿摆出的桥状物来练习跳跃。&lt;/p&gt;
&lt;p&gt;我知道她必定是想在我面前表现表现，因为前段时间在视频里，母亲说过女儿近期非常喜欢跳跃，但总是跳不好。也许这句话她记在心坎里了，只要找到机会，找到类似的障碍物，她都会尝试起跳。&lt;/p&gt;
&lt;p&gt;那天晚上，我看着她的小身影，在我身边跳来跳去。每一次跳跃，她都伴随着“跳”的话语。&lt;/p&gt;
&lt;p&gt;“跳。”&lt;/p&gt;
&lt;p&gt;“跳。”&lt;/p&gt;
&lt;p&gt;“跳。”&lt;/p&gt;
&lt;p&gt;来来回回十几次，每一次摔倒都会尝试重新起跳。不断地练习着，直到我上前阻止。&lt;/p&gt;
&lt;p&gt;看着她的坚持，那股不断练习的劲儿，想必以后肯定是遇到困难不愿意放弃的孩子，或者是非常有自己主见。我作为成人，不得不佩服。&lt;/p&gt;
&lt;p&gt;都说培养孩子就像是照镜子一般，你在指引她的同时，她也会反过来影响你。让你看到了自己的影子，看到了自己的不足。&lt;/p&gt;
</description>
</item>
<item>
<title>2-女儿与我：叠词</title>
<link>https://liaolile.com/publication/2%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%8F%A0%E8%AF%8D/</link>
<pubDate>Thu, 07 Apr 2022 23:13:11 +0000</pubDate>
<guid>https://liaolile.com/publication/2%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%8F%A0%E8%AF%8D/</guid>
<description>&lt;p&gt;和普通的爸爸妈妈无任何差别，我会记录小孩在成长过程中所有的第一次。&lt;/p&gt;
&lt;p&gt;第一次发音，说的是“爸爸”还是“妈妈”呢？在无数次幻想着听到女儿叫自己妈妈时的心情，很是期待女儿可以将第一个叠词交给我。可惜的是，幻想终究是幻想，女儿还是偏爱爸爸，把人生的第一个初音交给了爸爸，虽然发音不是很标准。&lt;/p&gt;
&lt;p&gt;从那天开始，我便开始在与女儿睡前互动时收集她的咿咿呀呀，有时也会引导她喊“妈妈”，就像收集宝贝一样，把每一次录音文件以日期和内容的格式保存起来。&lt;/p&gt;
&lt;p&gt;6月22日，已经很清晰地发音“爸爸”了。&lt;/p&gt;
&lt;p&gt;6月23日，“爸爸”、“妈妈”分不清。&lt;/p&gt;
&lt;p&gt;6月24日，第一次发音说“妈妈”。&lt;/p&gt;
&lt;p&gt;8月23日，会发音说“牙牙”……&lt;/p&gt;
&lt;p&gt;任何的第一次发音，包括咿咿呀呀学唱歌，全部都会细心记录下来。&lt;/p&gt;
&lt;p&gt;现在回看手机里记录女儿每一天变化的视频和音频，百看不厌。&lt;/p&gt;
&lt;p&gt;记得有一次，女儿学着我母亲使用一次性手套帮她整理奶瓶，不得不说幼儿的她模仿能力太强了。不知道从哪里自己找来了两个保鲜袋子套在小手上，摇摇晃晃地走到我的面前说，“手手”。那时候的我很习惯帮她补充说明这些叠词的完整意思，“是不是要带手套呀？”。&lt;/p&gt;
&lt;p&gt;接下来整个对话是这样的，女儿用自制的手套拿着床上放着的新裤子。&lt;/p&gt;
&lt;p&gt;“裤裤呀。”&lt;/p&gt;
&lt;p&gt;“是不是要穿新裤子呀。”&lt;/p&gt;
&lt;p&gt;“嗯。”&lt;/p&gt;
&lt;p&gt;“脚脚呀。”&lt;/p&gt;
&lt;p&gt;“脚脚要从裤裤里伸出来”，结果自己穿的过程中，裤脚快掉了。&lt;/p&gt;
&lt;p&gt;“掉掉呀。”&lt;/p&gt;
&lt;p&gt;“哦，没事，妈妈扶着你，帮你把脚脚拉出裤腿。”&lt;/p&gt;
&lt;p&gt;女儿看到自己的小脚丫子从裤腿窜出来的时候，开心地呵呵呵笑。接着又摇摇晃晃走到新拖鞋旁边，一屁股坐在木地板上，开始摆弄鞋子，哪个才是左脚穿，哪只是右脚穿呢？看着实在可爱。&lt;/p&gt;
&lt;p&gt;在女儿玩电子狗，跳舞的小狗碰了下她的小手指，紧接着对着我说，“痛痛呀”。&lt;/p&gt;
&lt;p&gt;“哦，小狗碰到你的小手，疼了，是吧？”&lt;/p&gt;
&lt;p&gt;“揉揉呀。”&lt;/p&gt;
&lt;p&gt;“抱抱，抱抱抱……”&lt;/p&gt;
&lt;p&gt;“要谁抱抱呀？”&lt;/p&gt;
&lt;p&gt;“妈妈！”&lt;/p&gt;
&lt;p&gt;那时候的我好似女儿的翻译机，什么叠词都可以变成完整的一句话。而我总能完全理解并回馈给女儿，也许这就是用心陪伴的默契。&lt;/p&gt;
</description>
</item>
<item>
<title>1-女儿与我：序</title>
<link>https://liaolile.com/publication/1%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%BA%8F/</link>
<pubDate>Wed, 06 Apr 2022 23:25:04 +0000</pubDate>
<guid>https://liaolile.com/publication/1%E5%A5%B3%E5%84%BF%E4%B8%8E%E6%88%91%E5%BA%8F/</guid>
<description>&lt;p&gt;沿着人类群体生活自然发展规律，我也顺利地步入为人之母。&lt;/p&gt;
&lt;p&gt;从怀胎十月，到神奇的小生命伴着哇哇哭声降落到人世间。当护士将这可爱的小天使包裹着襁褓放在我的左手臂上的瞬间，就像是被定格了一般。第一次感受到一个生命在我的手臂上悦动，很暖和、很真实，黑黝黝的小眼珠像是在试探世界的温度，是否跟妈妈肚子里一般温暖。&lt;/p&gt;
&lt;p&gt;这就是我的小宝贝吗？实在太可爱了，跟第一次B超结果报告里的小眼睛一样，只是眼前的更加清晰，我想我永远都记住这黑黝黝的小眼睛。&lt;/p&gt;
&lt;p&gt;看着她极力吮吸着襁褓，突然地哇哇哇哭了起来。我慌了，着急了，不知道怎么样才能让这手臂上的小天使安静下来，直接靠着她的小脸，轻轻地、温柔地说：“妈妈在，妈妈在，不哭，不哭！很快我们就有牛奶喝了，乖乖！”果然，小天使安静了下来，好似能听懂我说的话，顿时幸福极了。就这样自然而然切换了角色，一点也不生疏和羞怯。&lt;/p&gt;
&lt;p&gt;被推出手术室的那个清晨，我没有入睡，一直看着在婴儿床上的小天使，看着她手舞足蹈，是在找妈妈吗？眼睛真的太像我了，该给她起什么名字好呢？之前想的那些没有一个派得上用场。还是静静欣赏这可爱的唯一属于我的小天使，渐渐地我被困意和疲惫合上了双眼，进入了幸福的梦想……&lt;/p&gt;
&lt;p&gt;一页页记忆犹新的片段，宛如播放电影般快速出现在我的眼眸中。&lt;/p&gt;
&lt;p&gt;想要以文字的方式记录起与女儿一起成长的点点滴滴，生怕以后来不及回忆，生怕太多想要记住却只留下最珍贵的一幕幕。心心念叨了许久，迟迟没有行动。就现在，就再次提起的这时，索性开启了这一篇篇生活节选。&lt;/p&gt;
</description>
</item>
<item>
<title>理解架构</title>
<link>https://liaolile.com/post/tech/base/%E7%90%86%E8%A7%A3%E6%9E%B6%E6%9E%84/</link>
<pubDate>Mon, 04 Apr 2022 21:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/base/%E7%90%86%E8%A7%A3%E6%9E%B6%E6%9E%84/</guid>
<description>&lt;p&gt;维基百科:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;软件架构是有关软件整体结构与组件的抽象描述，用于指导大型软件系统各个方面的设计。软件架构会包括软件组件、组件之间的关系，组件特性以及组件间关系的特性。软件架构可以和建筑物的架构相比拟。软件架构是构建计算机软件，开发系统以及计划进行的基础，可以列出开发团队需要完成的任务。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;架构是这样定义的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个系统都由一个架构&lt;/li&gt;
&lt;li&gt;架构由架构元素以及相互之间的关系构成&lt;/li&gt;
&lt;li&gt;系统是为了满足利益相关者（Stackholder）的需求而构建的&lt;/li&gt;
&lt;li&gt;利益相关者都有自己的关注点（Concerns）&lt;/li&gt;
&lt;li&gt;架构由架构文档描述&lt;/li&gt;
&lt;li&gt;架构文档描述了一系列的架构视角&lt;/li&gt;
&lt;li&gt;每个视角都解决并且对应到利益相关者的关注点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/07/02/rt8cLN25C9mOTkW.jpg" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;架构中的利益相关者：业务方、产品经理、客户、开发经理、工程师、项目经理、测试人员、运维人员、运营人员；理解各方的关注点和通电，并出架构解决这些关注点；&lt;/p&gt;
&lt;p&gt;业务驱动与基础设施的进化推动架构的发展。架构需要解决需求的问题，业务需求的变化驱动着架构的进化。&lt;/p&gt;
&lt;p&gt;基础设施的创新和开源价值的推动，一直在演进，到现在云原生时代，业务架构就需要基于云原生进行改造，如何基于云组件做适配，如何合理使用云的弹性、计算存储分离等功能也变得至关重要。而架构中最关键的是应该做到以不变应万变，这是以最终目标来看的：加速软件发布，减少整个软件生命周期中的资源投入（包括人力和最后软硬件资源等），通过管理复杂性、易变形和不确定性，为了简单高效的实现业务需求，确保在长期系统演进过程中，部分架构的变化不会对架构其它部分产生不必要的负面影响，让应用的易变部分能够频繁的变化。&lt;/p&gt;
&lt;p&gt;为了处理好业务复杂性的业务领域建模，实现系统非功能性需求的架构领域的设计模式/风格至今也同样还是架构师的必备技能，只是应用在不同的基础设施上。不管什么时候，我们都强调架构在软件方面的可维护性、可扩展性、高可伸缩性，在组织架构方面的人员组织结构。我们的产品（软件）也必然是其（人员）组织沟通结构的缩影。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The hardest part of design is deciding what to design.             &amp;ndash; the design of design&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;架构需要设计，但是架构更是一个根据业务长期演化才能落地生根的。而最终架构不仅要服务于技术，更要服务于人。&lt;/p&gt;
&lt;p&gt;非功能性需求的架构，xxx-abilities。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/07/02/n5sPD7JHIMQkEXj.png" style="zoom:80%;" /&gt;
&lt;h4 id="成为优秀的架构师"&gt;成为优秀的架构师&lt;/h4&gt;
&lt;p&gt;来自蔡超的三点建议：&lt;/p&gt;
&lt;p&gt;1、坚持编码。架构师也是程序员，代码是软件的最终实现形态，停止编程会逐渐让你忘记作为程序员的感受，更重要的是忘记其中的“痛”，从而容易产生一些不切实际的设计。应该尽可能写代码，做测试，然后才是设计架构。&lt;/p&gt;
&lt;p&gt;2、坚持学习。对于IT人而言忙碌已成为习惯，996也讽刺的变成了公司高效的标志。而实时上过度忙碌会导致你没有事件学习和更新自己的知识，进而逐渐落后。&lt;/p&gt;
&lt;p&gt;3、用于关注技术上新的变化，同时更多思考的角度，重点是靠那些经历多年真正不变的技术和理念。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/07/02/ifVvjWOdkGHQIUn.png" style="zoom: 50%;" /&gt;
</description>
</item>
<item>
<title>编程原则</title>
<link>https://liaolile.com/post/tech/base/%E7%BC%96%E7%A8%8B%E5%8E%9F%E5%88%99/</link>
<pubDate>Fri, 18 Mar 2022 22:15:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/base/%E7%BC%96%E7%A8%8B%E5%8E%9F%E5%88%99/</guid>
<description>&lt;p&gt;[toc]&lt;/p&gt;
&lt;p&gt;有目的的努力方向，才是正确的方向。而编程原则就是抽象于各种编程语言而来的思想，为的就是写下那隽永留千年的代码，因为最经典、最基础的一些思想总是源远流长的！&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;代码发布后故障不断。&lt;/p&gt;
&lt;p&gt;多时之后再看自己的代码，已经不能再忍受，重构。&lt;/p&gt;
&lt;p&gt;修改一行代码，整个程序都崩溃了。&lt;/p&gt;
&lt;p&gt;我的新功能应该在什么地方加入呢？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;系统最本质的内容，我们往往理解的不够，所以出现了很多矛盾和纠结。为啥不深入研究下软件中最基本的内容并且沉淀呢，面对这个最复杂的东西探析清楚，知其所以然。这就是本篇的内容。&lt;/p&gt;
&lt;h3 id="0-准确定义"&gt;0 准确定义&lt;/h3&gt;
&lt;h4 id="01-软件"&gt;0.1 软件&lt;/h4&gt;
&lt;p&gt;编程的产物也就是“软件”。我们常说的系统、工具、应用、平台等均是编程的产物，均归类为软件。&lt;/p&gt;
&lt;h4 id="02-代码"&gt;0.2 代码&lt;/h4&gt;
&lt;p&gt;编程中编写的东西统称为“代码”，包括源代码、程序、源程序等均为代码。&lt;/p&gt;
&lt;h4 id="03-编程"&gt;0.3 编程&lt;/h4&gt;
&lt;p&gt;编写代码这件事或行为，我们就叫“编程”；也有叫编码、Coding、开发、实现等，均用编程指代。&lt;/p&gt;
&lt;h4 id="04-程序员"&gt;0.4 程序员&lt;/h4&gt;
&lt;p&gt;负责编程的人统一称作“程序员”，根据不同的场景也区分为开发者、开发人员、软件工程师、程序猿。&lt;/p&gt;
&lt;h4 id="05-函数"&gt;0.5 函数&lt;/h4&gt;
&lt;p&gt;可供调用的代码块也就是“函数”，还能细化为功能、过程、方法、成员函数等；往往词语指代东西并不一致，功能是有返回值，而过程是无返回值。&lt;/p&gt;
&lt;h4 id="06-模块"&gt;0.6 模块&lt;/h4&gt;
&lt;p&gt;函数和变量的组合单元可以称为“模块”。包括更多的概念都可以提供如此的组合概念，如类、文件、库、组件、部件等，代表的是关联性较强的代码集合。&lt;/p&gt;
&lt;h4 id="07-软件架构"&gt;0.7 软件架构&lt;/h4&gt;
&lt;p&gt;软件的整体结构就是“软件架构”，高于模块一层来看整个软件的整体内容，聚焦模块间的交互。&lt;/p&gt;
&lt;h3 id="1-永恒的真理"&gt;1 永恒的真理&lt;/h3&gt;
&lt;h4 id="11-no-silver-bullet"&gt;1.1 No Silver Bullet&lt;/h4&gt;
&lt;p&gt;银弹是用来镇住狼人的唯一方法，那就是将银弹射入狼人的体内。软件编程中没有万能解决方案，没有特效药。如果有，软件就是一件简单的事情。&lt;/p&gt;
&lt;p&gt;软件是复杂的，千万行代码的软件比比皆是，而软件要素之间的依赖关系是动态的剪不断、理还乱。软件比其他任何构造物都复杂。&lt;/p&gt;
&lt;p&gt;软件是实时的，需要响应当下的状态，与硬件、网络、人的行为、其它软件等均相关联，这种实时是一种生命的不断向前，如果没有，那就没有软件的价值。&lt;/p&gt;
&lt;p&gt;软件是可变的，软件的生命在于它与现实世界的交互，双方处于螺旋而上升的变化状态中；现实世界因为软件的进步而更美好，更美好的现实世界驱动软件的进步；&lt;/p&gt;
&lt;p&gt;软件是不可见的，是现实生活中概念的虚实映射，进程是没法看见的，对概念的表达是肉眼看不见的东西，对世界是抽象的表达，舍象的呈现，无法全部表现。&lt;/p&gt;
&lt;p&gt;本质，是定义上无法舍去的东西，不可欠缺的性质。非本质是指次要的、附属的性质，不能最终影响事物本质的。&lt;/p&gt;
&lt;p&gt;而软件在本质上具有难度，归因就是软件具有复杂性。通过各种方法和思路，来降低复杂性给软件带来的影响。围绕软件的构建、环境、编程语言、库、框架等都是软件的非本质部分，而非本质的部分对于推进软件本质部分内容具有巨大的贡献，而往往非本质部分能够得到更简单的解决，间接降低软件整体的复杂度 。&lt;/p&gt;
&lt;p&gt;非本质部分的自动化可以大幅改善工作效率和工作质量，而目前对于软件本质来说，需要通过自动化非本质部分而腾出更多的时间给到软件本质，软件真正的价值上。这个和当前的云原生的理念是不谋而合！&lt;/p&gt;
&lt;h4 id="12-代码即设计文档"&gt;1.2 代码即设计文档&lt;/h4&gt;
&lt;p&gt;软件最终交付的有价值的内容除了代码，别无其它。而编程就是一个设计过程，只不过设计的是代码，而不是文档。产品的性能无法在制造和生产环境得到提升，能够得到提升的过程就是设计过程。不管是哪个环节，最终设计必须使用编程语言来表现，这个过程中编程语言才是最核心的设计要素。&lt;/p&gt;
&lt;p&gt;基本设计、详细设计等上游不应该偏离编程语言，因为编程、调测、测试等下游均是基于编程语言。所以如何端到端的打通整个过程，才是设计的初衷。设计需要创造力，编程就是一种创造行为，与其把不依赖编程语言的设计图翻译为代码，倒不如一开始让设计者编写代码来的省心。代码就是属于设计范畴，应该尽早的开始编写代码。&lt;/p&gt;
&lt;p&gt;代码是设计文档，并不代表代码是唯一文档。代码表达了“怎么做”和“是什么”，代码不能表达为什么这么做。而设计理由需要有地方承载。对于代码中的注释可以承担部分，注释需要弥补代码表达不出来的东西。另一方面，对代码进行说明的注释就是重复，应该避免这点。&lt;/p&gt;
&lt;p&gt;罗塞塔石碑&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;的文档，这是一份写个未来维护负责人的简单手册，描述了理解软件开发环境和软件架构的信息，描述构建和测试过程的执行方法，而其中的测试可以避免维护负责人理解的陷阱，在架构方面描述纵观全部代码的图表。&lt;/p&gt;
&lt;h4 id="13-一定会被修改的代码"&gt;1.3 一定会被修改的代码&lt;/h4&gt;
&lt;p&gt;代码如果不被修改，那软件的生命周期已经趋于死亡。“代码会被修改”是既定事实标准，我们做选择和判断时候优先考虑的事情。软件产生故障，需要修复；软件的新需求，需要新增；不管是修复还是新增，都是对软件的修改，软件必须迎合变化，没有一开始就能满足所有诉求的软件。&lt;/p&gt;
&lt;p&gt;需要编写经得起修改的代码，这个过程中代码的“可读”尤为重要。不管写代码需要耗费多少时间，只要读代码的时间能够缩短，那么我们就能够把消耗在写代码上的时间赚回来。要相信这点！&lt;/p&gt;
&lt;h3 id="2-正确的指导方针"&gt;2 正确的指导方针&lt;/h3&gt;
&lt;h4 id="21-kiss-keep-it-short--simple"&gt;2.1 KISS (Keep it short &amp;amp; simple)&lt;/h4&gt;
&lt;p&gt;保持简洁，容易理解，易于修改和使用。必不可少的最小集是什么，还能否做减法？功能简洁，接口简洁。奥卡姆剃刀，当一个事物存在多种解释时，最简单的哪个解释时正确的，减轻思考的负担、增强可读可理解，最后可敏捷修改。&lt;/p&gt;
&lt;h4 id="22-dry-dont-repeat-yourself"&gt;2.2 DRY (Don&amp;rsquo;t repeat yourself)&lt;/h4&gt;
&lt;p&gt;禁止重复的拷贝。发现重复应该立即予以消除，避免重复这点没有商量余地。重复的代码可读性下降、难以修改且分散多处测试困难。一定程度上的代码抽象化操作可以消除重复。逻辑执行抽象，就是给整个处理过程命名，将其函数化、模块化。对于数据的重复，需要定义常量来替换；对应的重复内容有了名称，提升了可读性。&lt;/p&gt;
&lt;p&gt;对于自动化作业对软件进行测试、构建和发布的持续集成也是消除重复，消除重复的手动作业，提升自动化水平。对于设计模式是一种防止重复思考的手法。&lt;/p&gt;
&lt;p&gt;WET, Write every time， Write everything twice重复同样的事情，正好也是DRY的反义词。&lt;/p&gt;
&lt;p&gt;对于数据库而言，不应该存储重复的数据，one fact only in one place；&lt;/p&gt;
&lt;h4 id="23-yagni-you-arent-going-to-need-it"&gt;2.3 YAGNI (You aren&amp;rsquo;t going to need it)&lt;/h4&gt;
&lt;p&gt;不用想太多，坚持只写当前需要的代码。比追求通用性，而复杂设计更应该重视单纯性，能用是第一位的，聚焦具体需求为基础的简单方案。&lt;/p&gt;
&lt;p&gt;想的太远只会增加代码的复杂度，提高修改的成本。所以编码的时候，要思考回到原点，保持纯粹的单纯简单，以代码阅读者的角度做些思考。&lt;/p&gt;
&lt;h4 id="24-pie-program-intently--expressively"&gt;2.4 PIE (Program intently &amp;amp; expressively)&lt;/h4&gt;
&lt;p&gt;编码更多要在表达上花心思，将软件运行方式直观地传达给阅读代码的人。代码是我们正确、完整地理解软件运行方式的唯一线索。代码是动态变更的，任何的文档都是跟不上的，因而编写可读性高的代码，用代码表达意图是唯一可取的方法。&lt;/p&gt;
&lt;p&gt;读代码的次数远多于写代码的次数，所以追求的是代码可读性而不是代码的易写性。代码只写一次，但是多次阅读，读代码的效率应优先于写代码的效率和执行代码的效率。&lt;/p&gt;
&lt;p&gt;表达意图的终极形态是&lt;code&gt;文学编程&lt;/code&gt;，将代码本身当作文档的编程方法，用于描述文档的语言和编程语言结合在一起。代码即文档，文档即代码。代码要表达作品的意图，并且要有自我说明的能力。&lt;/p&gt;
&lt;h4 id="25-slap-single-level-of-abstraction-principle"&gt;2.5 SLAP (Single level of abstraction principle)&lt;/h4&gt;
&lt;p&gt;抽象是分等级的，根据功能的复杂程度对象化概念进行分离，然后统一各层的抽象级别。统一各抽象级别之后，代码就可以像图书一样供人阅读。&lt;/p&gt;
&lt;p&gt;将代码分成级别统一的函数，能使代码具有概括性和可读性。函数一览起到目录作用，使代码拥有概括性。分割后的函数时小块代码，提升了代码的可读性。抽象度相同的处理在同一个地方，代码更加顺畅更加可读。函数结构化之后，各函数处理以调用比自己低一个级别的函数为中心。这种由其他函数调用组成的函数称为复合函数，符合函数要尽量小，如果想通过名称来表达意图，即使处理只有一行，也可以写成函数。&lt;/p&gt;
&lt;p&gt;面向对象中，容器时抽象类及其继承类。抽象类存放抽象级别较高的概念，继承类存放级别较低的概念。设计结构和编写内容时两件事情，需要独立的模式去实现。&lt;/p&gt;
&lt;h4 id="26-ocp-open--closed-principle"&gt;2.6 OCP (Open &amp;amp; closed principle)&lt;/h4&gt;
&lt;p&gt;代码需要满足对扩展开发，对修改关闭的属性。扩展开放表示代码的行为可以扩展，修改关闭表示对代码进行行为扩展时，其他代码完成不会受到影响。&lt;/p&gt;
&lt;p&gt;面向对象的多态是实现OCP的代表技术，领域模型是稳定的，识别系统中的稳定成分和不稳定部分，在这两部分之间通过稳定的接口将交界点包裹起来。受保护变化则使用这层接口防护墙将变更带来的影响抵御在外。&lt;/p&gt;
&lt;h4 id="27-naming-naming-is-important"&gt;2.7 Naming (Naming is important)&lt;/h4&gt;
&lt;p&gt;命名，一个合适的名字意味着元素被正确理解并正确地设计了出来。一个合适的名字表示设计已经完成了一大半。意图传达地核心概念就是命名，让人充分理解某个东西是怎么样做出来的，所以需要最大限度地在名字上下功夫。&lt;/p&gt;
&lt;p&gt;编码的时候并不是向读代码才去读的，在充分理解代码之后的修改或添加功能才是我们真正的目的。在读代码时，混乱的名字会占用所有的脑部资源，让编码困难。&lt;/p&gt;
&lt;p&gt;名字要能够搜索出来，不能是单个字母或数字，要避免常见的搜索在代码中产生无数个结果。名字要能够念出来，需要在团队中统一概念，传播给各个角色这些概念，大家在理解上是一致的。名字应该是基于标准术语来命名，避免大家心里映射才能理解元素表达的意思。&lt;/p&gt;
&lt;h3 id="3-unix思想"&gt;3 UNIX思想&lt;/h3&gt;
&lt;p&gt;UNIX是被认为是大量经验的结晶，是编写优秀代码的实用性技术集合。所以在这会讲明白其蕴涵的思想是什么，以及怎么做，而不去分析为什么，因为这就是历史的沉淀，一些约定俗成的规定，被证明是正确的，得到全世界开发者的赞同，并不断的完善。&lt;/p&gt;
&lt;p&gt;对我有些触发内容的点是，3.9 表达性原则和3.17 可扩展性原则。&lt;/p&gt;
&lt;h4 id="31-模块化原则"&gt;3.1 模块化原则&lt;/h4&gt;
&lt;p&gt;代码中关联性较强的元素聚集在一起就是模块，模块接口要简单明了，而不要冗余繁杂，最少和最小的接口提供最简练的功能。&lt;/p&gt;
&lt;p&gt;多个简单模块组装成软件，而每次修改都把影响控制在模块内。&lt;/p&gt;
&lt;h4 id="32-清晰原则"&gt;3.2 清晰原则&lt;/h4&gt;
&lt;p&gt;代码不应该复杂，应该清晰，便于理解。在读代码时，不要对难以读懂的部分再三解读。第一次需要解读可能那个时因为碰巧没看懂，如果第二次还需要解读，那就需要小重构了。此时可以添加注释解释为什么，或者把代码修改的更加容易理解。&lt;/p&gt;
&lt;h4 id="33-组合原则"&gt;3.3 组合原则&lt;/h4&gt;
&lt;p&gt;软件应该尽量做成一个简单的过滤器，接受某种数据流后，加工输出另一种数据流的软件。这种输入输出应该是简单明了的。通过不同的软件组合方式，就能够完成多种多样的任务。&lt;/p&gt;
&lt;h4 id="34-分离原则"&gt;3.4 分离原则&lt;/h4&gt;
&lt;p&gt;是常说的领域模型，因为每个领域内沉淀的内容是稳定的。同时为机制编写有效的测试代码，机制的寿命比较长，同时独立的机制是可以被其他软件重复使用的。&lt;/p&gt;
&lt;h4 id="35-简单原则"&gt;3.5 简单原则&lt;/h4&gt;
&lt;p&gt;代码设计的足够简单，只能规定只在必要的情况下添加复杂代码。团队间应该营造简单即美丽的文化氛围。&lt;/p&gt;
&lt;h4 id="36-简约原则"&gt;3.6 简约原则&lt;/h4&gt;
&lt;p&gt;简约和简单不同在于不写大代码，一方面指代码量大，也指代码复杂指数大。要吝啬，尽量少写，让代码维持小的状态。随着代码的添加而变大，就要尽快对代码进行分割。&lt;/p&gt;
&lt;h4 id="37-透明性原则"&gt;3.7 透明性原则&lt;/h4&gt;
&lt;p&gt;设计软件时，要从外部清楚看到软件的运行状态，不仅让软件正确运行，还要让人能够看到它是在正确地运行。软件需要一眼就能理解软件正在做什么和软件是怎么做地，同时要呈现并监控其内部状态。正式地代码中加入能够简化调试地机制是一件好事，需要认真对待。这是对于系统可观测能力地提升。&lt;/p&gt;
&lt;h4 id="38-健壮性原则"&gt;3.8 健壮性原则&lt;/h4&gt;
&lt;p&gt;软件不仅能在一般条件下正常运行，还能再预想之外地条件下提供适当地服务。要想代码具有健壮性，需要保证人们能轻松识别其内部结构。&lt;/p&gt;
&lt;h4 id="39-表达性原则"&gt;3.9 表达性原则&lt;/h4&gt;
&lt;p&gt;代码中地信息要尽量用数据而非逻辑来表达。将信息固定在数据一侧，可以提高逻辑地可读性和健壮性。数据不论多么复杂都能轻松地模型化，用数据来表达信息也更加简单。使用换算表地数组初始化语句与switch语句相比，数据结构一方面更容易理解。&lt;/p&gt;
&lt;p&gt;我们应当把代码中无法避免的复杂部分交给数据表示。当遇到数据和逻辑必须要有一个复杂化的情况时，毫不犹豫选择的是让数据复杂化。这也就是我们的领域模型，通过模型上的数据来承担过程逻辑。&lt;/p&gt;
&lt;h4 id="310-最小意外原则"&gt;3.10 最小意外原则&lt;/h4&gt;
&lt;p&gt;接口的设计尽量不要让使用者感到意外，让接口运行符合用户的预期。对于一些约定俗成的东西，我们去遵循就好了，我们往往希望看到熟悉的东西就是自己熟知的东西，而不是还需要一层映射才能理解。当然有时候场景的区分需要通过不同来显示区分，比如get从一个模块获取数据，而fetch用以表示获取远程模块的数据。这个fetch和git中的概念就是保持一致的。&lt;/p&gt;
&lt;h4 id="311-沉默原则"&gt;3.11 沉默原则&lt;/h4&gt;
&lt;p&gt;软件应该将希纳是的内容控制在最少的程度，除非遇到必须提醒的情况。只输出重要的信息，内部运行的信息不要参杂其中。对于错误发生时只将真正错误的部分作为标准错误输出，不输出所需范围之外的任何数据。对于调试而需要的信息，可以通过一个冗余模式的开关，默认让其处于关闭状态。&lt;/p&gt;
&lt;h4 id="312-修复原则"&gt;3.12 修复原则&lt;/h4&gt;
&lt;p&gt;软件运行过程中，出现错误且修复失败，就应该立即停止处理，同时还应该有明显的提示。对修复失败情况下继续处理，就会出现最坏的结果，故障可能在不知不觉中破坏所有的数据。&lt;/p&gt;
&lt;p&gt;软件在发生错误时应尽早让人立刻知晓，软件在无法自行修复的时候，需要把控制权交给用户进行判断，这点很重要。&lt;/p&gt;
&lt;h4 id="313-经济原则"&gt;3.13 经济原则&lt;/h4&gt;
&lt;p&gt;程序员的时间时宝贵资源，值得珍惜。任何浪费程序员的时间都是不经济的。&lt;/p&gt;
&lt;h4 id="314-生成原则"&gt;3.14 生成原则&lt;/h4&gt;
&lt;p&gt;生成原则指编写用于生成代码的代码，减少手动操作，编写用于生成代码地代码。只在优先的范围内生成代码也是很有效果的，重复的、形式固定的代码尤其适合由代码生成器生成。&lt;/p&gt;
&lt;h4 id="315-优化原则"&gt;3.15 优化原则&lt;/h4&gt;
&lt;p&gt;在代码优化之前，先要保证代码能够正常运行。代码尚且不能充分运行阶段，对细节进行打磨是一种吃力不讨好的做法。先要确保代码正确运行，再去追求所谓的运行速度，确保足够的简单。代码越简单，可优化的地方就越容易被找到。&lt;/p&gt;
&lt;h4 id="316-多样性原则"&gt;3.16 多样性原则&lt;/h4&gt;
&lt;p&gt;容许存在多种方法，在软件中没有唯一正确的方法。我们不能相信任何宣传软件开发存在唯一正确方法的言论。应该认可多样性，调动思维，不断寻找更好的方案。&lt;/p&gt;
&lt;h4 id="317-可扩展性原则"&gt;3.17 可扩展性原则&lt;/h4&gt;
&lt;p&gt;通过代码可扩展，代码能满足多样的需求。可以采用可插拔的设计，对于扩展可插拔接口部分，要采用灵活的设计，并且在代码一旁加上“如果需要xxx”的注释。另外，可扩展性并不是添加非必要的功能，而是要编写能在需要的时候轻松添加相应功能的代码。&lt;/p&gt;
&lt;p&gt;可扩展性同样适用于数据格式，要让数据格式具有自我描述和可扩展性。让数据格式由几个独立的自我描述部分组成能够取得更好的效果，而不依赖顺序，甚至依赖其他数据。这样做的好处，可以在不搞混所读取的代码的前提下添加新的部分和删除旧的部分。&lt;/p&gt;
&lt;h3 id="ref"&gt;REF&lt;/h3&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://baike.baidu.com/item/%e7%bd%97%e5%a1%9e%e5%a1%94%e7%9f%b3%e7%a2%91/34799?fr=aladdin" target="_blank" rel="noopener"&gt;罗塞塔石碑（古埃及托勒密王朝著名石碑）_百度百科 (baidu.com)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>云原生开篇</title>
<link>https://liaolile.com/post/tech/cloudnative/%E4%BA%91%E5%8E%9F%E7%94%9F/</link>
<pubDate>Thu, 10 Feb 2022 09:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/cloudnative/%E4%BA%91%E5%8E%9F%E7%94%9F/</guid>
<description>&lt;p&gt;[toc]&lt;/p&gt;
&lt;h4 id="0-云原生"&gt;0. 云原生&lt;/h4&gt;
&lt;p&gt;云原生是一种思想，是一种解决方案，是一种抽象。云原生是从云的原生应用角度出发，是一种构建和运行应用程序的方法，是一套技术体系和方法论&lt;code&gt;Cloud Native Stack&lt;/code&gt;，一整套设计、开发、部署、运行、维护的流程、技术栈以及背后文化理念的统称。&lt;strong&gt;云原生&lt;/strong&gt;是一个用来描述应用、架构、平台/ 基础架构和流程的形容词，包括研发流程规范，软件架构，基础设施和工具集，是一套不断自我演进的理论体系提供指导思想和最佳实践的组合。谈云原生的本质，不如我们将它理解为一套愿景，一种文化，而不具象为哪些技术体系&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;您是否能&lt;strong&gt;赢得、服务和留住&lt;/strong&gt;&lt;code&gt;客户&lt;/code&gt;，很大程度上取决于能否通过&lt;strong&gt;软件应用持续、快速地交付新功能&lt;/strong&gt;，提供备受认可的业务价值。而云原生就是为了这个价值而努力的手段；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CNCF（云原生计算基金会）&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中，构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。&lt;/p&gt;
&lt;p&gt;这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段，云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;VMware Tanzu&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;云原生是一种利用云计算交付模型的优势来构建和运行应用程序的方法论。当企业使用云原生架构开发和运维应用程序时，它们能更快速地响应客户需求将新想法推向市场。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;云原生是关于不需要人类做出决定的自治系统。它仍然使用自动化，但只有在决定了所需的操作之后。只有在系统不能自动确定正确的事情时才应该通知人。具有这些特征的应用程序需要一个能够实际监控，收集度量标准并在发生故障时做出反应的平台。&lt;/p&gt;
&lt;p&gt;云原生系统（pivotal公司2017）一般具有如下的特点，：模块化（Modularity）、可观测性（Observability）、可部署性（Deployability）、可测试性（Testability）、可处理性（Disposability）、可替代性（Replaceability）。&lt;/p&gt;
&lt;h5 id="01-云原生的范围内容"&gt;0.1 云原生的范围内容&lt;/h5&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;云原生范围&lt;/th&gt;
&lt;th style="text-align:left"&gt;主要内容&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;方法论与原则&lt;/td&gt;
&lt;td style="text-align:left"&gt;12要素，声明式API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;流程规范&lt;/td&gt;
&lt;td style="text-align:left"&gt;DevOps，持续交付，自动化测试，Code Review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;软件架构&lt;/td&gt;
&lt;td style="text-align:left"&gt;微服务，服务网格，无服务&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;基础设施&lt;/td&gt;
&lt;td style="text-align:left"&gt;敏捷基础设施，如K8S、Docker、云服务器、云数据库、云存储等&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;工具集&lt;/td&gt;
&lt;td style="text-align:left"&gt;Prometheus，Envoy，Jaeger等&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h5 id="02-云原生中的代表技术"&gt;0.2 云原生中的代表技术&lt;/h5&gt;
&lt;img src="https://s2.loli.net/2022/06/04/73n8N26SJQDCXlq.jpg" style="zoom: 33%;" /&gt;
&lt;ol&gt;
&lt;li&gt;不可变基础设施&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;基础设施可编程且不可变的，直接通过API可以对外提供服务，通过代码或者配置来定义一组基础设施，并通过版本化的管理能够保证业务的快速变更。其中的应用载体是不可变的，自包含构建方式以及运行环境，简化应用的更新，删除旧实例，上线新实例。&lt;/p&gt;
&lt;p&gt;任何的基础实例（服务器、容器等各种软硬件）一旦创建之后便成为一种只读状态，不对其进行任何更改，如果需要修改或升级实例，唯一方式是创建一批新实例以替换。&lt;/p&gt;
&lt;p&gt;Pets Vs Cattle&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;，宠物和牲口。过去依赖传统的高可靠基础设施，服务的可靠性依赖于高可靠性的服务器，对待服务器就像对待宠物一样，需要实时关注服务的状态并精心维护，系统故障或者升级时候需要通过对服务器进行修复和配置实现。牲口模式下，底层系统故障或者需要升级，直接杀掉后重新创建一个，云原生的架构下底层就是依赖这种模式。&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4 id="pets"&gt;Pets&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Servers or server pairs that are treated as indispensable or unique systems that can never be down. Typically they are manually built, managed, and “hand fed”. Examples include mainframes, solitary servers, HA loadbalancers/firewalls (active/active or active/passive), database systems designed as master/slave (active/passive), and so on.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;h4 id="cattle"&gt;Cattle&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Arrays of more than two servers, that are built using automated tools, and are designed for failure, where no one, two, or even three servers are irreplaceable. Typically, during failure events no human intervention is required as the array exhibits attributes of “routing around failures” by restarting failed servers or replicating data through strategies like triple replication or erasure coding. Examples include web server arrays, multi-master datastores such as Cassandra clusters, multiple racks of gear put together in clusters, and just about anything that is load-balanced and multi-master.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;相同的类比是：雪花服务器和凤凰服务器，雪花服务器是手工管理的服务器，需要经常更新和调整，从而形成独特的环境。凤凰服务器总时从0开始构建，并且很容易通过自动化过程重新创建（浴火重生）。&lt;/p&gt;
&lt;p&gt;不可变基础设施同不可变变量类似，完成赋值后不能够被修改。运行服务的服务器在完成部署后，就不再进行变更，这一点是通过容器镜像来实现的，是一个自包含、自描述可以完全在不同的环境中迁移的东西。&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;声明式API&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;描述最终的状态和幂等性。&lt;/p&gt;
&lt;ol start="3"&gt;
&lt;li&gt;
&lt;p&gt;容器&lt;/p&gt;
&lt;p&gt;作为应用包装的载体。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务网格&lt;/p&gt;
&lt;p&gt;服务网格（Service Mesh）这个术语通常用于描述构成这些应用程序的微服务网络以及应用之间的交互。随着规模和复杂性的增长，服务网格越来越难以理解和管理。它的需求包括服务发现、负载均衡、故障恢复、指标收集和监控以及通常更加复杂的运维需求，例如 A/B 测试、金丝雀发布、限流、访问控制和端到端认证等，服务于系统的可观测性、安全性和可靠性。通常是由平台层而不是应用层来实现。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;微服务&lt;/p&gt;
&lt;p&gt;微服务是一种分布式架构设计理念，为了推动细粒度服务的使用，这些服务要能协同工作，每个服务都有自己的生命周期。一个微服务就是一个独立的实体，可以独立的部署在 Paas 平台上，也可以作为一个独立的进程在主机中运行。服务之间通过 API 访问，修改一个服务不会影响其它服务。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id="03-云原生基础设施"&gt;0.3 云原生基础设施&lt;/h5&gt;
&lt;p&gt;云，它是一种新兴的 IT 基础设施交付方式，通过虚拟化技术，对 IT 硬件资源与软件组件进行了标准化、抽象化和规模化，变成 “产品服务” 和 “账单”（pay as you go）。&lt;/p&gt;
&lt;p&gt;Support for cloud native attribute: modularity, operability, elasticity, resilliency;&lt;/p&gt;
&lt;p&gt;Gartner 将云原生基础设施划分：Iaas(VMs), Caas(Container), Serverless, Faas&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/04/zc7SQiZYG8IenPf.jpg" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;目前更多的AI出现，衍生的Daas，数据即服务，AI与云服务结合产生很多高价值的服务。&lt;/p&gt;
&lt;h4 id="1-云原生应用"&gt;1. 云原生应用&lt;/h4&gt;
&lt;p&gt;云原生应用是一个相互关联但又不独立的组件（&lt;strong&gt;service、task、worker&lt;/strong&gt;）的集合，这些组件与配置结合在一起并在适当的运行时实例化后，共同完成统一的功能目的。云原生应用开发是根据众所周知的云计算技巧与技术构建、运行和改进应用的一种方法。云原生应用是独立的小规模松散耦合服务的集合。&lt;/p&gt;
&lt;p&gt;云原生应用程序被设计为在平台上运行，并设计用于&lt;strong&gt;弹性，敏捷性，可操作性和可观测性&lt;/strong&gt;。弹性包含失败而不是试图阻止它们；它利用了在平台上运行的动态特性。敏捷性允许快速部署和快速迭代。可操作性从应用程序内部控制应用程序生命周期，而不是依赖外部进程和监视器。可观测性提供信息来回答有关应用程序状态的问题。&lt;/p&gt;
&lt;p&gt;符合云原生架构的应用程序应该是：采用开源堆栈（K8s+Docker）进行容器化，基于微服务架构提高灵活性和可维护性，借助敏捷方法、DevOps支持持续迭代和运维自动化，利用云平台设施实现弹性伸缩、动态调度、优化资源利用率。通过一组架构原则和设计模式，将应用中的非业务代码部分进行最大化的剥离，从而让云设施接管应用中原有的大量非功能特性（如弹性、韧性、安全、 可观测性、灰度等），借助云原生委托大量应用非功能性特性，使业务不再受非功能性业务中断困扰的同时，具备轻量、敏捷、高度自动化的特点。&lt;/p&gt;
&lt;h5 id="11-云原生应用模型"&gt;1.1 云原生应用模型&lt;/h5&gt;
&lt;p&gt;&lt;code&gt;OAM &lt;/code&gt;全称是 Open Application Model，旨在定义了云原生应用的标准，阿里巴巴和微软共同开源的云原生应用规范模型[^]。云原生中的大部分概念来自于此，对不同平台和场景的逻辑中DevOps做出更高级别的抽象。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;开放（Open）：支持异构的平台，容器运行时、调度系统、云供应商、硬件配置等；与底层无关，与供应商无关；&lt;/li&gt;
&lt;li&gt;应用（Application）：云原生应用&lt;/li&gt;
&lt;li&gt;模型（Model）：应以标准，以使其与底层平台无关；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OAM中定义的术语对象概念：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Workload（工作负载）：应用程序的工作负载类型（如有状态工作负载）对于部署单元的具体描述，由平台提供；&lt;/li&gt;
&lt;li&gt;Component（组件）：定义了Workload的实例，并以基础设施中的术语声明其运维特性；&lt;/li&gt;
&lt;li&gt;Trait（特性）：用于将运维特性（如弹性、回滚、实例个数等）分配给组件实例；&lt;/li&gt;
&lt;li&gt;ApplicationScope（应用作用域）：将组件划分为具有共同特性的松散耦合的应用（如网络/健康）；&lt;/li&gt;
&lt;li&gt;ApplicaitonConfiguration（应用配置）：描述Component的部署、包括Trait和ApplicationScope；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;云原生应用来说：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基础设施运维：提供不同的Workload类型供开发者使用；&lt;/li&gt;
&lt;li&gt;应用运维：定义适用于不同Workload的运维属性Trait和管理Component的ApplicaitonScope；&lt;/li&gt;
&lt;li&gt;应用开发者：负责应用组件Component的定义；&lt;/li&gt;
&lt;li&gt;应用开发和运维：应用程序全生命周期管理，绑定Component和Trait；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/04/aBAnFwUrSj4RPxX.jpg" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;OAM规范原则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;关注点分离：根据功能和行为来定义模型，以此划分不同角色的职责，&lt;/li&gt;
&lt;li&gt;平台中立：OAM 的实现不绑定到特定平台；&lt;/li&gt;
&lt;li&gt;优雅：尽量减少设计复杂性；&lt;/li&gt;
&lt;li&gt;复用性：可移植性好，同一个应用程序可以在不同的平台上不加改动地执行；&lt;/li&gt;
&lt;li&gt;非编程模型：OAM 提供的是应用程序模型，描述了应用程序的组成和组件的拓扑结构，而不关注应用程序的具体实现。&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="12-云原生应用12军规"&gt;1.2 云原生应用12军规&lt;/h5&gt;
&lt;p&gt;&lt;code&gt;The Twelve-Factor App&lt;/code&gt;：云原生应用架构的模式集合&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/04/iJdvcAYptLHM8l3.jpg" style="zoom: 33%;" /&gt;
&lt;p&gt;更多3项&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API声明管理，万物皆服务。你的代码会被一个前端客户端、网关或者其他服务调用；&lt;/li&gt;
&lt;li&gt;认证和授权，从 一开始就需要考虑设计；&lt;/li&gt;
&lt;li&gt;监控与告警，领域相关的监控以及健康数据；&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="13-云原生系统哲学"&gt;1.3 云原生系统哲学&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;面向分布式设计（Distribution）：容器、微服务、API驱动的开发；&lt;/li&gt;
&lt;li&gt;面向配置设计（Configuration）：一个镜像，多个不同环境配置；&lt;/li&gt;
&lt;li&gt;面向韧性设计（Resistancy）：故障容忍和自愈；&lt;/li&gt;
&lt;li&gt;面向弹性设计（Elasticity）：弹性扩展和环境（负载）做出响应；&lt;/li&gt;
&lt;li&gt;面向交付设计（Delivery）：自动拉起，缩短交付时间；&lt;/li&gt;
&lt;li&gt;面向性能设计（Performance）：响应式，并发和资源高效利用；&lt;/li&gt;
&lt;li&gt;面向自动化设计（Automation）：自动化的Devops；&lt;/li&gt;
&lt;li&gt;面向诊断性设计（Diagnosability）：集群级别的日志、metric和追踪；&lt;/li&gt;
&lt;li&gt;面向安全设计（Security）：安全端点、API Gateway、端到端加密&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id="14-关于云原生应用的健康报告和遥测数据"&gt;1.4 关于云原生应用的健康报告和遥测数据&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;健康报告&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;停止逆向工程应用程序并开始从内部进行监控。 —— Kelsey Hightower，Monitorama PDX 2016：healthz&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;应用程序应该暴露健康检查以便提高其可操作性和管理自动化；一个常见的手段是提供web服务，返回Http状态码来检查健康状态。对于平台需要更准确的了解应用程序所处的状态，平台需要知道应用程序什么时候开始接受流量，而应用通过该检查来表明自身的健康。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;遥测数据&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;遥测数据是进行决策所需的信息。遥测数据可能与健康报告存在部分重叠，但它们有不同的用途。&lt;code&gt;健康报告&lt;/code&gt;通知我们&lt;strong&gt;应用程序生命周期状态&lt;/strong&gt;，而&lt;code&gt;遥测数据&lt;/code&gt;通知我们&lt;strong&gt;应用程序业务目标&lt;/strong&gt;。更加关注的应用层面SLO内容，而不是某个节点，确保应用程序的性能处于服务级别目标内。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;请求率&lt;/code&gt;: 收到了多少个请求？&lt;code&gt;错误&lt;/code&gt;: 应用程序有多少错误？&lt;code&gt;时间&lt;/code&gt;: 多久才能收到回复？&lt;/p&gt;
&lt;h4 id="2-云原生实践"&gt;2. 云原生实践&lt;/h4&gt;
&lt;h5 id="21-cncf-给出的云原生实践路线图"&gt;2.1 CNCF 给出的云原生实践路线图&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;容器化&lt;/p&gt;
&lt;p&gt;一般目前以Docker为主要方式进行容器化。各类应用均可进行容器化，容器化建议服务分割为微服务的方式进行；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CI/CD&lt;/p&gt;
&lt;p&gt;创建持续集成持续部署的环境，敏捷的快体现就是快速集成，快速发布。使得整个Devops可以自动从源码进行容器化构建和测试，并部署到生产环境。同时系统可以自动部署、自动回滚、自动测试。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;应用定义和编排&lt;/p&gt;
&lt;p&gt;Kubernetes作为容器化的应用编排成熟解决方案，目前使首选。Helm Charts能帮助使用者对复杂的Kubernetes应用进行定义、安装和升级&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;监控和分析&lt;/p&gt;
&lt;p&gt;解决方案应该包括监控、日志、和追踪（metrics、logs、tracing），推荐的为Prometheus监控和告警、Fluentd用于日志，而Jaeger用于调用链追踪。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务代理、服务发现和服务网格&lt;/p&gt;
&lt;p&gt;提供健康检查、请求路由方向代理以及负载均衡等。服务发现可以使用CoreDNS, 服务网格目前成熟的使Envoy和Linkerd。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;网络和策略&lt;/p&gt;
&lt;p&gt;网络需求可以基于CNI兼容的网络解决方案如Flannel或者Weave Net。OPA(Open Police Agent)秉承着“策略即代码”原则，完成通用的策略引擎的基本功能，使用者控制策略和权限确保合规。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分布式数据库与存储&lt;/p&gt;
&lt;p&gt;分布式数据库可以获取更好的弹性和伸缩性能。确保横向扩展中，通过sharding的方式保证mysql的横向扩展性，Vitess是一个不错的选择。作为Kubernetes大脑的，etcd提供了集群中以可靠的方式存储数据的能力；需要使用KV存储时候，可以考虑TiKV，其使用Rust编写的高性能的分布式事务级Key-Value解决方案。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;流与消息处理&lt;/p&gt;
&lt;p&gt;对于json-rest更高性能诉求时候，gRPC或者NATS是一个更好的选择。NATS是一个包含了请求、发布/订阅、复杂均衡队列的多模型消息系统；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;镜像私库和运行环境&lt;/p&gt;
&lt;p&gt;可以使用Harbor作为镜像私库进行存储以及内容扫描，运行环境需要使用具有OCI兼容性的方案。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;软件分发&lt;/p&gt;
&lt;p&gt;TLS能够去确保通信的安全，特别是当服务器出现问题后，使用Notary/TUF可以解决这问题，是，使得在软件的分发和更新更加安全。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id="22-helm包管理"&gt;2.2 Helm包管理&lt;/h5&gt;
&lt;p&gt;Helm是K8s生态系统中的软件包管理工具，为了以下的目的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;管理、编辑以及更新分散在各处的kubernetes API 对象描述文件；&lt;/li&gt;
&lt;li&gt;相关配置文件作为一个应用进行管理，管理应用依赖关系、管理应用版本并发布软件仓库；&lt;/li&gt;
&lt;li&gt;分发和重用K8s应用配置；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Helm包中的概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tiller: Helm的服务端，部署在K8s集群中用于处理Helm命令；&lt;/li&gt;
&lt;li&gt;Chart： Helm的打包格式，不好了一组相关K8s的配置；&lt;/li&gt;
&lt;li&gt;Repository：Helm的软件仓库，该软件仓库保存了Chart软件包以供下载，并提供Chart包清单以供查询；&lt;/li&gt;
&lt;li&gt;Release： 使用Helm install命令在K8s集群中安装Chart就成为Release&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通过一系列的Helm命令，可以创建、校验、打包、绑定repo，搜索、部署、查看、升级、回滚的对应的应用；Helm总有一个字段Revision记录了Release的被更新次数，同etcd中的Revision（Create Revision/Mod Revision等）概念一致，对应于某个时间点的版本信息；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reference&lt;/strong&gt;:&lt;/p&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://landscape.cncf.io/" target="_blank" rel="noopener"&gt;CNCF Cloud Native Interactive Landscape&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="http://cloudscaling.com/blog/cloud-computing/the-history-of-pets-vs-cattle/" target="_blank" rel="noopener"&gt;The History of Pets vs Cattle and How to Use the Analogy Properly | Cloudscaling&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://12factor.net/" target="_blank" rel="noopener"&gt;The Twelve-Factor App (12factor.net)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>理解Boltdb</title>
<link>https://liaolile.com/post/tech/cloudnative/%E7%90%86%E8%A7%A3boltdb/</link>
<pubDate>Wed, 13 Oct 2021 12:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/cloudnative/%E7%90%86%E8%A7%A3boltdb/</guid>
<description>&lt;p&gt;[toc]&lt;/p&gt;
&lt;p&gt;😃&lt;/p&gt;
&lt;p&gt;在不同的场景、不同的组件中。具体采用&lt;strong&gt;自底向上&lt;/strong&gt;还是&lt;strong&gt;自顶向下&lt;/strong&gt;来分析。见仁见智，也具体问题具体分析。在本篇中自底向上分析boltdb，然后到etcd，应为etcd的底层就依赖于boltdb的数据存储。&lt;/p&gt;
&lt;h3 id="1-boltdb"&gt;1. boltdb&lt;/h3&gt;
&lt;h4 id="11-boltdb基本理解"&gt;1.1 boltdb基本理解&lt;/h4&gt;
&lt;p&gt;boltdb 是一个纯 go 编写的支持事务的文件型单机 kv嵌入式数据库。目前支持的事务包括：&lt;em&gt;读写事务、只读事务&lt;/em&gt;。事务中的所有操作都在内存中进行，只有commit时候才会写磁盘。boltdb所有数据都存储在磁盘上，数据涉及在内存和磁盘的交换，适用于读多写少的存储场景。其对外暴露的是kv的接口，支持数据类型均是[]byte的key和value。&lt;/p&gt;
&lt;p&gt;boltd的源码大约4000行&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;， 目前已经归档，是目前etcd，InfluxDb依赖的底层存储。boltdb中三大概念名词：DB, Bucket， K/V。如果把boltdb比喻成衣柜，我们把东西整理放入衣柜就是对boltd的操作，Bucket就是柜子分隔后的小柜子或者抽屉，K/V就是放入衣柜的每个东西，其中K就是这个东西的标记，V就是具体的东西。换着说：boltdb是有多个桶Bucket，每个桶存放键值对数据kv。&lt;/p&gt;
&lt;p&gt;boltdb每个db对应一个文件，文件按照page来组织，page id为0和1的两个page是metadata，同时还有freelist的page用来存放空闲的page id， 剩下的page构成一个B+树包括brach page用于存放具体的索引信息以及leaf page存放真实的用户数据。通过Bucket来支持namespace，每个Bucket是一个完整的B+树。&lt;/p&gt;
&lt;p&gt;全局视图如下：&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/26/4oxOWdGKq6gB5IQ.png" alt="image-20220626174419166" style="zoom:80%;" /&gt;
&lt;h4 id="12-boltdb数据结构"&gt;1.2 boltdb数据结构&lt;/h4&gt;
&lt;p&gt;对于文件数据库的性能提升，因为文件是在磁盘上，为了减少读磁盘的时间（寻道时间+旋转时间+传输时间），同时顺序读写比随机更快，因而性能提升主要聚焦在如何最大程度进行顺序读写方式来进行数据的写入和查询。&lt;/p&gt;
&lt;p&gt;如何将用户写进来在内存中的数据尽可能采用顺序写的方式放进磁盘，同时在用户读数据时候，将磁盘中保存的数据尽可能少的IO调用次数加载到内存中，而返回给用户。&lt;/p&gt;
&lt;p&gt;对于boltdb在存储结构上，磁盘上是按照4K的page进行数据结构组织，内存中的数据结构是node，还有一个page和node之间的相互转化。对于boltdb的set操作，本质上对应的就是set-&amp;gt;node&amp;gt;page-&amp;gt;file， 而对于get操作是file-&amp;gt;page-&amp;gt;node-&amp;gt;get的过程。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/26/xjMyzIXcnbClYh6.jpg" style="zoom:80%;" /&gt;
&lt;p&gt;boltdb没有实现page cache，而是调用mmap将整个文件进行内存映射，并且调用madvise(MADV_RANDOM)由操作系统管理page cache，后续对磁盘上的文件的所有读写操作直接读取db.data即可。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// mmap memory maps a DB&amp;#39;s data file.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;mmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sz&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;// Map the data file to memory.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;	&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;syscall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Mmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fd&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;syscall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PROT_READ&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;syscall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAP_SHARED&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MmapFlags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;// Advise the kernel that the mmap is accessed randomly.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nf"&gt;madvise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;syscall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MADV_RANDOM&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;madvise: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="c1"&gt;// Save the original byte slice and convert to a byte array pointer.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;	&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataref&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;maxMapSize&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;unsafe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;datasz&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;boltdb中，一个Bucket对象是一颗B+树，它上面存储一批kv键值对，同时一个Bucket下还可以由嵌套的subbucket。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Page&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据在磁盘上按照Page页来存储的，以page为单位来读取和写入数据，page大小是保持和操作系统对应的内存页大小一致。page上由两部分数据组成：header+data，即页头数据和真实数据，页头数据占用16字节。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/26/GsQkzCZB5ce1PhT.jpg" style="zoom:80%;" /&gt;
&lt;p&gt;boltdb在写入数据到磁盘文件时候直接写入的是page结构体的二进制，避免了序列化和反序列化的开销；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;meta page&lt;/strong&gt;, 其pageId是固定的0和1，该page主要用来保存数据库的基本信息，比如根节点、版本号、空闲列表，当前元数据页的id，最大的事务txid等；其中一个元数据页出问题了，可以使用另外一份进行修复来保证数据库可用。每次读写事务前，都会选取txid最大的那个meta进行事务初始化，同时MVCC时，会拷贝最新的meta。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;leaf page&lt;/strong&gt;，是用户的数据实际存储的结构，相关的对应地址信息可以通过header中的数据获取得到。存在如下的关系:&amp;amp;leafPageElement + pos == &amp;amp;key、&amp;amp;leafPageElement + pos + ksize == &amp;amp;val。&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/06/26/xdjmJKuplqWwe8P.jpg" style="zoom:80%;" /&gt;
&lt;p&gt;对于上述的leafPageElement中的flags取值为0时，表示叶子节点为普通的key/value类型，取值为1时，标识叶子节点为桶类型，其key为桶的key，当桶中的元素很少时，value会填充为桶的pgid以及其内联的kv节点数据。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;branch page&lt;/strong&gt;, 主要用于构建索引，方便提升查询效率。一个分支页节点页上会存储多个分支页元素即branchPageElement，branch node的value是子节点的pageId，存放在branchPageElement中，而key的存储相同都是通过pos获得。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/26/73aPx2do9AcgFz1.jpg" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;B+树的存储中单个节点为node，包括branch和leaf节点，访问节点时首先将page的内容转化为内存中的node，每个node对应一个或多个连续的page。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/26/cNdKYwPZ72zj9hx.jpg" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;对于branch节点而言，每对key/val指向一个节点，key是子节点的其实range，val存放子节点的pageId。对于leaf节点，每对key/val存放数据，没有指针指向sibiling node；&lt;/p&gt;
&lt;p&gt;对于数据的查询过程如下步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;找到bucket的根节点，也就是B+树的根节点page id；&lt;/li&gt;
&lt;li&gt;读取对应的page，转化为内存中的node；&lt;/li&gt;
&lt;li&gt;若是branch node，则更具key查找合适的子节点的page id;&lt;/li&gt;
&lt;li&gt;重复2/3步骤找打leaf node，返回node中对应的value；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;freelist page&lt;/strong&gt;，空闲列表页中主要包含三个部分：所有已经可以重新利用的空闲页列表ids，将来很快释放掉的事务关联页的列表pending，页的id缓存。&lt;/p&gt;
&lt;h4 id="13-boltdb事务"&gt;1.3 boltdb事务&lt;/h4&gt;
&lt;p&gt;对于boltdb同一时间有且只能由一个读写事务执行，但是同一时刻允许多个只读事务执行。每个事务都拥有自己的一套一致性视图。&lt;/p&gt;
&lt;p&gt;boltdb所有的数据最终会保存在文件中，当事务结束后，会将数据进行刷盘。由于用户的直接改动数据最终都发生在叶子节点，为了维持B+树的性质，会在commit前进行调整，调整过程中会引起中间节点的级联变化。所有这些节点在&lt;code&gt;spill&lt;/code&gt;阶段通过node.write转化为页，所有变动的页称为脏页，在spill后会对这些脏页进行刷盘，按照下述的步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;将脏页按page id排序后逐个遍历；&lt;/li&gt;
&lt;li&gt;将page id转化为offset；&lt;/li&gt;
&lt;li&gt;通过db.ops.writeAt将脏页在offset处刷盘；&lt;/li&gt;
&lt;li&gt;通过page pool服用page size = 1的脏页，以备allocate时复用；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;对于刷盘有个开关控制db.NoSync，如果配置为true，每次commit后并不会刷盘，而是写入缓冲区，有操作系统决定真正落盘的时机；上述刷盘结束后，会对元信息（freelist和整个db元数据）进行刷盘，只有元信息页落盘成功，才会使得改动对用户可见。元信息页作为全局指针，该指针的写入原子性来保证事务的原子性，如果宕机元数据没有写入完成，所有改动便不会生效，达到了自动回滚的效果。&lt;/p&gt;
&lt;p&gt;boltdb会通过冗余一份元数据来做容错，当事务提交时，如果写入一般机器挂了，此时数据会有问题。当boltdb再次恢复时，会对元数据进行校验和修复。&lt;/p&gt;
&lt;p&gt;boldtb在上层支持多个进程以读写或者只读的方式打开数据库，在内部实现的时候底层是不同的锁，只读模式是共享锁，而读写模式是互斥锁。在数据库内部中支持上述说的读写事务和只读事务，两种类型的事务底层都保留一套完整的视图和元数据，彼此间相互隔离；&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;增量写内存。&lt;/li&gt;
&lt;li&gt;穿透读磁盘。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;读写事务的变动都在内存中，而只读事务通过 mmap 直接读取的磁盘上的内容，因此读写事务的改动不会为只读事务所见。多个读写事务是串行的，也不会互相影响。而每个只读事务期间所看到的状态，就是该只读事务开始执行时的状态。&lt;/p&gt;
&lt;h3 id="ref"&gt;REF&lt;/h3&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://github.com/boltdb/bolt" target="_blank" rel="noopener"&gt;boltdb/bolt: An embedded key/value database for Go. (github.com)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>说说缓存</title>
<link>https://liaolile.com/post/tech/distributesystem/%E8%AF%B4%E8%AF%B4%E7%BC%93%E5%AD%98/</link>
<pubDate>Mon, 04 Oct 2021 23:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/distributesystem/%E8%AF%B4%E8%AF%B4%E7%BC%93%E5%AD%98/</guid>
<description>&lt;p&gt;&lt;strong&gt;缓存使用场景：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;从&lt;strong&gt;硬件的角度&lt;/strong&gt;来说，缓存就是可以进行高速数据交换的存储器。最经典例子就是&lt;code&gt;CPU&lt;/code&gt;层面的多级缓存：性能最高的寄存器、多级缓存L1/L2/L3、主存，外部的机械硬盘。计算机总是优先从读写性能最好的存储器中来读写数据。&lt;/p&gt;
&lt;p&gt;从&lt;strong&gt;中间件的角度&lt;/strong&gt;来看，缓存在&lt;code&gt;数据库&lt;/code&gt;中应用，如Mysql拿到一个查询请求后，先会查询缓存是否命中（key为查询语句，value为查询的结果），如果命中则返回；实际中不建议，对于业务表查询缓存失效的概率极高；&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RocketMQ&lt;/code&gt;中的缓存，是在Page Cache机制的预读作用下使得Consumer queue文件的读性能几乎接近内存。Page Cache是操作系统对文件的缓存，使用一部分内存用作Page Cache。对于数据的写入，操作系统会先写入至Cache中，随后异步的方式由&lt;code&gt;pdflush&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;内核线程将Cache内的数据刷盘。对于数据读取，如果未出现命中Page Cache，操作系统从屋里磁盘上访问读取文件同时，会顺序对其相邻块数据文件进行预读取Read Ahead。Page Cache利用的是&lt;em&gt;时间局部性&lt;/em&gt;原理，最近访问的数据接下来再次访问当。预读取数据放入Page Cache利用的是&lt;em&gt;空间局部性&lt;/em&gt;原理，依据数据往往是连续访问。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Elastic Search&lt;/code&gt;中的缓存&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;包括Query Cache/Filter Cache、Request Cache、Field Data Cache。Query Cache就是对一个查询中包含的过滤器执行结果进行缓存；Request Cache模块就是为了缓存这些“分片级”的本地结果集，一个面向请求的缓存，缓存的key是查询DSL字符串。Fielddata是专门针对分词的字段在query-time（查询期间）的数据结构的缓存。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;常见主流的缓存算法&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LRU(Least-Recently-Used): 替换掉最近请求最少的对象，实际中使用最广。cpu缓存淘汰和虚拟内存效果好，web应用欠佳&lt;/li&gt;
&lt;li&gt;LFU(Least-Frequently-Used): 缓存污染问题(一个先前流行的缓存对象会在缓存中驻留很长时间)&lt;/li&gt;
&lt;li&gt;LRU2(Least Recently Used 2): 为什么LRU2优于LRU：当一次访问过来的时候，在缓存系统中找出最少最近使用的对象是一项时间复杂度非常高的运算，这就是为什么LRU2是最好的选择。&lt;/li&gt;
&lt;li&gt;2Q(two queues)。多级缓存&lt;/li&gt;
&lt;li&gt;SIZE：替换占用空间最大的。也会有缓存污染&lt;/li&gt;
&lt;li&gt;LRU-Threashold：不超过某一个size 的，其他与 LRU 相同&lt;/li&gt;
&lt;li&gt;Log(Size) + LRU: 替换 size 最大的对象，当size相同按 LRU 替换&lt;/li&gt;
&lt;li&gt;Hyper-G: LFU 改进版，同时考虑上次访问时间和对象 size&lt;/li&gt;
&lt;li&gt;Pitkow/Recker: 替换最近最少使用对象，除非所有对象都是今天访问过的。如果是，替换调最大的对象&lt;/li&gt;
&lt;li&gt;Lowest-Latency-First: 替换下载时间最少的，最小化平均延迟&lt;/li&gt;
&lt;li&gt;Hybrid Hybrid: 保留效用最低的会被替换掉&lt;/li&gt;
&lt;li&gt;Lowest Relative Value(LRV): 替换保留效用最低的&lt;/li&gt;
&lt;li&gt;Adaptive Replacement Cache(ARC)&lt;/li&gt;
&lt;li&gt;Most Recently Used(MRU)&lt;/li&gt;
&lt;li&gt;First in First out(FIFO)&lt;/li&gt;
&lt;li&gt;Random Cache&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缓存的应用&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;以web应用为例说明，用户请求到后台，会先从缓存中取数据，如果在缓存中取到数据，就直接返回结果，如果取不到数据就需要查询数据库，从数据库中取数据，从数据库中取到数据后会同步更新到缓存，并返回结果。下一个用户就可以直接从缓存中取值了。那如果在数据库也没有取到，就只能直接返回空结果。在该场景下，缓存主要是为了缓解数据库访问压力，提升请求响应；&lt;/p&gt;
&lt;div class="mermaid"&gt;flowchart LR
id1[用户请求]
id2{Redis中请求特征Key是否存在}
id3[获取redis中数据]
id4{数据库中请求特征key是否存在}
id5[更新Redis数据]
id6[返回空]
id7[返回Redis数据]
E[结束]

id1[用户请求] --&gt;id2
id2 --&gt;|Yes|id3
id2 --&gt;|No| id4
id3 --&gt; id7
id7 --&gt; E
id4 --&gt; |Yes|id5
id4 --&gt; |No| id6
id5--&gt; id7
id6--&gt; E
 
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;缓存失效或者异常&lt;/strong&gt;，导致访问压力流转到数据库，使得数据库负载过高；归于提升缓存命中率，同时数据库需要限流；&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;缓存穿透:&lt;/p&gt;
&lt;p&gt;外部可以非法请求一个缓存和数据库中必定不存在的数据，让其击穿缓存直接打到数据库，不断的大流量攻击就可以让数据库瘫痪。应对这种情况的发生，使用布隆过滤器进行过滤避免击穿，布隆过滤器存储空间小，可以存储大量的key。但是存在误判：布隆过滤器中没有的元素一定没有，但是布隆过滤器提示有的元素不一定有。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缓存击穿：&lt;/p&gt;
&lt;p&gt;当缓存数据失效的瞬间，大量的请求打入而没有命中导致直接打入数据库；需要通过互斥锁让线程回写缓存，其他线程等待回写缓存后再读取，这种方案缺点是吞吐量不够；另外可以设置热点数据不过期，或者异步线程基于要过期的数据缓存重构建；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缓存雪崩：&lt;/p&gt;
&lt;p&gt;缓存中数据大批量到过期时间，而查询数据量大落在数据库上，引起数据库压力大而宕机。缓存击穿是并发查询同一条数据，缓存雪崩是不同数据都过期了，很多数据查不到而查数据库。需要结合业务分析进行缓存预热，针对热key的失效点均衡分布。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缓存预热异常&lt;/p&gt;
&lt;p&gt;系统上线后，不需要用户访问后才加载缓存数据，而是先查数据库构建好缓存；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缓存降级异常&lt;/p&gt;
&lt;p&gt;缓存降级是指缓存失效的或者缓存服务器宕机后，不去访问数据库，而是直接返回默认数据或者访问服务的内存数据。降级一般是有损的，需要考虑其对业务的影响；&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://zhuanlan.zhihu.com/p/71217136" target="_blank" rel="noopener"&gt;Linux中的Page Cache  - 知乎 (zhihu.com)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://blog.csdn.net/chennanymy/article/details/52504386" target="_blank" rel="noopener"&gt;Elasticsearch2.x 三种缓存介绍：Query Cache、Request Cache、Fielddata Cache_飞奔的代码的博客-CSDN博客_es 缓存&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>安全架构设计</title>
<link>https://liaolile.com/post/tech/base/%E5%AE%89%E5%85%A8%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/</link>
<pubDate>Thu, 29 Apr 2021 12:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/base/%E5%AE%89%E5%85%A8%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/</guid>
<description>&lt;p&gt;如今，安全对于软件系统越来越重要！公司越大，对于安全方面的考虑也越重视！同时随着当前系统个人数据量激增，隐私保护也日益凸显！&lt;/p&gt;
&lt;p&gt;对于任何时候，安全隐私无小事！或多或少会影响，甚至因为安全事故导致公司破产！&lt;/p&gt;
&lt;p&gt;当今软件系统已不仅仅是功能正确，对于功能可用只是系统冰山一角，而冰面之下的的内容就是：软件安全、软件可信、软件韧性等非功能性内容。&lt;/p&gt;
&lt;p&gt;如何做到系统安全，如何打造稳健的系统？下述内容涉及从宏观角度来看，安全架构、安全设计相关最基本的，以及通用的内容。对于不同形式的软件系统可能涉及的关注点也不同，比如手机终端在组网安全的考虑就比较少。&lt;/p&gt;
&lt;p&gt;下述包括8个维度的安全动作内容和8个基本安全设计原则！&lt;/p&gt;
&lt;p&gt;如果把任何我们要开发的软件系统比做一场必须要赢得的战争，那安全架构就是战略级的威慑，而安全设计就是战术内容，而安全分析就是软件工程师面对的一场场的战斗，成熟的安全威胁库参考就是历史中发生的一场场的战役，而来自不同方面的安全需求就是我们面临每场战斗的具体战法，解决实际问题最需要的实践。&lt;/p&gt;
&lt;p&gt;下面&lt;code&gt;PPT&lt;/code&gt;内容详细呈现&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/22/johXAiPY3DczU5s.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/22/IE9Dt7lc4CoV82s.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/22/HblfVQmwjXRyzNO.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
</item>
<item>
<title>hey- a tiny program that sends some load to a web application</title>
<link>https://liaolile.com/post/tech/sourcecode/hey-a-tiny-program-that-sends-some-load-to-a-web-application/</link>
<pubDate>Mon, 26 Apr 2021 12:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/sourcecode/hey-a-tiny-program-that-sends-some-load-to-a-web-application/</guid>
<description>&lt;p&gt;&lt;strong&gt;源码地址&lt;/strong&gt;： &lt;a href="https://github.com/rakyll/hey" target="_blank" rel="noopener"&gt;rakyll/hey: HTTP load generator, ApacheBench (ab) replacement (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;源码语言&lt;/strong&gt;：GO&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;源码出品&lt;/strong&gt;：Google&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;源码关联分析&lt;/strong&gt;： &lt;a href="https://blog.csdn.net/chenchen5152/article/details/116378028" target="_blank" rel="noopener"&gt;(3条消息) fasthttp性能真的比标准库http包好很多吗？一文告诉你真相！_不想秃头的晨晨的博客-CSDN博客_fasthttp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/bigwhite/experiments/blob/master/http-benchmark/client/http_client_load.sh" target="_blank" rel="noopener"&gt;experiments/http_client_load.sh at master · bigwhite/experiments (github.com)&lt;/a&gt; hey的使用封装脚本&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;源码分析&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;hey主要借助go原生的net/http包构造测试请求，可以充当压测小工具。对于请求的响应会做详细的分析，包括：请求摘要信息（平均时延/Qps/最快时延/最慢时延等），响应时延（histogram、tp99等），以及请求时间的具体耗时分析。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/22/LPQcf2Koid5YztX.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;
&lt;p&gt;使用hey工具，hey直接linux使用运行，其结果可以输出到文件中，后续对文件内数据进行提取统计分析；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;其中的Makefile文件对于不同环境的构建进行描述，如下，并且使用&lt;strong&gt;make release&lt;/strong&gt;即可在linux进行编译构建;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/22/GQ8cHMxAhi6jsKX.png" alt="image-202205220940343103" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;源码借鉴&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;cmd的命令行参数解析，flag.string的使用，以及cmd help场景，做一个命令行工具的标准参考；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于需要做服务端的请求metrics信息统计，可以参考，快速实现直方图/TP时延等信息的收集；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;相关的并发协程的高级用法参考使用；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test测试用例的写法，t.Errorf即可输出测试用例失败场景；&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;TestBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;ioutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Body&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;         &lt;span class="nx"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddInt64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;httptest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HandlerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewBuffer&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Body&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;Work&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      &lt;span class="nx"&gt;RequestBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Body&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      &lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;           &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;           &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;      &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Expected to work 10 times, found %v&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
</item>
<item>
<title>easy-try一种存储介质可扩展的持久化重试方案</title>
<link>https://liaolile.com/post/tech/sourcecode/easy-retry-%E4%B8%80%E7%A7%8D%E5%AD%98%E5%82%A8%E4%BB%8B%E8%B4%A8%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E9%87%8D%E8%AF%95%E6%96%B9%E6%A1%88/</link>
<pubDate>Sat, 24 Apr 2021 12:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/sourcecode/easy-retry-%E4%B8%80%E7%A7%8D%E5%AD%98%E5%82%A8%E4%BB%8B%E8%B4%A8%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E9%87%8D%E8%AF%95%E6%96%B9%E6%A1%88/</guid>
<description>&lt;p&gt;&lt;strong&gt;源码地址&lt;/strong&gt;：&lt;a href="https://github.com/alibaba/easy-retry" target="_blank" rel="noopener"&gt;alibaba/easy-retry: easy-retry (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;源码语言&lt;/strong&gt;：Java&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;源码出品&lt;/strong&gt;：Alibaba&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;源码关联分析&lt;/strong&gt;： &lt;a href="https://github.com/houbb/sisyphus" target="_blank" rel="noopener"&gt;houbb/sisyphus: The java retry framework.(支持注解的 java 重试框架) (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;源码分析&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;其目录树结构为：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---easy-retry-common
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---easy-retry-core
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---easy-retry-extensions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;   ---easy-retry-mybatis-extension
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;   ---easy-retry-spring-extension
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---easy-retry-starters
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;   ---easy-retry-memory-starter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;   ---easy-retry-mybatis-starter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;   ---easy-retry-starter-common
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;目前支持两种模式的重试，包括持久化到mysql依赖mybatis和内存数据版本，分别需要以来easy-retry-mybatis-starter和easy-retry-memoery-starter模块。&lt;/p&gt;
&lt;p&gt;重试的最基本的interface以及model定义在easy-retry-common中，retry逻辑的具体默认实现在easy-retry-core模块中；&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;该重试的模块中定义的核心概念有：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;Retryable&lt;/code&gt;支持重试的注解，支持定义是否重新抛出异常，以及SpelExpression来驱动重试判定&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryInfo&lt;/code&gt; 通过@Retryable注解绑定获取执行的executor和executorMethod信息绑定到RetryInfo上；&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryTask&lt;/code&gt; 对于重试任务的定义，重要的领域模型。其在框架中的convert关系：retryInfo-&amp;gt;retryTask-&amp;gt;retryTaskPo&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryConfiguration&lt;/code&gt; 重试的配置，如果没有自定义的则框架默认的重试机制。支持灵活的自定义内容，包含有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;获取重试任务&lt;/li&gt;
&lt;li&gt;重试信息序列化器获取，默认是 Hessian&lt;/li&gt;
&lt;li&gt;重试机制的定义&lt;/li&gt;
&lt;li&gt;重试执行器，执行驱动业务&lt;/li&gt;
&lt;li&gt;重试最大次数&lt;/li&gt;
&lt;li&gt;重试事件监听&lt;/li&gt;
&lt;li&gt;任务结果序列化器，配合SPEL表达式决策是否需要重试，默认是 Hessian&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Retryer&lt;/code&gt; 重试的基本Call定义，@FunctionalInterface 函数式接口声明&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryContext&lt;/code&gt;，重试的上下文内容，上下文内容来自于RetryConfiguration，目前只有一种实现，即MaxAttemptsPersistenceRetryContext；绑定具体的task和task executor method&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryContainer&lt;/code&gt; 重试的容器承载，目前一种实现，即SimpleRetryContainer。其通过一个生产-消费者设计模式，实现了retryTask的生产和消费，用于对retryTask的管理；&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryContext&lt;/code&gt;和&lt;code&gt;RetryContainer&lt;/code&gt;目前都托管在RetryLifeCycle中管理，在启动和关闭时候做相关资源的处理；RetryContainer中是一个优先队列装的是RetryContext，RetryContex中承载了RetryTask，而RetryTask的优先级最终反应到RetryContext上。而任务的优先级通过任务重试的背压机制设置，避免失败的任务频繁的重试；&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryFilter&lt;/code&gt;，重试的过滤器，在过滤器中可以针对RetryContext进行相关的拦截统一处理；其中有一个确保线程安全的过滤器；&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryInterceptor&lt;/code&gt; 切面的切入，该切入点做了BeforeRetryProcess和OnRetryProcess切入动作，两个process针对正常场景和异常场景定义了相关处理方法，来决策是否需要进行重试；&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryProcessor&lt;/code&gt;，拦截面切入的动作定义&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryStrategy&lt;/code&gt;，具体的重试策略，包括等待策略以及结束策略&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryEvent&lt;/code&gt;，重试的事件，包括重试前的重试对象获取前后事件，以及重试中的失败、成功、等待事件等；&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryListener&lt;/code&gt;，事件的监听者；&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RetryExecutor&lt;/code&gt;，重试的执行器，在上下文中依赖于RetryConfiguration和RetryTask关联，确定task的执行器；当前的executor实现了PersistencRetryExecutor。其处理逻辑是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;RetryContainer从当前优先队列中获取最优先的任务对应的RetryContext上下文信息，送入executor中执行。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;executor判断当前任务是否需要立即执行还是继续等待，决定于背压模式下的时间设定。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果可以执行，则更新当前的retryTask状态为handling&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;执行器执行对应的filter逻辑，filter逻辑返回对应的信息，filter链中最后一个处理逻辑为冲RetryContext取出Invocation信息并且invoke对应的method。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;依据filter chain的返回结果后者会抛出异常，针对这两个结果进行判定，决策当前的执行是否需要重试，如果需要重试再决策是否已经达到最大重试次数或者进入背压逻辑，返回该次的结果；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;依据上述的状态结果，进行事件广播，相关的Retrylisterner即会被调用；&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/22/tZPD2LrR5ezgySf.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;源码借鉴&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;概念定义清楚，从领域建模的角度，区分开来各种概念的含义，面向对象，对象定义清楚，准确定义。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于各个Bean的AutoConfiguration，集中进行管理，且当用户无自定义时候，需要提供默认的注入实现；—这是开发框架和非框架的本质区别；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;按模块做成各个模块之间的独立，模块的边界定义清晰；&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
</item>
<item>
<title>markdown命令语法</title>
<link>https://liaolile.com/post/tools/markdown%E5%91%BD%E4%BB%A4/</link>
<pubDate>Fri, 04 Dec 2020 21:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tools/markdown%E5%91%BD%E4%BB%A4/</guid>
<description>&lt;p&gt;&lt;strong&gt;记录在此处，主要避免每次都要互联网中搜索，而是选择在本地就搜索，缩小这个知识的范围；&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;微信公众号排版工具。问题或建议，请公众号留言。&lt;strong&gt;&lt;a href="#jump_8"&gt;程序员翻身&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;建议使用 &lt;strong&gt;Chrome&lt;/strong&gt; 浏览器，体验最佳效果。&lt;/p&gt;
&lt;p&gt;使用微信公众号编辑器有一个十分头疼的问题：粘贴出来的代码，格式错乱，空间小还带行号，而且特别丑。Markdown.com.cn编辑器能够解决这个问题。&lt;/p&gt;
&lt;p&gt;Markdown是一种轻量级的「标记语言」。&lt;/p&gt;
&lt;p&gt;请阅读下方文本熟悉工具使用方法，本文可直接拷贝到微信中预览。&lt;/p&gt;
&lt;h2 id="1-markdowncomcn-简介"&gt;1 Markdown.com.cn 简介&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;支持自定义样式的 Markdown 编辑器&lt;/li&gt;
&lt;li&gt;支持微信公众号、知乎和稀土掘金&lt;/li&gt;
&lt;li&gt;点击右上方对应图标，一键复制到各平台&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="2-markdown语法教程"&gt;2 Markdown语法教程&lt;/h2&gt;
&lt;h3 id="21-标题"&gt;2.1 标题&lt;/h3&gt;
&lt;p&gt;不同数量的&lt;code&gt;#&lt;/code&gt;可以完成不同的标题，如下：&lt;/p&gt;
&lt;h1 id="一级标题"&gt;一级标题&lt;/h1&gt;
&lt;h2 id="二级标题"&gt;二级标题&lt;/h2&gt;
&lt;h3 id="三级标题"&gt;三级标题&lt;/h3&gt;
&lt;h3 id="22-字体"&gt;2.2 字体&lt;/h3&gt;
&lt;p&gt;粗体、斜体、粗体和斜体，删除线，需要在文字前后加不同的标记符号。如下：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这个是粗体&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;这个是斜体&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;这个是粗体加斜体&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;~这里想用删除线~~&lt;/p&gt;
&lt;p&gt;注：如果想给字体换颜色、字体或者居中显示，需要使用内嵌HTML来实现。&lt;/p&gt;
&lt;h3 id="23-无序列表"&gt;2.3 无序列表&lt;/h3&gt;
&lt;p&gt;无序列表的使用，在符号&lt;code&gt;-&lt;/code&gt;后加空格使用。如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;无序列表 1&lt;/li&gt;
&lt;li&gt;无序列表 2&lt;/li&gt;
&lt;li&gt;无序列表 3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果要控制列表的层级，则需要在符号&lt;code&gt;-&lt;/code&gt;前使用空格。如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;无序列表 1&lt;/li&gt;
&lt;li&gt;无序列表 2
&lt;ul&gt;
&lt;li&gt;无序列表 2.1&lt;/li&gt;
&lt;li&gt;无序列表 2.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;由于微信原因，最多支持到二级列表&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="24-有序列表"&gt;2.4 有序列表&lt;/h3&gt;
&lt;p&gt;有序列表的使用，在数字及符号&lt;code&gt;.&lt;/code&gt;后加空格后输入内容，如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;有序列表 1&lt;/li&gt;
&lt;li&gt;有序列表 2&lt;/li&gt;
&lt;li&gt;有序列表 3&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="25-引用"&gt;2.5 引用&lt;/h3&gt;
&lt;p&gt;引用的格式是在符号&lt;code&gt;&amp;gt;&lt;/code&gt;后面书写文字。如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;读一本好书，就是在和高尚的人谈话。 ——歌德&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;雇用制度对工人不利，但工人根本无力摆脱这个制度。 ——阮一峰&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="27-链接"&gt;2.7 链接&lt;/h3&gt;
&lt;p&gt;微信公众号仅支持公众号文章链接，即域名为&lt;code&gt;https://mp.weixin.qq.com/&lt;/code&gt;的合法链接。使用方法如下所示：&lt;/p&gt;
&lt;p&gt;对于该论述，欢迎读者查阅之前发过的文章，&lt;a href="https://mp.weixin.qq.com/s/s5IhxV2ooX3JN_X416nidA" target="_blank" rel="noopener"&gt;你是《未来世界的幸存者》么？&lt;/a&gt;
&lt;a id="jump_8"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="28-图片"&gt;2.8 图片&lt;/h3&gt;
&lt;p&gt;插入图片，格式如下：&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://www.nginx.cn/wp-content/uploads/2020/03/qrcode_for_gh_82cf87d482f0_258.jpg" alt="这里写图片描述" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;支持 jpg、png、gif、svg 等图片格式，&lt;strong&gt;其中 svg 文件仅可在微信公众平台中使用&lt;/strong&gt;，svg 文件示例如下：&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://markdown.com.cn/images/i-am-svg.svg" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;支持图片&lt;strong&gt;拖拽和截图粘贴&lt;/strong&gt;到编辑器中。&lt;/p&gt;
&lt;p&gt;注：支持图片 &lt;em&gt;&lt;strong&gt;拖拽和截图粘贴&lt;/strong&gt;&lt;/em&gt; 到编辑器中，仅支持 https 的图片，图片粘贴到微信时会自动上传微信服务器。&lt;/p&gt;
&lt;h3 id="29-分割线"&gt;2.9 分割线&lt;/h3&gt;
&lt;p&gt;可以在一行中用三个以上的减号来建立一个分隔线，同时需要在分隔线的上面空一行。如下：&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="210-表格"&gt;2.10 表格&lt;/h3&gt;
&lt;p&gt;可以使用冒号来定义表格的对齐方式，如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align:left"&gt;姓名&lt;/th&gt;
&lt;th style="text-align:center"&gt;年龄&lt;/th&gt;
&lt;th style="text-align:right"&gt;工作&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:left"&gt;小可爱&lt;/td&gt;
&lt;td style="text-align:center"&gt;18&lt;/td&gt;
&lt;td style="text-align:right"&gt;吃可爱多&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left"&gt;小小勇敢&lt;/td&gt;
&lt;td style="text-align:center"&gt;20&lt;/td&gt;
&lt;td style="text-align:right"&gt;爬棵勇敢树&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:left"&gt;小小小机智&lt;/td&gt;
&lt;td style="text-align:center"&gt;22&lt;/td&gt;
&lt;td style="text-align:right"&gt;看一本机智书&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="3-特殊语法"&gt;3. 特殊语法&lt;/h2&gt;
&lt;h3 id="31-脚注"&gt;3.1 脚注&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;支持平台：微信公众号、知乎。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;脚注与链接的区别如下所示：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;链接：[文字](链接)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;脚注：[文字](脚注解释 &amp;#34;脚注名字&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;有人认为在&lt;a href="https://en.wikipedia.org/wiki/Front-end_web_development" title="Front-end web development" target="_blank" rel="noopener"&gt;大前端时代&lt;/a&gt;的背景下，移动端开发（Android、IOS）将逐步退出历史舞台。&lt;/p&gt;
&lt;p&gt;&lt;a href="%e6%98%af%e6%8c%87%e6%8e%8c%e6%8f%a1%e5%a4%9a%e7%a7%8d%e6%8a%80%e8%83%bd%ef%bc%8c%e5%b9%b6%e8%83%bd%e5%88%a9%e7%94%a8%e5%a4%9a%e7%a7%8d%e6%8a%80%e8%83%bd%e7%8b%ac%e7%ab%8b%e5%ae%8c%e6%88%90%e4%ba%a7%e5%93%81%e7%9a%84%e4%ba%ba%e3%80%82" title="什么是全栈工程师"&gt;全栈工程师&lt;/a&gt;在业务开发流程中起到了至关重要的作用。&lt;/p&gt;
&lt;p&gt;脚注内容请拉到最下面观看。&lt;/p&gt;
&lt;h3 id="32-代码块"&gt;3.2 代码块&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;支持平台：微信代码主题仅支持微信公众号！其他主题无限制。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如果在一个行内需要引用代码，只要用反引号引起来就好，如下：&lt;/p&gt;
&lt;p&gt;Use the &lt;code&gt;printf()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;在需要高亮的代码块的前一行及后一行使用三个反引号，同时&lt;strong&gt;第一行反引号后面表示代码块所使用的语言&lt;/strong&gt;，如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// FileName: HelloWorld.java
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloWorld&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="c1"&gt;// Java 入口程序，程序从此入口
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello,World!&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 向控制台打印一条语句
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;支持以下语言种类：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clojure，cpp，cs，css
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dart，dockerfile, diff
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;erlang
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go，gradle，groovy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;haskell
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;java，javascript，json，julia
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kotlin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lisp，lua
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;makefile，markdown，matlab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;objectivec
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;perl，php，python
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;r，ruby，rust
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scala，shell，sql，swift
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tex，typescript
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;verilog，vhdl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果想要更换代码高亮样式，可在上方&lt;strong&gt;代码主题&lt;/strong&gt;中挑选。&lt;/p&gt;
&lt;p&gt;其中&lt;strong&gt;微信代码主题与微信官方一致&lt;/strong&gt;，有以下注意事项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;带行号且不换行，代码大小与官方一致&lt;/li&gt;
&lt;li&gt;需要在代码块处标志语言，否则无法高亮&lt;/li&gt;
&lt;li&gt;粘贴到公众号后，用鼠标点代码块内外一次，完成高亮&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;diff 不能同时和其他语言的高亮同时显示，且需要调整代码主题为微信代码主题以外的代码主题才能看到 diff 效果，使用效果如下:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ 新增项
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;&lt;/span&gt;&lt;span class="gd"&gt;- 删除项
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;其他主题不带行号，可自定义是否换行，代码大小与当前编辑器一致&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="33-数学公式"&gt;3.3 数学公式&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;支持平台：微信公众号、知乎。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;行内公式使用方法，比如这个化学公式：$\ce{Hg^2+ -&amp;gt;[I-] HgI2 -&amp;gt;[I-] [Hg^{II}I4]^2-}$&lt;/p&gt;
&lt;p&gt;块公式使用方法如下：&lt;/p&gt;
&lt;p&gt;$$H(D_2) = -\left(\frac{2}{4}\log_2 \frac{2}{4} + \frac{2}{4}\log_2 \frac{2}{4}\right) = 1$$&lt;/p&gt;
&lt;p&gt;矩阵：&lt;/p&gt;
&lt;p&gt;$$
\begin{pmatrix}
1 &amp;amp; a_1 &amp;amp; a_1^2 &amp;amp; \cdots &amp;amp; a_1^n \
1 &amp;amp; a_2 &amp;amp; a_2^2 &amp;amp; \cdots &amp;amp; a_2^n \
\vdots &amp;amp; \vdots &amp;amp; \vdots &amp;amp; \ddots &amp;amp; \vdots \
1 &amp;amp; a_m &amp;amp; a_m^2 &amp;amp; \cdots &amp;amp; a_m^n \
\end{pmatrix}
$$&lt;/p&gt;
&lt;p&gt;公式由于微信不支持，目前的解决方案是转成 svg 放到微信中，无需调整，矢量不失真。&lt;/p&gt;
&lt;p&gt;目前测试如果公式量过大，在 Chrome 下会存在粘贴后无响应，但是在 Firefox 中始终能够成功。&lt;/p&gt;
&lt;h3 id="34-toc"&gt;3.4 TOC&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;支持平台：微信公众号、知乎。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;TOC 全称为 Table of Content，列出全部标题。&lt;/p&gt;
&lt;p&gt;[TOC]&lt;/p&gt;
&lt;p&gt;由于微信只支持到二级列表，本工具仅支持二级标题和三级标题的显示。&lt;/p&gt;
&lt;h3 id="35-注音符号"&gt;3.5 注音符号&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;支持平台：微信公众号。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;支持注音符号，用法如下：&lt;/p&gt;
&lt;p&gt;Markdown Nice 这么好用，简直是{喜大普奔|hē hē hē hē}呀！&lt;/p&gt;
&lt;h3 id="36-横屏滑动幻灯片"&gt;3.6 横屏滑动幻灯片&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;支持平台：微信公众号。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;通过&lt;code&gt;&amp;lt;![](url),![](url)&amp;gt;&lt;/code&gt;这种语法设置横屏滑动滑动片，具体用法如下：&lt;/p&gt;
&lt;p&gt;&amp;lt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://markdown.com.cn/images/blue.jpg" alt="蓝1" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
,















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://markdown.com.cn/images/green.jpg" alt="绿2" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
,















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://markdown.com.cn.jpg" alt="红3" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&amp;gt;&lt;/p&gt;
&lt;h2 id="4-其他语法"&gt;4 其他语法&lt;/h2&gt;
&lt;h3 id="41-html"&gt;4.1 HTML&lt;/h3&gt;
&lt;p&gt;支持原生 HTML 语法，请写内联样式，如下：&lt;/p&gt;
&lt;p&gt;&lt;span style="display:block;text-align:right;color:orangered;"&gt;橙色居右&lt;/span&gt;
&lt;span style="display:block;text-align:center;color:orangered;"&gt;橙色居中&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="42-uml"&gt;4.2 UML&lt;/h3&gt;
&lt;p&gt;不支持，推荐使用开源工具&lt;code&gt;https://draw.io/&lt;/code&gt;制作后再导入图片&lt;/p&gt;
&lt;h2 id="5-致谢"&gt;5 致谢&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;歌词经理 &lt;a href="https://github.com/lyricat/wechat-format" title="灵感来源" target="_blank" rel="noopener"&gt;wechat-fromat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;颜家大少 &lt;a href="http://md.aclickall.com/" title="MdA2All" target="_blank" rel="noopener"&gt;MD2All&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="10"&gt;&lt;/h3&gt;
&lt;p&gt;REF:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://markdown.com.cn/basic-syntax/" target="_blank" rel="noopener"&gt;Markdown 基本语法 | Markdown 官方教程&lt;/a&gt;&lt;/p&gt;
</description>
</item>
<item>
<title>markdown工具绘图</title>
<link>https://liaolile.com/post/tools/markdown%E7%BB%98%E5%9B%BE/</link>
<pubDate>Fri, 04 Dec 2020 21:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tools/markdown%E7%BB%98%E5%9B%BE/</guid>
<description>&lt;p&gt;[toc]&lt;/p&gt;
&lt;p&gt;千言万语不如一张图 &lt;code&gt;Express yourself by Pic&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;给你一座灯塔，给你一个希望&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/03/7qibJsPXy9ZdaW3.png" alt="image-20220603155904263" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Markdown可以绘制各种不同的图，依赖于&lt;code&gt;mermaid&lt;/code&gt; 引擎&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;h4 id="flowchart"&gt;Flowchart&lt;/h4&gt;
&lt;p&gt;Flowchart 都由&lt;strong&gt;节点&lt;/strong&gt;、几何形状和&lt;strong&gt;边缘&lt;/strong&gt;、箭头或线条组成。mermaid代码定义了这些&lt;strong&gt;节点&lt;/strong&gt;和&lt;strong&gt;边&lt;/strong&gt;的制作和交互方式&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;可能的flowchart 方向是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TB - 从上到下&lt;/li&gt;
&lt;li&gt;TD - 自上而下/与自上而下相同&lt;/li&gt;
&lt;li&gt;BT - 自下而上&lt;/li&gt;
&lt;li&gt;RL - 从右到左&lt;/li&gt;
&lt;li&gt;LR——从左到右&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;实例：&lt;/p&gt;
&lt;div class="mermaid"&gt;flowchart  LR  
	id1([start]) --&gt; id2[需求基线确定] --&gt; id3[内部需求变更]--&gt;id4{是否对实际业务产生影响}
	id4--&gt;|no|id5{是否接受当前版本变更} --&gt;|no|id6[下一个版本]
	id4--&gt;|yes|id7[与客户协商需求变更]--&gt;id8[客户需求变更流程]
	id5--&gt;|yes|id9[更新需求文档]--&gt;id10[通知项目组开发测试]--&gt;id11([需求变更备案])
&lt;/div&gt;
&lt;h4 id="sequence"&gt;Sequence&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;-&amp;raquo; 代表实线箭头，&amp;ndash;&amp;raquo; 则代表虚线箭头&lt;/li&gt;
&lt;li&gt;-&amp;gt;直线，&amp;ndash;&amp;gt;虚线&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="mermaid"&gt;sequenceDiagram
李雷 -&gt; 韩梅梅: Hello 梅梅, How are you?
Note right of 韩梅梅: 韩梅梅心想
韩梅梅 --&gt; 李雷: I'm fine, thanks, and you?
&lt;/div&gt;
&lt;h4 id="gantt"&gt;Gantt&lt;/h4&gt;
&lt;div class="mermaid"&gt;gantt
        dateFormat  YYYY-MM-DD
        title 快乐的生活
        section 吃一把鸡就学习
        学习            :done,    des1, 2014-01-06,2014-01-09
        疯狂学习               :active,  des2, 2014-01-09, 3d
        继续疯狂学习               :         des3, after des2, 5d
        吃鸡！               :         des4, after des3, 4d
        section 具体内容
        学习Python :crit, done, 2014-01-06,72h
        学习C++          :crit, done, after des1, 2d
        学习Lisp             :crit, active, 3d
        学习图形学        :crit, 4d
        跳伞           :2d
        打枪                      :2d
&lt;/div&gt;
&lt;h4 id="classdiagram"&gt;ClassDiagram&lt;/h4&gt;
&lt;div class="mermaid"&gt;
classDiagram

  Class01 &lt;|-- AveryLongClass: Cool
  &lt;&lt;interface&gt;&gt; Class01
  Class09--&gt;C2: Where am i?
  Class09 --* C3
  Class09 --|&gt; Class07
  Class07: equals()
  Class07: Object[] elementData
  Class01: size()
  Class01: int chimp
  Class01: int gorilla
  class Class10 {
  &lt;&lt;service&gt;&gt;
  int id
  size()
 }
&lt;/div&gt;
&lt;h4 id="statediagram"&gt;StateDiagram&lt;/h4&gt;
&lt;div class="mermaid"&gt;stateDiagram

  [*]--&gt;Active
  state Active {
    [*]--&gt;NumLockOff
    NumLockOff--&gt;NumLockOn : EvNumLockPressed
    NumLockOn--&gt;NumLockOff : EvNumLockPressed
    --
    [*]--&gt;CapsLockOff
    CapsLockOff--&gt;CapsLockOn : EvCapsLockPressed
    CapsLockOn--&gt;CapsLockOff : EvCapsLockPressed
    --
    [*]--&gt;ScrollLockOff
    ScrollLockOff--&gt;ScrollLockOn : EvCapsLockPressed
    ScrollLockOn--&gt;ScrollLockOff : EvCapsLockPressed
       }
&lt;/div&gt;
&lt;h4 id="erdiagram"&gt;ErDiagram&lt;/h4&gt;
&lt;div class="mermaid"&gt;erDiagram
  CUSTOMER ||--o{ORDER : places
  ORDER ||--|{LINE-ITEM : contains
  CUSTOMER}|..|{DELIVERY-ADDRESS : uses
&lt;/div&gt;
&lt;h4 id="gitgraph"&gt;GitGraph&lt;/h4&gt;
&lt;div class="mermaid"&gt;gitGraph:
options
{
"nodeSpacing": 150,
"nodeRadius": 15
}
end
commit
branch lelandBranch
checkout lelandBranch
commit
commit
checkout master
commit
commit
commit
merge lelandBranch
&lt;/div&gt;
&lt;h4 id="pie"&gt;Pie&lt;/h4&gt;
&lt;div class="mermaid"&gt;pie

title Key elements in Product X
"Calcium" : 42.96
"Potassium" : 50.05
"Magnesium" : 10.01
"Iron" : 5
&lt;/div&gt;
&lt;h4 id="journey"&gt;Journey&lt;/h4&gt;
&lt;p&gt;展示了不同用户要做的步骤信息，可以展示当前的工作流&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Task name: &lt;score&gt;: &lt;comma separated list of actors&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="mermaid"&gt;journey

title My working day
    section Go to work
        Make tea: 5: Me
        Go upstairs: 3: Me
        Do work: 1 : Me, Cat

    section Go home
        Go downstairs: 5: Me
        Sit down: 3: Me
&lt;/div&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://blog.csdn.net/qq_36075612/article/details/118161100?spm=1001.2101.3001.6661.1&amp;amp;utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~default-1-118161100-blog-121381426.pc_relevant_scanpaymentv1&amp;amp;depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~default-1-118161100-blog-121381426.pc_relevant_scanpaymentv1&amp;amp;utm_relevant_index=1" target="_blank" rel="noopener"&gt;使用Typora画 流程图、时序图、顺序图、甘特图、等图详解_Ch_champion的博客-CSDN博客_typora 时序图&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://blog.csdn.net/acktomas/article/details/124644100" target="_blank" rel="noopener"&gt;mermaid流程图语法教程_acktomas的博客-CSDN博客_mermaid 流程图&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>测试的概念</title>
<link>https://liaolile.com/post/tech/test/%E6%B5%8B%E8%AF%95%E7%9A%84%E6%A6%82%E5%BF%B5/</link>
<pubDate>Fri, 04 Dec 2020 21:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/test/%E6%B5%8B%E8%AF%95%E7%9A%84%E6%A6%82%E5%BF%B5/</guid>
<description>&lt;p&gt;&lt;code&gt;Test Double&lt;/code&gt; [^1]is a generic term for any case where you replace a production object for testing purposes.&lt;/p&gt;
&lt;p&gt;我们使用&lt;code&gt;Test Double&lt;/code&gt;替代真实的依赖组件去和待测系统进行交互，&lt;code&gt;Test Double&lt;/code&gt;不必和真实的依赖组件的实现一模一样，比如不用去实现依赖组件复杂的内部逻辑等，我们只需要在满足测试需求范围内，确保对于待测系统来说&lt;code&gt;Test Double&lt;/code&gt;提供的API是和依赖组件提供的一样的，API是怎么实现的在这个上下文就显得不重要了。多用于自动化测试比如单元测试和集成测试。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Test Stub, you can define answers to me, I will respond the same&lt;/p&gt;
&lt;p&gt;Stubs会按照我们设计的输出与待测系统进行交互， 这个桩既不会与测试用例(代码)交互，也不会在待测系统内部进行验证。&lt;code&gt;Test Stub&lt;/code&gt;常用于响应待测系统的请求，然后返回特定的值。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hard Coded Test Stub&lt;/li&gt;
&lt;li&gt;Configurable Test Stub&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;UserCase：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;依赖组件无法使用，影响测试结果&lt;/li&gt;
&lt;li&gt;依赖组件响应太慢，影响测试速度&lt;/li&gt;
&lt;li&gt;成为响应者，需要给系统注入特定的数据，从而影响被测试系统&lt;/li&gt;
&lt;li&gt;成为破坏者，需要给系统注入无效的数据，从而对系统产生异常响应&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mock Object，you can set expectation on me and pre-programmed with expectations which form a specification of the calls they are expected to receive.&lt;/p&gt;
&lt;p&gt;Mocks是一个完全代替待测系统的组件，并且应用于验证待测系统输出的对象。这个对象接受待测系统的输入，同时返回输出给到待测系统，然后进行验证。其一个重要特点是可以对无法在待测系统上直接被观察到的行为或输出进行验证。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fake Object，you can have me with limited capabilities and working implements, but usually take some shortcut and have simplified version of production code, make it not suit for production (InMemeoryTestDatabase for example)&lt;/p&gt;
&lt;p&gt;Fakes是指一个轻量级的完全代替待测系统依赖组件的对象，采用更加简洁的方法实现组件的功能。轻量级是指仅仅提供和依赖组件一样的功能接口保证待测系统正常工作，不需要具有真实依赖组件的很多特性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test Spy，are stubs, monitor real ones，you can change my behavior. Record some information based on how they called.&lt;/p&gt;
&lt;p&gt;Spies是指一个待测系统依赖组件的替身，并且捕捉和保存待测试对象对依赖系统的输出，这个输出是会用于测试代码中的验证。主要用于记录和验证待测试对象对依赖系统的输出。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dummy Object，pass around but never actually used，usually used to fill parameter lists&lt;/p&gt;
&lt;p&gt;Dummies是指为了调用被测试方法而传入的假参数，实际上传入的参数不会对测试有任何作用，仅仅是为了成功调用被测试方法，又被称为Placeholder。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;REF&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;[^1]： &lt;a href="https://martinfowler.com/bliki/TestDouble.html" target="_blank" rel="noopener"&gt;TestDouble (martinfowler.com)&lt;/a&gt;&lt;/p&gt;
</description>
</item>
<item>
<title>高效率系统办公</title>
<link>https://liaolile.com/post/tools/%E9%AB%98%E6%95%88%E7%8E%87%E5%8D%8F%E5%90%8C%E5%8A%9E%E5%85%AC/</link>
<pubDate>Fri, 04 Dec 2020 21:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tools/%E9%AB%98%E6%95%88%E7%8E%87%E5%8D%8F%E5%90%8C%E5%8A%9E%E5%85%AC/</guid>
<description>&lt;p&gt;在Windows下工作的效率问题，对于公司和家里都有物理PC机器，也有笔记本，希望在某些时候笔记本具有移动特性的也能够方便的获取到对应应用和数据；在这块的切换，由于各个电脑上安装的内容均不同，且有所变化，导致存在切换的时候要找到的东西内容比较少；&lt;/p&gt;
&lt;p&gt;当前的系统使用的是win10，对于远程桌面这种只能说体验很差，毕竟是两个隔离的环境，而目的是两个环境的一致；同时由于公司是内网，家里是外网，也就是有4台机器数据涉及同步；&lt;/p&gt;
&lt;p&gt;不同的环境保持相同的操作习惯，对于效率的提升无非是有益的。PC和笔记本是瘦客户端，而仅仅是账号、配置等的管理；&lt;/p&gt;
&lt;p&gt;主要的矛盾：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个机器上的应用不同；&lt;/li&gt;
&lt;li&gt;每个机器上对应的数据也不同；&lt;/li&gt;
&lt;li&gt;缺少自动化的手段维持一致性；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要解决的问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;实现应用（版本）和数据的一致性，包括安装路径、数据文件路径等、定义规范；&lt;/li&gt;
&lt;li&gt;应用的配置（比如ssl证书等）和安装自动化；&lt;/li&gt;
&lt;li&gt;在自动化手段不够的时候，能够迅速的通过指引找到维持一致性；&lt;/li&gt;
&lt;li&gt;各个&lt;strong&gt;环境账号密码的统一管理&lt;/strong&gt;，不要每个环境都输入密码，以及验证码统一手机；&lt;/li&gt;
&lt;li&gt;在某些场景下找到第三方，实现数据的直接访问，而不需要在多个设备上同步；&lt;/li&gt;
&lt;li&gt;能够快速恢复想要的环境，环境可以在新机上一键拉起；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;场景化：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;办公，办公主要是设计文档、代码调测等需要，以及公司ilearning资源的学习；&lt;/li&gt;
&lt;li&gt;日常，主要是写作博客，积累日常生活中最本质的一些内容；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;公共&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;git，主要用于实现代码和数据的同步能力，在公司依赖codehub，在家依赖gitee；这个都是小数据量的场景；
&lt;ul&gt;
&lt;li&gt;私仓管理，对于个人数据的备份；&lt;/li&gt;
&lt;li&gt;云端管理，对于应用的部署、代码的管理，同时能够往第三方私仓备份；&lt;/li&gt;
&lt;li&gt;备份管理遵循：云服务-&amp;gt;本地备份-&amp;gt;云端备份（自动化，集中化）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;浏览器，Edge数据；&lt;/li&gt;
&lt;li&gt;写作，Typora，基于Markdown的写作；
&lt;ul&gt;
&lt;li&gt;PicGo&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;效率工具utools，everything，beyondCompare&lt;/li&gt;
&lt;li&gt;Idea系列
&lt;ul&gt;
&lt;li&gt;maven/jdk/go-sdk&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;截图软件，snipaste&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;办公&lt;/strong&gt;（更多的是公司）&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数据库连接，navicat&lt;/li&gt;
&lt;li&gt;远程连接，xshell和tabby，xshell主要是现网问题登录问题，tabby主要是日常命令行工具&lt;/li&gt;
&lt;li&gt;onebox，大文件备份同步（关于应用软件，同一版本）&lt;/li&gt;
&lt;li&gt;wenote，云笔记&lt;/li&gt;
&lt;li&gt;Edraw，绘图工具；&lt;/li&gt;
&lt;li&gt;关于测试工具；关于文本工具；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;日常&lt;/strong&gt;（更多的是家庭）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;翻墙Latern，用于github经常访问失败的问题；&lt;/li&gt;
&lt;li&gt;weizhiNote，云笔记；&lt;/li&gt;
&lt;li&gt;本地命令行工具，tabby，通过这个使一切自动化；&lt;/li&gt;
&lt;li&gt;坚果云平台&lt;/li&gt;
&lt;li&gt;fastgithub_win-x64，快速访问github的能力&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关于手动数据的合并，怎么通过git管理其差异；比如Edge的书签内容，如何定时的自动化同步；&lt;/p&gt;
&lt;p&gt;本地文件夹设计&lt;/p&gt;
&lt;p&gt;原则：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数字前缀，多个单词间下划线分割，全小写；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;p&gt;0_leland  个人重要的数据文件，需要往第三方定时备份的内容（非大文件）；&lt;/p&gt;
&lt;p&gt;1_config  应用的配置以及环境的配置；&lt;/p&gt;
&lt;p&gt;99_backup 云端重要内容，需要往云服务器定时拉取到本地，然后定时备份到第三方的内容；&lt;/p&gt;
&lt;p&gt;apps 应用程序&lt;/p&gt;
&lt;p&gt;software 应用程序安装位置；&lt;/p&gt;
&lt;p&gt;download 所有下载文件的路径；&lt;/p&gt;
&lt;p&gt;Ref:&lt;/p&gt;
</description>
</item>
<item>
<title>分布式系统中的概念</title>
<link>https://liaolile.com/post/tech/distributesystem/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E4%B8%AD%E6%A6%82%E5%BF%B5/</link>
<pubDate>Sat, 18 Jul 2020 13:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/distributesystem/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E4%B8%AD%E6%A6%82%E5%BF%B5/</guid>
<description>&lt;p&gt;[toc]&lt;/p&gt;
&lt;p&gt;分布式技术理论涉及范围广，包括系统开发、架构设计、网络通信等，本篇聚焦介绍在分布式系统中大家需要理解的一些概念。&lt;/p&gt;
&lt;p&gt;该篇文章会持续的更新，以期覆盖更全的内容概念。&lt;/p&gt;
&lt;h4 id="1系统开发"&gt;1、系统开发&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;高内聚/低耦合&lt;/p&gt;
&lt;p&gt;软件模块是由相关性强的代码组成，软件模块需要做到内聚，反映的是模块内部联系紧密。模块应该是单一责任原则，各个模块之间独立。同时模块间要低耦合，这取决于模块间接口定义的复杂性、调用的方式以及传递的消息。模块高内聚后，往往模块间也会是低耦合。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;过度设计&lt;/p&gt;
&lt;p&gt;过多的面向未来的设计(把简单的事情想复杂了)，过度追求模块化、可扩展性、设计模式等而引入了系统的复杂性；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;过早优化&lt;/p&gt;
&lt;p&gt;开发过程的早期，未来需求的变化走向未清洗的时候，优化导致新的需求无法很好实现，而且优化的预期可能是错的，而简介把代码弄得复杂。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;重构&lt;/p&gt;
&lt;p&gt;通过调整代码改善软件的质量、性能，使程序的设计模式和架构更加合理，软件的可扩展性和维护性也得到提高。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;破窗效应&lt;/p&gt;
&lt;p&gt;系统代码或者架构设计的隐患存在的时候，那这个隐患在将来的时候已经会出现，同时随着事件的推移隐患会越越重，因此需要尽早的消除当前的隐患.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;零信任原则&lt;/p&gt;
&lt;p&gt;程序运行的上下游整个链路中，任何一个节点不能保证绝对可靠，任何一个点都可能随时发生故障或者不可预期的行为。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;持久化&lt;/p&gt;
&lt;p&gt;程序对于由状态的数据需要进行存储，也就是临时状态和持久状态间的转化，比如内存的中的数据持久化到磁盘。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;临界区&lt;/p&gt;
&lt;p&gt;表示一种公共资源或者共享数据，可以被多个线程或进程使用，但是每次只能允许其中一个使用。临界资源一但被占用，其他的使用者就需要等待。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;阻塞/非阻塞&lt;/p&gt;
&lt;p&gt;临界区资源的等待就是阻塞。如果占用资源的线程一直不释放资源，那么所有阻塞在临界区上的线程都不能工作。而非阻塞即允许多个线程同时进入临界区。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同步/异步&lt;/p&gt;
&lt;p&gt;具体指应用对于请求的处理，同步时在收到请求/调用时候在没有得到结果之前，就不会返回结果。而异步调用会瞬间返回，但是异步返回的内容并不代表任务处理完成了，往往需要回调或者其他方式在任务完成后通知调用防。如WebFlux框架支持的异步；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;并发/并行&lt;/p&gt;
&lt;p&gt;并行是指同一时刻，由多条指令在多个处理器上同时执行；无论宏观和微观都是一起执行；并发是指同一时刻只有一条指令执行，但多个进程指令被快速的轮转执行，在时间上分成若干段，多个进程快速交替执行；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="2架构设计"&gt;2、架构设计&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;高并发&lt;/p&gt;
&lt;p&gt;通过设计保证系统能够同时并行处理很多请求。也就是同时间点，很多用户同时访问系统的能力。常用的指标如TPS/QPS来衡量。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;高可用&lt;/p&gt;
&lt;p&gt;经过设计能够达到系统停工时间的减少，确保系统在任何时候都能够正常的对外提供服务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;读写分离&lt;/p&gt;
&lt;p&gt;往往是为了确保如数据库产品的稳定性，往往把系统做拆分，其中某个节点提供增删改的业务，其他的节点主要提供读的操作；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;冷备/热备&lt;/p&gt;
&lt;p&gt;冷备为一台运行，另一台不运行作为备份，应对其中一台宕机后使用。冷备需要主动切换服务。而热备是active/standby，当active服务出现故障，通过检测手段发现后激活standby，确保短时间内服务完全恢复正常使用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;异地多活&lt;/p&gt;
&lt;p&gt;不同城市建设独立的数据中心，如三地二中心的容灾模式。活是相对于冷备份而言，冷备份是全量数据备份，平时不支撑业务需求，只在主机房出现故障的时候才切换到备用机房。多活是指这些机房在日常的业务中也需要走流量做业务支撑。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;负载均衡&lt;/p&gt;
&lt;p&gt;使用堕胎服务器进行流量分发的负载均衡服务。可以在多个实例间分配应用程序的对外服务能力，消除单点故障。实现应用程序的更高的容错能力。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;动静分离&lt;/p&gt;
&lt;p&gt;web服务器架构中，静态页面和动态页面，静态内容接口和动态内容接口分开不同系统访问的架构设计方法，进而提升整个服务访问性能和可维护性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;集群&lt;/p&gt;
&lt;p&gt;单台服务器对于并发的承载有限，通过横向扩容，突破单台服务器的瓶颈，将堕胎服务器组合起来提供服务，即为集群服务，可以成倍的提升整个系统的并发处理能力。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分布式&lt;/p&gt;
&lt;p&gt;一个完整的系统拆分成多个独立的子系统，每个子系统称为服务，分布式系统将请求分发到不同的子系统，让不同的服务来处理不同的请求。分布式系统中，子系统独立的运行，通过网络通信连接起来实现数据互通和组合服务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CAP理论&lt;/p&gt;
&lt;p&gt;在分布式系统中，Consistency、Availability、Partition Tolerance不能同时成立。一致性要求同一时刻点，分布式系统的所有的数据备份都相同或处于同一状态；可用性要求系统集群一部分节点宕机后，系统依然能够正确的响应用户的请求。分区容错性是需要系统能够容忍节点之间网络通信的故障。由于分布式系统分区是存在的，往往在一致性和可用性之间做出选择；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;BASE理论&lt;/p&gt;
&lt;p&gt;Basically Available/Soft State/Eventually consisitence，对于CAP理论的扩充，对一致性和可用性进行权衡的结果。我们无法做到强一致，但每个应用都可以根据自身的业务特点，采用适当的方式使系统达到最终一致性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;水平扩展/垂直扩展/Z轴扩展&lt;/p&gt;
&lt;p&gt;水平扩展就是scale out更多的实例来分散负载，提升存储能力和计算能力。垂直扩展scale up通过提升单机硬件性能或者软件/架构性能来达到；Z轴扩展时依据sharding对于数据进行分片，让其路由到对应的sharding上进行数据的获取。或者说时Cell架构的扩容；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;平行扩容&lt;/p&gt;
&lt;p&gt;类似水平扩展，集群服务器中的节点均为平行对等节点，一般来说关键路径（登录，关键业务逻辑等）都需要支持运行时动态平行扩容。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;弹性扩容&lt;/p&gt;
&lt;p&gt;对部署的集群进行动态在线扩容，根据实际业务环境按照一定策略自动的添加更多的节点（包括存储节点、计算节点、网络节点）来增加系统容量、提高系统性能和可靠性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="3网络通信"&gt;3、网络通信&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;连接池&lt;/p&gt;
&lt;p&gt;预先建立连接缓冲池，并提供一套连接使用、分配、管理策略，使得该连接池中的连接可以得到高效、安全的服用，避免频繁建立和关闭连接的开销。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;断线重连&lt;/p&gt;
&lt;p&gt;由于网络波动造成用户间接性断开与服务器的连接，待网络恢复之后服务器尝试将用户连接到上次断开时的状态和数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;会话保持&lt;/p&gt;
&lt;p&gt;识别客户端和服务端之间交互过程的关联性，在做负载均衡的同时保证相关联的访问都会分配到一台机器上，即一次会话过程中发起的多个请求都会落到同一台机器上。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;长连接/短连接&lt;/p&gt;
&lt;p&gt;均值TCP连接，长连接就是建立TCP连接后，一直保持这个连接，在此期间通过发送心跳来确认双方的存在，中间会做多次业务数据传输，一般不会主动断开连接。短连接一般就指连接建立后，执行一次事务后，然后关掉这个连接。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;流量控制/拥塞控制&lt;/p&gt;
&lt;p&gt;流量控制为了防止发送方太快，而接收方因为资源受限处理不了；拥塞控制是避免网络来不及处理而产生拥塞，进而引起整个网络性能下降的现象；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;惊群效应&lt;/p&gt;
&lt;p&gt;多进程在同时阻塞等待同一个事件的时候，如果等待的这个事件发生，他们他就会唤醒等待的所有进程。但是最终只有一个进程获得这个时间的控制权。对于没有获取到控制权的进程只能重新进入休眠状态，这种现象和性能浪费就叫做惊群。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NAT&lt;/p&gt;
&lt;p&gt;网络地址转换，替换IP报文头部的地址信息。NAT通常部署在网络出口位置，通过内部IP地址替换为出口IP地址提供公网可达性和上层协议的连接能力。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="4故障异常"&gt;4、故障异常&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;宕机&lt;/p&gt;
&lt;p&gt;计算机出现意外故障而死机，对应的服务不能对外提供。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;coredump&lt;/p&gt;
&lt;p&gt;程序出现异常而中断的时，OS会把程序的当前工作状态存储为一个coredump文件，通常情况下，该文件包含了程序运行时的内存、寄存器状态、堆栈指针，内存管理信息等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缓存穿透/击穿/雪崩&lt;/p&gt;
&lt;p&gt;穿透指查询一个一定不存在的数据，而导致流量积压到数据库上上旬；击穿指某个热点key过期时候，而这个时候大量该key的并发请求而导致流量也聚集到数据库上；雪崩指缓存中大批量到过期时间，而查询数据量大导致数据库压力过大的情况；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;内存溢出/内存泄漏&lt;/p&gt;
&lt;p&gt;内存溢出指程序申请内存时，没有足够的内存供申请者使用，此时回报OOM的失败；内存泄露指的时动态分配的堆内存由于某种原因程序未释放或无法释放，造成系统内存的浪费，导致程序运行速度减慢甚至崩溃。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;句柄泄露&lt;/p&gt;
&lt;p&gt;进程在调用系统文件后，没有释放已经发开的文件句柄。操作系统的交互是通过获取文件句柄来实现的，一般泄露后，机器变慢，CPU飙升；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;死锁&lt;/p&gt;
&lt;p&gt;两个或两个以上的线程执行过程中，由于竞争资源或者彼此通信而造成阻塞的现网。互相等待对方的资源。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;软中断/硬中断&lt;/p&gt;
&lt;p&gt;一般中断即指硬中断，主要用来通知操作系统系统外设状态的变化。软中断是硬中断服务程序对内核的中断，为了满足实时系统的要求，中断处理应该是越快越好。在发生中断时候，硬中断处理那些短时间就可以完成的工作，而将那些处理时间比较长的工作，当道中断之后来完成，也就是软中断来完成。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;毛刺&lt;/p&gt;
&lt;p&gt;短暂某一时刻，服务器性能的指标比如IO/CPU远大于该时刻前后时间段。毛刺的出现代表服务器资源利用不均匀，不充分容易诱发其他更严重的问题。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;重放攻击&lt;/p&gt;
&lt;p&gt;攻击者发送一个目的主机已经接受过的包，来达到欺骗系统的目的，主要用于身份认证过程，破坏认证的正确性。该攻击下会不断恶意或欺诈性的重复一个有效的数据传输，可以由攻击发起者也可以由拦截并重发该数据的敌方进行。攻击者利用网络监听或者其他方式获取的凭证，之后再把它重新发给认证服务器。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;网络孤岛&lt;/p&gt;
&lt;p&gt;网络孤岛是指分布式系统中，部分机器与整个集群失去网络连接，而分裂为一个小集群而且发生数据不一致的状况；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;数据倾斜&lt;/p&gt;
&lt;p&gt;对于集群系统，数据的分布也是分布式的，即不同的节点负责一定范围的数据。由于数据分散度不够，导致大量的数据集中到了一台或者几台服务节点上，称为数据倾斜，一般来说数据倾斜是由于负载均衡实时效果不好引起的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;脑裂&lt;/p&gt;
&lt;p&gt;集群系统中，部分节点之间网络不可达而引起的系统分裂，不同分裂的小集群会按照各自的状态提供服务，原本集群会同时存在不一致的反应，造成节点间互相争抢资源、系统混乱、数据损坏。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="5监控告警"&gt;5、监控告警&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;服务监控&lt;/p&gt;
&lt;p&gt;主要目的是服务出现故障或问题时候能够准确快速的发现，避免产生更大范围的影响。可以分为系统层包括主机的一些CPU\磁盘等指标，应用层包括进程状态、吞吐量，业务层包括业务自定义的指标，服务响应类等，用户层关注在用户行为、舆情监控等；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务拨测&lt;/p&gt;
&lt;p&gt;拨测是探测服务可用性的监控方式，通过拨测节点对目标服务进行周期性探测，主要通过可用性和响应时间来度量，拨测节点通常由异地多个。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;节点探测&lt;/p&gt;
&lt;p&gt;用来发现和追踪不同的机房节点之间网络可用性和通畅性的架空方式，主要通过响应时间、丢包率、跳数来度量。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;告警去重&lt;/p&gt;
&lt;p&gt;当告警恢复之前，不会有相同的告警持续产生；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;告警抑制&lt;/p&gt;
&lt;p&gt;为了减少系统抖动带来的干扰，还需要实现告警的抑制，比如服务器瞬间高负载可能是正常的，只有持续一段时间的高复杂才需要得到重视。这个往往可以通过连续告警探测次数来达到。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;告警恢复&lt;/p&gt;
&lt;p&gt;开发/运维人员不仅需要收到告警通知，还需要收到告警消除和告警恢复正常的通知。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;告警合并&lt;/p&gt;
&lt;p&gt;对同一时刻产生的多条相同告警进行合并，如某个集群服务同时出现多个子服务负载过高的告警，需要合并为一条告警；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;告警收敛&lt;/p&gt;
&lt;p&gt;某个告警产生时候，往往也会产生其他的告警，这时只对更笨原因产生告警，其他告警收敛为自告警一并发送原因。如某个主机网络不通的时候，可能伴随也是服务不可用的告警；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;故障自愈&lt;/p&gt;
&lt;p&gt;实时发现告警、预诊断分析自动恢复故障，并且打通周边系统实现整个流程的闭环。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="6服务治理"&gt;6、服务治理&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;微服务&lt;/p&gt;
&lt;p&gt;架构模式，单一应用划分成一组小的服务，服务之间相互协调、互相配合，为用户提供最终价值；服务间提供轻量级的通信机制。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务发现&lt;/p&gt;
&lt;p&gt;使用注册中心来记录分布式系统中全部的服务信息，以便其他依赖该服务的服务能够找到。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;流量雪峰&lt;/p&gt;
&lt;p&gt;流量的峰值可能是短暂的，为了节省机器资源，不能按照对大话资源的能力来支持短时间的高峰请求。需要有一定的手段进行高峰流量的削弱，让系统吞吐量在高峰请求下可控。常见的策略有队列、限频、分层过滤、多级缓存等；&lt;/p&gt;
&lt;p&gt;限频指的是在同一时刻内，并发请求数不能超过某个值。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;版本兼容&lt;/p&gt;
&lt;p&gt;升级版本过程中，需要考虑版本升级后，新的数据结构是否能够兼容旧的数据结构，新修改的协议是否能够理解旧的协议。以及版本的升级依赖问题。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;过载保护&lt;/p&gt;
&lt;p&gt;当前负载已经超出了系统的最大处理能力，过载的出现，会导致部分服务不可用，如果处理不当可能造成整个服务的不可用，雪崩。针对这种异常的场景，需要做的保护措施，避免整个服务的不可用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务熔断&lt;/p&gt;
&lt;p&gt;当出现服务不可用或响应超时的情况，为了防止整个系统出现雪崩，暂停对该服务的调用，往往熔断的是不重要的系统，避免影响核心业务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务降级&lt;/p&gt;
&lt;p&gt;当服务器压力剧增的时候，更具业务情况及流量对服务有策略的降级，以释放资源保证核心任务的正常运行。降级的方式可以优雅，依据服务方式拒收请求或者延迟服务，或者依据服务范围砍掉某个功能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;熔断和降级&lt;/p&gt;
&lt;p&gt;目标都是基于可用性和可靠性出发，防止系统崩溃，最终让用户体验到的是某些功能暂时不可用。服务熔断一般是某个下游服务故障引起，而服务降级一般是从整体负荷考虑；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;故障屏蔽&lt;/p&gt;
&lt;p&gt;把故障的机器，或者故障的服务从当前的集群剔除，确保新的请求不会进入到故障机器。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
</item>
<item>
<title>未来, 你好</title>
<link>https://liaolile.com/post/life/%E6%9C%AA%E6%9D%A5%E4%BD%A0%E5%A5%BD/</link>
<pubDate>Tue, 31 Mar 2020 23:13:00 +0000</pubDate>
<guid>https://liaolile.com/post/life/%E6%9C%AA%E6%9D%A5%E4%BD%A0%E5%A5%BD/</guid>
<description>&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/yVtwJRAK5x1ujNs.jpg" alt="Snipaste_2022-03-12_15-08-50" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;我不知道未来会发生什么，但可以想象。如果用科学理论思考，未来人类可能会继续进化，发明出真“懂“你的智能机器人，我们喜爱的熊、狗、马和橡木树这类动植物也会不断进化，有一天它们能开头诉说自己生命的意义。这是我的一种假设，但我不保证如果真有那么一天，我肯定会告诉你。&lt;/p&gt;
&lt;p&gt;如果我用右脑用得多一点，我会相信爱是一切的基础。但礼物只有打开了才算是礼物，所以未来怎样，我也不清楚。&lt;/p&gt;
&lt;p&gt;但可以找一件人生中最有意义的事，将它守护。怎样的人生才有意义？为什么人生一定要有意义？&lt;/p&gt;
&lt;p&gt;第二个问题：如果都不知道自己想解决哪些问题，不完美的世界诸多不完美的问题，让世界变得更加美好，我们才会感受到自身的重要性，才会抹去那一份愧疚不安。&lt;/p&gt;
&lt;p&gt;第一个问题：“无限”，无限将自己缩得很小，为的是给我们腾出一块地方出来大施拳脚。为了创造无限，无限本身必须从中抽身，但是又不能完全抽身。就像上帝不能创造一块自己也搬不起来的石头。关于这份自由你不能去想太多，否则礼物就失去了意义。人生的意义是“无限”能送给我们最好的礼物 ，但是为了让我们拿到这份礼物，它必须腾出一些空间。&lt;/p&gt;
&lt;p&gt;我找工作赚钱生孩子，还你也一样，一边待着去，瞎叨叨什么？如果自己满意，别人也说不出什么，你大可以继续像动物一样活下去。但是人生何能如此，人类选择给人生赋予意义，无限是在赋予我们以无限性，创造一个宇宙，其中有一种生物逐渐进化得能够安排自己的生活， 能将自己从生物学和文化条件的作用做解放出来。这种无限性要求事物的存在需要有意义！&lt;/p&gt;
&lt;p&gt;这个世界并不完美，既有美好的一面，也有可怖的一面，我们每个人都能以自己独特的方式来修复它。我们移除界限、摆脱互相之间的折磨后，就能够在无限中获得更多的个人感知。为了解决世界上各种各样的问题，我们有很多碎片需要拼凑，这样对世界的认识才是完整的，而我们每个人的碎片都不尽相同。碎片的尽管也有菱角，但融合后是一种更高效的新方式，是一种尝试，也是一种努力，更是一种完美。&lt;/p&gt;
&lt;p&gt;对于人本身来说，美好的瞬间肯定不单单是快乐，你肯定还完成了一些自己关心的事。这些事才是关键。如果你感到自己可有可无，与周围失去了联系，那肯定不好受。只有把问题放到生活的大背景中，才能全身心的领会美好的瞬间。我们是全身心向着这个方向努力，可以得到身体最直接的反应。&lt;/p&gt;
&lt;p&gt;自己快乐的同时，让全世界也感受快乐。&lt;/p&gt;
&lt;p&gt;我知道你是个好人。一切没有区别的时候，没人想做恶人。你希望自己快乐，也希望大家都快乐，这样自己才会更快乐。大家都感受到快乐了，那还能再加点什么呢？加什么才不无聊，不老套呢？那唯一的答案应该是迈步往前，然后干。&lt;/p&gt;
&lt;p&gt;学到了知识，解决了问题。这种发现可以智力层面、艺术层面或是个人层面的，可能是你了解了自己的使命、搞清了自己要养什么宠物、想住什么样的房子，也可能是构建起了一套成功的理论体系。当然，在生命的很多时间，你有了惊人的发现，相比之下，之前的日子太糟糕了。此时我们应该“啊哈，啊哈”高喊几声，因为苹果砸到牛顿的头时，他们都有这种的感觉。在情绪层面，最重要的是体会到爱与被爱的感受，这是音乐给的节奏。&lt;/p&gt;
&lt;p&gt;所以说…最好的瞬间应该是极致的身体快感，加上爱与被爱的情绪满足感，再加上高喊出“啊哈”！的精神愉悦感，很新鲜，也很出人意料，就像一个茶包泡出了五杯茶。已经和好了，但还不完美，但是没有必要为之前虚度的时光感到惭愧。我们肯定都希望现在和过去不一样，要比过去更好，但又不能反衬得过去像一对垃圾一样，我们对过去心怀感恩，同时享受当下更美好、丰富、新鲜、有趣、快乐的新生活。最好的时光并不是要完全抛弃过去的岁月，而是可爱的婴儿长大成人，是嫩芽到参天大树的成长，是细菌进化出热热闹闹的地球生物。&lt;/p&gt;
&lt;p&gt;只有你自己经历过了，才会知道它对你重不重要，为什么重要。是的，世界上很多事情即使不做也知道很重要。比如让你的孩子多学点东西，多看些书。但是并不是看电脑玩手机眼睛会瞎，而看书不会。重要的是那些能为你开启新世界大门的事，大门后是你之前不知道也没有想过的更多重要的事。我们最初都有一些自己的坚持，一步步由过去变成了现在的模样，这给我们带来了欢乐和意义。随着时光流逝，我们遇到了其他人，与他们相爱生子，变成祖辈。后代是由我们的基因网和人生意义造就的，就像一颗大树结出了果实。我们必须经历从不成熟走向成熟，然后繁衍、变老。这就是我们的未来，我们设想了美好瞬间，也设计了美好时光。无限、自由的美好。&lt;/p&gt;
&lt;p&gt;在最后的时光，有几分钟思考的时间，可以沉浸在喜剧里，和家人朋友讲讲笑话。面前堆放着他的礼物，上面分别贴着：“自由”，“神秘主义”和“未来”！&lt;/p&gt;</description>
</item>
<item>
<title>Hugo Todo</title>
<link>https://liaolile.com/post/tools/hugo-todo/</link>
<pubDate>Tue, 04 Jun 2019 12:35:10 +0000</pubDate>
<guid>https://liaolile.com/post/tools/hugo-todo/</guid>
<description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;友链&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.tencent.com/developer/article/1944132" target="_blank" rel="noopener"&gt;Hugo博客添加友链 - 云+社区 - 腾讯云 (tencent.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hutusi.com/links/" target="_blank" rel="noopener"&gt;友链 | 胡涂说 (hutusi.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://iamgodot.com/about/" target="_blank" rel="noopener"&gt;Godot&amp;rsquo;s Blog (iamgodot.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sulvblog.cn/" target="_blank" rel="noopener"&gt;Sulv&amp;rsquo;s Blog (sulvblog.cn)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;支持&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://nodogmablog.bryanhogan.net/support/" target="_blank" rel="noopener"&gt;Support this site | no dogma blog (bryanhogan.net)&lt;/a&gt;&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/05/22/Mzav2DrgPqfmeoE.png" alt="image-20220522075405309" style="zoom:67%;" /&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://huhuaping.com/" target="_blank" rel="noopener"&gt;Academic (huhuaping.com)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;分发&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/crawlab-team/artipub" target="_blank" rel="noopener"&gt;crawlab-team/artipub: Article publishing platform that automatically distributes your articles to various media channels (github.com)&lt;/a&gt; ArtiPub (Article Publisher 的简称，意为 &amp;ldquo;文章发布者&amp;rdquo;) 是一款开源的一文多发平台，可以帮助文章作者将编写好的文章自动发布到掘金、SegmentFault、CSDN、知乎、开源中国等技术媒体平台，传播优质知识，获取最大的曝光度。ArtiPub 安装简单，提供了多种安装方式，可以一键安装使用，安装一般只要 5 分钟。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;持续集成&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://app.netlify.com/sites/dapper-kringle-21e9eb/settings/domain" target="_blank" rel="noopener"&gt;Domain management | Site settings (netlify.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(统计分析) &lt;a href="https://github.com/electerious/Ackee" target="_blank" rel="noopener"&gt;https://github.com/electerious/Ackee&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;文章目录，参考&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;云原生领域大神，赵化冰&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/zhaohuabing/hugo-theme-cleanwhite" target="_blank" rel="noopener"&gt;zhaohuabing/hugo-theme-cleanwhite: A clean, elegant blog theme for hugo (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.zhaohuabing.com/post/2021-09-26-hugo-theme-clean-white/" target="_blank" rel="noopener"&gt;Hugo Theme: CleanWhite-赵化冰的博客 | Zhaohuabing Blog&lt;/a&gt;&lt;/p&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;云原生社区官方网站源码参考学习，基于Hugo：&lt;a href="https://github.com/cloudnativeto/cloudnative.to" target="_blank" rel="noopener"&gt;cloudnativeto/cloudnative.to: Source code of cloudnative.to (github.com)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>Linux的命令学习</title>
<link>https://liaolile.com/post/tools/linux%E5%91%BD%E4%BB%A4/</link>
<pubDate>Tue, 04 Jun 2019 12:35:10 +0000</pubDate>
<guid>https://liaolile.com/post/tools/linux%E5%91%BD%E4%BB%A4/</guid>
<description>&lt;ol&gt;
&lt;li&gt;关于关键字在对应的目录中查找出对应的文件&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f &lt;span class="p"&gt;|&lt;/span&gt;xargs grep &lt;span class="s2"&gt;&amp;#34;Liao lile work&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;查询某个时间以后修改的文件列表&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find ./ -newermt &lt;span class="s1"&gt;&amp;#39;2022-05-18 23:46:43&amp;#39;&lt;/span&gt; -type f &lt;span class="p"&gt;|&lt;/span&gt;xargs ls -ltr  --full-time
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="3"&gt;
&lt;li&gt;
&lt;p&gt;关于linux的控制台颜色定制&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;在~/.bashrc文件中保存下述的内容；&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git_branch&lt;span class="o"&gt;(){&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;git rev-parse --abbrev-ref HEAD 2&amp;gt;/dev/null&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;(no branch)&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;			&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;(`git rev-parse --short HEAD`...)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;(&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;debian_chroot&lt;/span&gt;&lt;span class="p"&gt;:+(&lt;/span&gt;&lt;span class="nv"&gt;$debian_chroot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\[\033[00;34;1m\]\u\[\033[00;34;1m\]@\[\033[00;34;1m\]\h\[\e[37;1m\]:\[\033[00;34;1m\]\w\[\033[01;36;1m\] \$(git_branch)\[\e[35;1m\] \$\[\e[35;1m\] &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://blog.csdn.net/qq_41009742/article/details/85009432" target="_blank" rel="noopener"&gt;Linux下使用git设置显示分支名称和改变颜色_犹有傲霜枝的博客-CSDN博客_git分支颜色&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>Hugo环境搭建</title>
<link>https://liaolile.com/post/tools/hugo%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/</link>
<pubDate>Sat, 04 May 2019 11:35:10 +0000</pubDate>
<guid>https://liaolile.com/post/tools/hugo%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/</guid>
<description>&lt;p&gt;[toc]&lt;/p&gt;
&lt;h3 id="hugo是什么"&gt;Hugo是什么？&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Hugo以速度快著称，号称是世界上最快的网站生成框架。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当前放弃了WordPress作为博客的选择！😂😂 体验不够优雅顺滑！其技术栈复杂，用到了mysql, php-fpm, openresty以及wordpress本身，而且wordpress本身一大堆的插件，2U2G的机器不足以容纳如此重的内容；&lt;/p&gt;
&lt;p&gt;下述文档仅记录Hugo环境搭建过程需要注意的内容，以备后续查阅需要。&lt;/p&gt;
&lt;!---more--&gt;
&lt;h3 id="faq"&gt;FAQ&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;关于nginx ssl 证书的获取&lt;/p&gt;
&lt;p&gt;当前的方案是参考在阿里云申请的免费ssl证书&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;，证书由于是有有效期的，到期了还得去阿里云重新申请证书并且绑定，有点繁琐；当前申请的证书是在浏览器访问的时候并不会出现不安全的提示。&lt;/p&gt;
&lt;p&gt;为了避免繁琐的证书到期而切换，希望有一种方法能够自动化实现证书的定期更新，因而找到了另外在skyao的博客中提及的内容&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;（有待后续进一步验证）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于nginx的80端口和443端口&lt;/p&gt;
&lt;p&gt;对于服务能够对外提供既能够提供https, 也能够提供http服务；默认https走的443端口，而http走的80端口,可以按照如下的配置使http的请求都会跳转到对应的https&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;liaolile.com&lt;/span&gt; &lt;span class="s"&gt;www.liaolile.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^(.*)&lt;/span&gt;$  &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$host$1&lt;/span&gt; &lt;span class="s"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关于当前Hugo国际化i18n配置&lt;/p&gt;
&lt;p&gt;需要在hugo的根目录下进行&lt;strong&gt;i18n&lt;/strong&gt;目录的创建，并且在其中加上对应的zh.toml配置文件，用于国际化内容替换&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/14/k8NHChwJgrUB4Xp.png" alt="" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关于高效的写作环境
使用的是Typora + PicGo + SM.MS 三个配合进行使用&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;，其中Typora为Markdown写作编辑器，体验不错；PicGo主要用于处理当前Markdown文档中图片自动落床的问题，其会把Markdown文档中插入的图片自动上传到SM.MS图床服务账号中，为啥不选gitee作为图床呢，当前遇到了一些坑，服务端一直报403。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关于hugo academic主题&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;acadmic主题的地址是：&lt;a href="https://github.com/wowchemy/starter-hugo-academic" target="_blank" rel="noopener"&gt;start-hugo-academic&lt;/a&gt;，类似于springboot的一键式集成，其对应的主题实际是在go.mod中指定的github.com/wowchemy/wowchemy-hugo-modules/wowchemy/v5 ，主题会下载到本地，因而主题的定制需要在对应的本地文件中。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/21/q7wh9jFylQ8GeP3.png" alt="image-20220521094822726" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;该wowchemy/v5主题中很多资源引用的cdn.jsdelivr.net的资源，但是目前其资源由于dns污染，在中国加载有问题&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;，所以需要切换对静态资源加载的地址，主要的资源地址配置在&lt;code&gt;/opt/blog/hugo-theme&lt;/code&gt;/wowchemy/wowchemy-hugo-modules/wowchemy/data/assets.toml文件中，其中上述加粗/opt/blog/hugo-theme是对应的主题的本地路径。该文件中主要有两种资源：cdn.jsdelivr.net/npm和cdn.jsdelivr.net/gh资源（github静态资源托管），其中https://cdn.jsdelivr.net/npm资源替换为https://unpkg.com/, cdn.jsdelivr.net/gh暂时找不到对应的替换cdn地址，只能去github上下载对应的源码文件并且托管到自身的服务器上，如下是参考：&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/05/21/feibZHkVYhjpBJM.png" alt="image-20220521100110619" style="zoom:50%;" /&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于出现替换本地文件后出现Failed to find a valid digest in the &lt;strong&gt;&amp;lsquo;integrity&amp;rsquo;&lt;/strong&gt; attribute for resource &amp;lsquo;&lt;a href="https://liaolile.com/js/local/cdn.jsdelivr.net/gh/krisk/Fuse@v3.2.1/dist/fuse.min.js%27" target="_blank" rel="noopener"&gt;https://liaolile.com/js/local/cdn.jsdelivr.net/gh/krisk/Fuse@v3.2.1/dist/fuse.min.js'&lt;/a&gt; with computed SHA-512 integrity &amp;lsquo;&lt;strong&gt;tm9sNooEMtnClt+Dyrr0YPWwlOdUSm9/y97x0WjXHahG7QyPXs334pApMrY2cxitrW5zZIDCHveVvvgHfJS9uQ==&lt;/strong&gt;&amp;rsquo;. The resource has been blocked.问题，直接找到对应的文件的sri值，替换为对应的SHA-512值即可。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关于分享集成&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;对于share.js的集成，参考相关的帖子&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;，同时对应share.js的github地址可供相关的定制使用参考：&lt;a href="https://github.com/overtrue/share.js" target="_blank" rel="noopener"&gt;overtrue/share.js: 一键分享到微博、微信&lt;/a&gt;。界面相关的一些其他的定制，均可参考该帖子，方法类似；当前微信的分享标签在手机端是不显示的，因为手机端的app一般都有分享的控件直接进行控制；网页版效果如下：&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/05/22/djfWxKlQOzBi9aI.png" alt="image-20220522213142045" style="zoom:50%;" /&gt;
&lt;p&gt;修改/opt/blog/hugo-theme/wowchemy/wowchemy-hugo-modules/wowchemy/layouts/partials/page_footer.html，放上自己定义的share.html嵌入；&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/05/29/qOAcLinBmCTyatl.png" alt="image-20220527230558677" style="zoom:67%;" /&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关于author微信二维码的图片，当前尚无现有的方法进行集成，需要自行写js以及插入到对应的html界面中。获取当前微信头像的悬浮事件，然后绑定图像呈现在对应的下方；当前所有的社交icon均在&lt;strong&gt;network-icon&lt;/strong&gt; class中定义的（当前有两个地方引用，一个是author的个人简介部分，一个是每篇文章的末尾介绍），需要把相关的js加载的，并且把二维码渲染绑定到.fa-weixin上。如下图：&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/05/22/Hrw7ZJqUFynOmLV.png" alt="文章后面的社交媒体账号信息" style="zoom:50%;" /&gt;
&lt;p&gt;对应的需要修改的html对应的文件是：&lt;code&gt;/opt/blog/hugo-theme/wowchemy/wowchemy-hugo-modules/wowchemy/layouts/partials/social_link.html&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;新增下述红色内容：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/js/jquery.js&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/js/self.js&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src="https://s2.loli.net/2022/05/29/59oYdxThEilVJPZ.png" alt="image-20220527225350013" style="zoom: 67%;" /&gt;
&lt;img src="https://s2.loli.net/2022/05/22/FVM2hxTvB3ntDrW.png" alt="个人简介的社交媒体账号信息" style="zoom:50%;" /&gt;
&lt;p&gt;对应的需要修改的html对应的文件是：&lt;code&gt;/opt/blog/hugo-theme/wowchemy/wowchemy-hugo-modules/wowchemy/layouts/partials/widgets/about.html&lt;/code&gt;，也是新增自定的js脚本&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/05/29/eCBpTSyaVGrjqf3.png" alt="image-20220527230303178" style="zoom:67%;" /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关于文章内容加密&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hugo-Encryptor&lt;/strong&gt;&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt; 是一款能够帮助作者保护文章内容的工具。它使用 AES-256 来对文章的内容进行加密，并且通过在文章中嵌入内联 &lt;code&gt;JavaScript&lt;/code&gt; 代码来验证读者输入的密码是否正确。没有正确的文章密码，读者将无法看到文章的加密内容&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;遇到如下的问题：&lt;/p&gt;
&lt;img src="https://s2.loli.net/2022/08/12/FhzjOD3KpPXbRGU.png" alt="image-20220812001935062" style="zoom:67%;" /&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="参考"&gt;参考&lt;/h3&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://blog.csdn.net/m0_37969197/article/details/106330622" target="_blank" rel="noopener"&gt;阿里云免费SSL证书配置（图文详解）_老吉丶的博客-CSDN博客_阿里云免费ssl证书&lt;/a&gt;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://skyao.io/learning-hugo/docs/installation/https.html" target="_blank" rel="noopener"&gt;开启HTTPS | Hugo学习笔记 (skyao.io)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://blog.csdn.net/sxf1061700625/article/details/107948323" target="_blank" rel="noopener"&gt;使用Gitee作为Markdown的图床_小锋学长生活大爆炸的博客&lt;/a&gt;&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://blog.csdn.net/u013014254/article/details/122045331" target="_blank" rel="noopener"&gt;jsdelivr炸了如何解决|用这些免费cdn_地域男孩的博客-CSDN博客_jsdelivr&lt;/a&gt;&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://huangzhongde.cn/post/2020-02-22-hugo-blog-using-sharejs/" target="_blank" rel="noopener"&gt;Hugo集成Share.js一键分享插件 | 黄忠德的博客 (huangzhongde.cn)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://github.com/Li4n0/hugo_encryptor/blob/master/README-zh_CN.md" target="_blank" rel="noopener"&gt;hugo_encryptor/README-zh_CN.md at master · Li4n0/hugo_encryptor (github.com)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7" role="doc-endnote"&gt;
&lt;p&gt;&lt;a href="https://0n0.fun/post/2019/03/this-is-hugo-encryptor/" target="_blank" rel="noopener"&gt;这是一个Hugo文章加密工具 (0n0.fun)&lt;/a&gt;&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
</item>
<item>
<title>Slides</title>
<link>https://liaolile.com/slides/example/</link>
<pubDate>Tue, 05 Feb 2019 00:00:00 +0000</pubDate>
<guid>https://liaolile.com/slides/example/</guid>
<description>&lt;h1 id="create-slides-in-markdown-with-wowchemy"&gt;Create slides in Markdown with Wowchemy&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://wowchemy.com/" target="_blank" rel="noopener"&gt;Wowchemy&lt;/a&gt; | &lt;a href="https://owchemy.com/docs/managing-content/#create-slides" target="_blank" rel="noopener"&gt;Documentation&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="features"&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Efficiently write slides in Markdown&lt;/li&gt;
&lt;li&gt;3-in-1: Create, Present, and Publish your slides&lt;/li&gt;
&lt;li&gt;Supports speaker notes&lt;/li&gt;
&lt;li&gt;Mobile friendly slides&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="controls"&gt;Controls&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Next: &lt;code&gt;Right Arrow&lt;/code&gt; or &lt;code&gt;Space&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Previous: &lt;code&gt;Left Arrow&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Start: &lt;code&gt;Home&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Finish: &lt;code&gt;End&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Overview: &lt;code&gt;Esc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Speaker notes: &lt;code&gt;S&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Fullscreen: &lt;code&gt;F&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Zoom: &lt;code&gt;Alt + Click&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://revealjs.com/pdf-export/" target="_blank" rel="noopener"&gt;PDF Export&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="code-highlighting"&gt;Code Highlighting&lt;/h2&gt;
&lt;p&gt;Inline code: &lt;code&gt;variable&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Code block:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;porridge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;blueberry&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;porridge&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;blueberry&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Eating...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="math"&gt;Math&lt;/h2&gt;
&lt;p&gt;In-line math: $x + y = z$&lt;/p&gt;
&lt;p&gt;Block math:&lt;/p&gt;
&lt;p&gt;$$
f\left( x \right) = ;\frac{{2\left( {x + 4} \right)\left( {x - 4} \right)}}{{\left( {x + 4} \right)\left( {x + 1} \right)}}
$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="fragments"&gt;Fragments&lt;/h2&gt;
&lt;p&gt;Make content appear incrementally&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{% fragment %}} One {{% /fragment %}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{% fragment %}} **Two** {{% /fragment %}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{% fragment %}} Three {{% /fragment %}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Press &lt;code&gt;Space&lt;/code&gt; to play!&lt;/p&gt;
&lt;span class="fragment " &gt;
  One
&lt;/span&gt;
&lt;span class="fragment " &gt;
  &lt;strong&gt;Two&lt;/strong&gt;
&lt;/span&gt;
&lt;span class="fragment " &gt;
  Three
&lt;/span&gt;
&lt;hr&gt;
&lt;p&gt;A fragment can accept two optional parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;class&lt;/code&gt;: use a custom style (requires definition in custom CSS)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;weight&lt;/code&gt;: sets the order in which a fragment appears&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="speaker-notes"&gt;Speaker Notes&lt;/h2&gt;
&lt;p&gt;Add speaker notes to your presentation&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{% speaker_note %}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Only the speaker can read these notes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Press &lt;span class="sb"&gt;`S`&lt;/span&gt; key to view
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  {{% /speaker_note %}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Press the &lt;code&gt;S&lt;/code&gt; key to view the speaker notes!&lt;/p&gt;
&lt;aside class="notes"&gt;
  &lt;ul&gt;
&lt;li&gt;Only the speaker can read these notes&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;S&lt;/code&gt; key to view&lt;/li&gt;
&lt;/ul&gt;

&lt;/aside&gt;
&lt;hr&gt;
&lt;h2 id="themes"&gt;Themes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;black: Black background, white text, blue links (default)&lt;/li&gt;
&lt;li&gt;white: White background, black text, blue links&lt;/li&gt;
&lt;li&gt;league: Gray background, white text, blue links&lt;/li&gt;
&lt;li&gt;beige: Beige background, dark text, brown links&lt;/li&gt;
&lt;li&gt;sky: Blue background, thin dark text, blue links&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;night: Black background, thick white text, orange links&lt;/li&gt;
&lt;li&gt;serif: Cappuccino background, gray text, brown links&lt;/li&gt;
&lt;li&gt;simple: White background, black text, blue links&lt;/li&gt;
&lt;li&gt;solarized: Cream-colored background, dark green text, blue links&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image="/media/boards.jpg"
  &gt;

&lt;h2 id="custom-slide"&gt;Custom Slide&lt;/h2&gt;
&lt;p&gt;Customize the slide style and background&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{&lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;slide&lt;/span&gt; &lt;span class="na"&gt;background-image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/media/boards.jpg&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{&lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;slide&lt;/span&gt; &lt;span class="na"&gt;background-color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#0000FF&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{&lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;slide&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;my-style&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="custom-css-example"&gt;Custom CSS Example&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s make headers navy colored.&lt;/p&gt;
&lt;p&gt;Create &lt;code&gt;assets/css/reveal_custom.css&lt;/code&gt; with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;reveal&lt;/span&gt; &lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;reveal&lt;/span&gt; &lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;reveal&lt;/span&gt; &lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;navy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h1 id="questions"&gt;Questions?&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/wowchemy/wowchemy-hugo-modules/discussions" target="_blank" rel="noopener"&gt;Ask&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://wowchemy.com/docs/managing-content/#create-slides" target="_blank" rel="noopener"&gt;Documentation&lt;/a&gt;&lt;/p&gt;
</description>
</item>
<item>
<title>计算机领域的定律</title>
<link>https://liaolile.com/post/tech/base/%E8%AE%A1%E7%AE%97%E6%9C%BA%E9%A2%86%E5%9F%9F%E7%9A%84%E5%AE%9A%E7%90%86/</link>
<pubDate>Sun, 08 Apr 2018 21:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/base/%E8%AE%A1%E7%AE%97%E6%9C%BA%E9%A2%86%E5%9F%9F%E7%9A%84%E5%AE%9A%E7%90%86/</guid>
<description>&lt;p&gt;&lt;code&gt;定律&lt;/code&gt;是为实践和事实所证明，反映事物在一定条件下发展变化的客观规律的论断。定律的特点，是可证，而且已经被不断证明。定律是一种理论模型，它用以描述特定情况、特定尺度下的现实世界，在其它尺度下可能会失效或者不准确。&lt;/p&gt;
&lt;p&gt;计算机领域存在很多经典的理论，由于之前没有系统的去梳理，所以大多是听过，然后后续再听的时候，嗯，是有这么一回事。但是要自己能够在对应的场景下去引用，去讲出来，就有些不够丰满。因而这篇主要关注怎么把这些计算机领域的定律，像故事一样的简单，总结起来。&lt;/p&gt;
&lt;p&gt;tl;dr&lt;/p&gt;
&lt;p&gt;康威定律可谓是软件架构设计中的第一定律，在《人月神话》这本软件圣经引用后被广泛推广。摩尔定律也是人们耳熟能详的，是计算机第一定律。&lt;/p&gt;
&lt;p&gt;另外还包括阿姆达尔Amdahl定律，奥卡姆剃刀原理。&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h3 id="康威定律"&gt;康威定律&lt;/h3&gt;
&lt;p&gt;1967年，马尔文·康威：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;设计系统的架构受制于生产这些设计的组织的沟通结构。&lt;/p&gt;
&lt;p&gt;Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;康威定律可以总结为4个定律：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;组织沟通方式会通过系统设计表达出来；&lt;/li&gt;
&lt;li&gt;时间再多一件事情也不可能做的完美，但总有时间做完一件事情；&lt;/li&gt;
&lt;li&gt;线型系统和线型组织架构间由潜在的异质同态特性；&lt;/li&gt;
&lt;li&gt;大的系统组织总是比小系统更倾向于分解；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;组织的沟通和系统的设计之间紧密相连，特别是复杂系统，解决好人与人的沟通才能由一个更好的系统设计。人员增加沟通成本呈指数增长的规律：沟通成本=n*(n-1)/2， n表示人的个数，n-1表示每个人据需要同剩下的n-&lt;/p&gt;
&lt;p&gt;1个人由交流，而沟通交流是双向的，所以会在此基础上除以2。&lt;/p&gt;
&lt;p&gt;对于团队我们应该追求小团队，为了整个系统的开发效率和最终产品结果。使用一切手段提升沟通效率，每个人每个系统有明确的分工。&lt;/p&gt;
&lt;p&gt;在软件开发中人手永远是不够的，事情也是永远做不完的，不可能做完没。面对这样的情况，敏捷开发可以做到不断迭代、持续交付、快速验证和反馈并持续的改进。再牛的开发也会写出bug，在全面的测试覆盖率也无法测出所有的问题，解决方案不是消灭这些问题，而是容忍一些问题的存在，然后通过适当的设计（冗余、监控、高可用）允许接受出错，当问题发生时能够快速解决。&lt;/p&gt;
&lt;p&gt;我们想要什么系统就搭建什么样的团队，反过来有什么样的团队就搭建什么样的系统。对于大的公司，架构不仅仅需要技术，还需要政治。这种政治说的是和他人协作将事情搞定的艺术，架构是一种社交活动，在技术世界里，个人主义很容易被打败即便目的是好的技术也是最有的技术。技术决策是也是政治决策，一个产品任何一个团队都可以做，但是对于选择任何一个都意味着局限。&lt;/p&gt;
&lt;h3 id="摩尔定律"&gt;摩尔定律&lt;/h3&gt;
&lt;p&gt;1965年，戈登·摩尔：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;每个新芯片大体上包含其前任2倍的容量，每个芯片的生产都是在前一个芯片产生后的18-24个月内。计算能力相对于时间周期将呈指数式的上升。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;衍生出三个版本：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;集成电路芯片上所集成的电路的数目，每隔18个月就翻一番；&lt;/li&gt;
&lt;li&gt;微处理器的性能每隔18个月提高1倍，而价格下降1倍；&lt;/li&gt;
&lt;li&gt;用1个美元所能买大的电脑性能，每隔18个月翻两番；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更有一个安迪比尔定律。安迪给你的，比尔都会拿走。安迪是Intel创始人，比尔是微软的创始人，intel不断提高CPU的计算能力，微软就用新的操作系统来吃掉它，就是硬件性能的提高总会迅速的被新的软件消耗掉。&lt;/p&gt;
&lt;p&gt;相近的一个使维尔斯定律，其认为软件变慢的速度比硬件编码的速度更慢。&lt;/p&gt;
&lt;p&gt;同时有一个反摩尔定律，就是IT公司如果18个月后卖掉同样多的同样的产品，其营业额却要减少1半，需要所有的硬件和设备生产厂商都要追赶上摩尔定律的发展速度。&lt;/p&gt;
&lt;p&gt;目前GPU就是摩尔定律进入失效区间的一个创新，计算不仅仅依赖CPU。图形渲染单元和计算单元放在一个芯片上，因为它们不会同时被使用，所以发热问题得到缓解。GPU简化了控制单元和缓存，把有限的芯片上的空间让个了计算单元，通过牺牲延时换取了吞吐量。&lt;/p&gt;
&lt;h3 id="阿姆达尔定律--古斯塔夫森定律"&gt;阿姆达尔定律 &amp;amp; 古斯塔夫森定律&lt;/h3&gt;
&lt;p&gt;阿姆达尔定律用于计算优化某一部分能够对整体产生的最大优化效果。在并行计算中，阿姆达尔定律主要用于预测使用多处理器的程序理论上所能达到的最大提速。
$$
{S}&lt;em&gt;{latency}(s)=1/(1-p+p/s)
$$
其中${S}&lt;/em&gt;{latency}$是任务整体执行过程的理论速度，s是任务中受益于系统性能提升的那一部分的加速，p是获益部分占用执行时间的比例。&lt;/p&gt;
&lt;p&gt;古斯塔夫森定律给出了任务执行时间固定时，通过提升系统性能所能达到的理论潜在加速。
$$
{S}&lt;em&gt;{latency}(s)=1-p+sp
$$
其中${S}&lt;/em&gt;{latency}$是整个任务执行过程的理论潜在加速，s是任务中受益于系统资源改进部分的潜在加速，p是系统资源改善之前收益部分占整个任务的执行工作量的比例。&lt;/p&gt;
&lt;p&gt;阿姆达尔定律假设问题大小固定，即执行的工作量不会随着资源的改善而改变。古斯塔夫森定律提出，程序员倾向于调整问题的大小以充分利用通过改善资源释放出的计算能力，更快的设备可以使用相同的时间解决更大的问题。&lt;/p&gt;
&lt;p&gt;阿姆达尔定律优化的目标是使程序在相同的工作负载下更快运行，古斯塔夫森定律意义在于改变了研究目的，选择或重构问题从而使用相同时间解决更大的问题，在相同的运行时间内实现更大的工作负载量。&lt;/p&gt;
&lt;h3 id="奥卡姆剃刀原理"&gt;奥卡姆剃刀原理&lt;/h3&gt;
&lt;p&gt;14 世纪，逻辑学家奥卡姆的威廉：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如无必要，勿增实体&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;不要浪费更多的东西去做，你可以用更少的东西做同样的事情。人们做的大部分事情可能没有意义，而隐藏在复杂事务中的一小部分是有意义的。复杂事情往往可以通过简单的方法解决，应该化繁为简，抓住重点，把我关键。&lt;/p&gt;
&lt;h3 id="扬尼斯定律"&gt;扬尼斯定律&lt;/h3&gt;
&lt;p&gt;程序员的开发效率每6年会提高一倍。平均年提高16.6%，如果没有达标，则我们的价值其实是在下降16.6%。对于公司来说，6年内员工数量保持不变，如果营业额没有翻一倍，那么公司的利润其实是在下降。但是并不是所有的公司全员都是程序员。&lt;/p&gt;
&lt;h3 id="梅特卡夫定律"&gt;梅特卡夫定律&lt;/h3&gt;
&lt;p&gt;一家网络的价值与它的用户数量的平方成正比。正式这一预言可以解释看似不可理解的信息现象，并帮助网络拥有者和价值投资者进行正确估值。&lt;/p&gt;
&lt;h3 id="尤尔互补性定律"&gt;尤尔互补性定律&lt;/h3&gt;
&lt;p&gt;其指出如果两种属性或两种产品是互补品，其中一种互补品的价值/需求将与另一种互补品的价格成反比。也就是说，如果一种补品的价格降低，那另一种补品的需求就会增加。&lt;/p&gt;
</description>
</item>
<item>
<title>The Consensus Algorithm - Raft</title>
<link>https://liaolile.com/post/tech/distributesystem/consensus-protocol/</link>
<pubDate>Wed, 04 Apr 2018 23:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/distributesystem/consensus-protocol/</guid>
<description>&lt;blockquote&gt;
&lt;p&gt;There is only one consensus protocol, and that&amp;rsquo;s Paxos - all other approaches are just broken versions of Paxos.
Ironic, hard enough to understand compared to the Raft.
There are significant gaps between the description of the Paxos algorithm and the needs of a real-world system. . . . the final system will be based on an un-proven protocol.
&lt;code&gt;--Chubby Implementer&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;tl;dr: &lt;a href="http://thesecretlivesofdata.com/raft/" target="_blank" rel="noopener"&gt;Raft (thesecretlivesofdata.com)&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="what-is-raft"&gt;What is Raft&lt;/h2&gt;
&lt;p&gt;Raft is a &lt;strong&gt;consensus algorithm&lt;/strong&gt; that is designed to be easy to understand. It&amp;rsquo;s equivalent to Paxos in fault-tolerance and performance. The difference is that it&amp;rsquo;s decomposed into relatively independent sub-problems, and it cleanly addresses all major pieces needed for practical systems. We hope Raft will make consensus available to a wider audience, and that this wider audience will be able to develop a variety of higher quality consensus-based systems than are available today.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Raft decomposes the consensus problem into &lt;em&gt;three relatively&lt;/em&gt; independent sub-problems:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Leader election&lt;/strong&gt;: a new leader must be chosen when starting the cluster and when an exsiting leader fails.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Log replication&lt;/strong&gt;: the leader must accept log entries from clients and replicate them across the cluster, forcing the other logs to agree with its own.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Safety&lt;/strong&gt;: if any server has applied a particular log entry to its state machine,  then no other server may apply a different command for the same log index. (the State Machine Safety Property)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;The basic elements of Raft show as belows:&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/X7gC2eyUYzaSQMi.png" alt="raft_basic_elements" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The main procedure of Raft depicted as follows:&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/vqhaDMj6EbcGoWe.png" alt="raft_main" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Five things&lt;/strong&gt; to be determinately implemented:&lt;code&gt;&amp;lt;br/&amp;gt;&lt;/code&gt;
&lt;code&gt;Election safety&lt;/code&gt;, at most one leader can be elected in a given term.
&lt;code&gt;Leader append-only&lt;/code&gt;, never delete or overwrites entries, only append entries.
&lt;code&gt;Log matching&lt;/code&gt;, to be perfect
&lt;code&gt;Leader completeness&lt;/code&gt;, to be complete
&lt;code&gt;State machine safety&lt;/code&gt;, the only entry for the a given index.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ensure above the five properties  are correctly executed, then the Raft is achieved.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A Raft cluster contains several servers, five is a typical number and tolerates two failures at the same time.&lt;/p&gt;
&lt;p&gt;At a given time, each server is one of three states: leader, follower, or candidate.
In normal operation, only one leader and the others followers. Followers only respond to leader and candidates.
Leader handles all the client requests.
If a client contacts a follower, the follower will redirects it to the leader.
Candidates work when electing a new leader.&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/XErM9Dc1IsmZxBJ.png" alt="raft_roles" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Time is divided into terms, and each term begins with election.
After election, the leader works for the rest of the term.
A new election will begin shortly after a split vote.
Raft ensures at most one leader in a  given term.&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/sTmRaKArpgyjq2L.png" alt="raft_time_stream" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Different severs may observer the transitions between terms at different time, and in some situations a server may not observe an election or entire terms.
Terms act a logical clock, which allows servers to detect obsolete information such as stale leaders.
Each server stores a current-term number, which increases monotonically.&lt;/p&gt;
&lt;p&gt;Raft servers communicate use remote procedure calls (RPCs), two type of RPCs is need for the consensus algorithm: &lt;strong&gt;RequestVote RPCs and AppendEntries RPCs&lt;/strong&gt;.&lt;/p&gt;
</description>
</item>
<item>
<title>The Consensus Algorithm - Raft</title>
<link>https://liaolile.com/post/tech/distributesystem/%E5%88%86%E5%B8%83%E5%BC%8F%E5%85%B1%E8%AF%86%E7%AE%97%E6%B3%95/</link>
<pubDate>Wed, 04 Apr 2018 23:23:10 +0000</pubDate>
<guid>https://liaolile.com/post/tech/distributesystem/%E5%88%86%E5%B8%83%E5%BC%8F%E5%85%B1%E8%AF%86%E7%AE%97%E6%B3%95/</guid>
<description>&lt;blockquote&gt;
&lt;p&gt;There is only one consensus protocol, and that&amp;rsquo;s Paxos - all other approaches are just broken versions of Paxos.
Ironic, hard enough to understand compared to the Raft.
There are significant gaps between the description of the Paxos algorithm and the needs of a real-world system. . . . the final system will be based on an un-proven protocol.
&lt;code&gt;--Chubby Implementer&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;拜占庭帝国想要进攻一个强大的敌人，为此派出了10支军队去包围这个敌人。这个敌人虽不比拜占庭帝国，但也足以抵御5支常规拜占庭军队的同时袭击。这10支军队在分开的包围状态下同时攻击。他们任一支军队单独进攻都毫无胜算，除非有至少6支军队（一半以上）同时袭击才能攻下敌国。他们分散在敌国的四周，依靠通信兵骑马相互通信来协商进攻意向及进攻时间。困扰这些将军的问题是，他们不确定他们中是否有叛徒，叛徒可能擅自变更进攻意向或者进攻时间。在这种状态下，拜占庭将军们才能保证有多于6支军队在同一时间一起发起进攻，从而赢取战斗？&lt;/p&gt;
&lt;p&gt;拜占庭将军问题中并不去考虑通信兵是否会被截获或无法传达信息等问题，即消息传递的信道绝无问题。Lamport已经证明了在消息可能丢失的不可靠信道上试图通过消息传递的方式达到一致性是不可能的。所以，在研究拜占庭将军问题的时候，已经假定了信道是没有问题的。&lt;/p&gt;
&lt;p&gt;共识算法分为两类：Crash Fault Tolerance（CFT）和Byzantine Fault Tolerance（BFT）；&lt;/p&gt;
&lt;p&gt;对于大部分分布式集群来说，集群节点和网络消息一般是可控的，只会出现节点故障而不会出现拜占庭错误那样的伪造和欺骗的网络消息。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;并发控制&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;服务器节点对于资源的管理需要满足并发控制的机制，事务T对某一个服务器节点的资源对象S的并发访问在事务U之前， 需要保证所有服务器节点上对S和其他资源对下那个的冲突访问，T始终在U之前。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;锁并发控制&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;事务T锁住了服务器节点X上的资源A，进行写操作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;事务U锁住了服务器节点Y上的资源B，进行写操作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;事务T尝试读取服务器节点Y上的资源B，此时B被事务U锁住，因而事务T等待锁释放；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;事务U尝试读取服务器节点X上的资源A，此时A被事务T锁住，因而事务U等待锁释放；&lt;/p&gt;
&lt;p&gt;上述出现分布式事务之间的循环依赖导致死锁的场景，需要有机制检测死锁，然后通知协调者，放弃某个事务；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;时间戳并发控制&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;协调者在每个事务启动的时候会分配一个全局唯一的时间戳，所有的事物均在统一的时间轴上运行，通过按照访问对象的事务时间戳顺序提交资源对象的版本来强保证事务执行的串行等价性。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;乐观并发控制&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;各个并发事务在执行完成之后执行检测是否冲突，如果确实冲突就放弃一些事务，然后让客户端重新启动这些事务进行重试。每个事务在提交前检测验证&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;多版本并发控制&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多版本是MVCC实现的基础。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-is-raft"&gt;What is Raft&lt;/h2&gt;
&lt;p&gt;Raft is a &lt;strong&gt;consensus algorithm&lt;/strong&gt; that is designed to be easy to understand. It&amp;rsquo;s equivalent to Paxos in fault-tolerance and performance. The difference is that it&amp;rsquo;s decomposed into relatively independent sub-problems, and it cleanly addresses all major pieces needed for practical systems. We hope Raft will make consensus available to a wider audience, and that this wider audience will be able to develop a variety of higher quality consensus-based systems than are available today.&lt;/p&gt;
&lt;p&gt;tl;dr: &lt;a href="http://thesecretlivesofdata.com/raft/" target="_blank" rel="noopener"&gt;Raft (thesecretlivesofdata.com)&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Raft decomposes the consensus problem into &lt;em&gt;three relatively&lt;/em&gt; independent sub-problems:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Leader election&lt;/strong&gt;: a new leader must be chosen when starting the cluster and when an exsiting leader fails.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Log replication&lt;/strong&gt;: the leader must accept log entries from clients and replicate them across the cluster, forcing the other logs to agree with its own.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Safety&lt;/strong&gt;: if any server has applied a particular log entry to its state machine,  then no other server may apply a different command for the same log index. (the State Machine Safety Property)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;The basic elements of Raft show as belows:&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/X7gC2eyUYzaSQMi.png" alt="raft_basic_elements" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The main procedure of Raft depicted as follows:&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/vqhaDMj6EbcGoWe.png" alt="raft_main" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Five things&lt;/strong&gt; to be determinately implemented:&lt;code&gt;&amp;lt;br/&amp;gt;&lt;/code&gt;
&lt;code&gt;Election safety&lt;/code&gt;, at most one leader can be elected in a given term.
&lt;code&gt;Leader append-only&lt;/code&gt;, never delete or overwrites entries, only append entries.
&lt;code&gt;Log matching&lt;/code&gt;, to be perfect
&lt;code&gt;Leader completeness&lt;/code&gt;, to be complete
&lt;code&gt;State machine safety&lt;/code&gt;, the only entry for the a given index.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ensure above the five properties  are correctly executed, then the Raft is achieved.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A Raft cluster contains several servers, five is a typical number and tolerates two failures at the same time.&lt;/p&gt;
&lt;p&gt;At a given time, each server is one of three states: leader, follower, or candidate.
In normal operation, only one leader and the others followers. Followers only respond to leader and candidates.
Leader handles all the client requests.
If a client contacts a follower, the follower will redirects it to the leader.
Candidates work when electing a new leader.&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/XErM9Dc1IsmZxBJ.png" alt="raft_roles" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Time is divided into terms, and each term begins with election.
After election, the leader works for the rest of the term.
A new election will begin shortly after a split vote.
Raft ensures at most one leader in a  given term.&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/sTmRaKArpgyjq2L.png" alt="raft_time_stream" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Different severs may observer the transitions between terms at different time, and in some situations a server may not observe an election or entire terms.
Terms act a logical clock, which allows servers to detect obsolete information such as stale leaders.
Each server stores a current-term number, which increases monotonically.&lt;/p&gt;
&lt;p&gt;Raft servers communicate use remote procedure calls (RPCs), two type of RPCs is need for the consensus algorithm: &lt;strong&gt;RequestVote RPCs and AppendEntries RPCs&lt;/strong&gt;.&lt;/p&gt;
</description>
</item>
<item>
<title>The Basic Elements of Kafka</title>
<link>https://liaolile.com/post/tech/distributesystem/the_basic_elements_of_kafka/</link>
<pubDate>Sat, 31 Mar 2018 23:13:00 +0000</pubDate>
<guid>https://liaolile.com/post/tech/distributesystem/the_basic_elements_of_kafka/</guid>
<description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Kafka是一种高吞吐量的分布式&lt;em&gt;发布订阅&lt;/em&gt;消息系统，它可以处理消费者规模的网站中的所有动作流数据。由LinkedIn开发的一个分布式的消息系统，使用Scala编写。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;!-- more --&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/6RCijK5npvfzyLM.png" alt="kafka1" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote&gt;
&lt;h2 id="特点"&gt;特点：&lt;/h2&gt;
&lt;/blockquote&gt;
&lt;p&gt;1、通过O(1)的磁盘数据结构提供消息的持久化，这种结构对于即使数以TB的消息存储也能够保持长时间的稳定性能。保证常数时间复杂度的访问性能。
2、高吞吐量  ：即使是非常普通的硬件Kafka也可以支持每秒数百万的消息。
3、支持通过Kafka服务器和消费机集群来分区消息。支持Kafka Server间的消息分区，及分布式消费，同时保证每个Partition内的消息顺序传输。
4、同时支持离线数据处理和实时数据处理。
5、支持Hadoop并行数据加载。支持在线水平扩展。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="kafka术语"&gt;Kafka术语&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Broker&lt;/code&gt;
Kafka集群包含一个或多个服务器，这种服务器被称为broker。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Topic&lt;/code&gt;
每条发布到Kafka集群的消息都有一个类别，这个类别被称为Topic。（物理上不同Topic的消息分开存储，逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处）Topic在逻辑上可以被认为是一个queue，每条消费都必须指定它的Topic，可以简单理解为必须指明把这条消息放进哪个queue里。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Partition&lt;/code&gt;
Partition是物理上的概念，每个Topic包含一个或多个Partition，注意消费者数量超过分区数量，多余消费者会闲置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Producer&lt;/code&gt;
负责发布消息到Kafka broker&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Consumer&lt;/code&gt;
消息消费者，向Kafka broker读取消息的客户端。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Consumer Group&lt;/code&gt;
每个Consumer属于一个特定的Consumer Group（可为每个Consumer指定group name，若不指定group name则属于默认的group）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/iADIMN9EfX3Gbea.png" alt="kafka2" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Kafka通过Zookeeper管理集群配置，选举leader，以及在Consumer Group发生变化时进行rebalance。
kafka集群有多个kafka实例组成，每个实例(server)成为broker。无论是kafka集群，还是producer和consumer都依赖于zookeeper来保证系统可用性集群保存一些meta信息。
kafka 在 zookeeper 中的存储结构如下图所示：&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/Wj8ClScpEUVR4rF.png" alt="kafka3" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;物理上把Topic分成一个或多个Partition，每个Partition在物理上对应一个文件夹，该文件夹下存储这个Partition的所有消息和索引文件。&lt;/p&gt;
&lt;p&gt;每个日志文件都是一个log entry序列，每个log entry包含一个4字节整型数值（值为N+5），1个字节的&amp;quot;magic value&amp;quot;，4个字节的CRC校验码，其后跟N个字节的消息体。每条消息都有一个当前Partition下唯一的64字节的offset，它指明了这条消息的起始位置。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;message length ： 4 bytes (value: 1+4+n)
&amp;ldquo;magic&amp;rdquo; value ： 1 byte
crc ： 4 bytes
payload ： n bytes&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个log entries并非由一个文件构成，而是分成多个segment，每个segment以该segment第一条消息的offset命名并以“.kafka”为后缀。另外会有一个索引文件，它标明了每个segment下包含的log entry的offset范围，如下图所示。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/2As8knHywVGP9M1.png" alt="kafka4" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;因为每条消息都被append到该Partition中，属于顺序写磁盘，因此效率非常高（经验证，顺序写磁盘效率比随机写内存还要高，这是Kafka高吞吐率的一个很重要的保证）。&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/LboJe1sWxpSYd4I.png" alt="kafka5" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;多个Partition属于同一个topic，但是如何保证topic消息的顺序呢&lt;/em&gt;？&lt;/p&gt;
&lt;p&gt;对于传统的message queue而言，一般会删除已经被消费的消息，而Kafka集群会保留所有的消息，无论其被消费与否。当然，因为磁盘限制，不可能永久保留所有数据（实际上也没必要），因此Kafka提供两种策略删除旧数据。一是基于时间，二是基于Partition文件大小。例如可以通过配置$KAFKA_HOME/config/server.properties，让Kafka删除一周前的数据，也可在Partition文件超过1GB时删除旧数据。&lt;/p&gt;
&lt;p&gt;Kafka会为每一个Consumer Group保留一些metadata信息——当前消费的消息的position，也即offset。这个offset由Consumer控制。正常情况下Consumer会在消费完一条消息后递增该offset。当然，Consumer也可将offset设成一个较小的值，重新消费一些消息。因为offet由Consumer控制，所以Kafka broker是无状态的，它不需要标记哪些消息被哪些消费过，也不需要通过broker去保证同一个Consumer Group只有一个Consumer能消费某一条消息，因此也就不需要锁机制，这也为Kafka的高吞吐率提供了有力保障。&lt;/p&gt;
&lt;p&gt;在发送一条消息时，可以指定这条消息的key，Producer根据这个key和Partition机制来判断应该将这条消息发送到哪个Partition。Partition机制可以通过指定Producer的partition. class这一参数来指定，该class必须实现kafka.producer.Partitioner接口。
回答了上述的疑问！！&lt;/p&gt;
&lt;p&gt;使用Consumer high level API时，同一Topic的一条消息只能被同一个Consumer Group内的一个Consumer消费（可以多次消费），但多个Consumer Group可同时消费这一消息。&lt;/p&gt;
&lt;p&gt;​		















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/MTEejwBDgJfy6rA.png" alt="kafka6" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Kafka的设计理念之一就是同时提供离线处理和实时处理。根据这一特性，可以使用Storm这种实时流处理系统对消息进行实时在线处理，同时使用Hadoop这种批处理系统进行离线处理，还可以同时将数据实时备份到另一个数据中心，只需要保证这三个操作所使用的Consumer属于不同的Consumer Group即可。&lt;/p&gt;
&lt;p&gt;push模式很难适应消费速率不同的消费者，因为消息发送速率是由broker决定的。push模式的目标是尽可能以最快速度传递消息，但是这样很容易造成Consumer来不及处理消息，典型的表现就是拒绝服务以及网络拥塞。而pull模式则可以根据Consumer的消费能力以适当的速率消费消息。&lt;/p&gt;
&lt;p&gt;对于Kafka而言，pull模式更合适。pull模式可简化broker的设计，Consumer可自主控制消费消息的速率，同时Consumer可以自己控制消费方式——即可批量消费也可逐条消费，同时还能选择不同的提交方式从而实现不同的传输语义。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可靠的数据传递&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;保证：指的是确保系统在各种不同环境下能够发生一致的行为。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kafka 可以保证分区消息的顺序。同一个分区&lt;/li&gt;
&lt;li&gt;只有当消息被写入分区的所有同步副本（但不一定要写入磁盘），他才被认为是已提交的。&lt;/li&gt;
&lt;li&gt;只要还有一个副本是活跃的，那么已经提交的消息就不会丢失&lt;/li&gt;
&lt;li&gt;消费者只能读取已经提交的信息&lt;/li&gt;
&lt;/ul&gt;
</description>
</item>
<item>
<title>分布式系统的事务</title>
<link>https://liaolile.com/post/tech/distributesystem/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E7%9A%84%E4%BA%8B%E5%8A%A1/</link>
<pubDate>Thu, 29 Mar 2018 23:13:00 +0000</pubDate>
<guid>https://liaolile.com/post/tech/distributesystem/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E7%9A%84%E4%BA%8B%E5%8A%A1/</guid>
<description>&lt;blockquote&gt;
&lt;p&gt;事务，一组操作构成的可靠的独立执行的单元，事务具备原子性、一致性、隔离性和持久性。&lt;/p&gt;
&lt;p&gt;分布式事务系统， Distributed Transaction System, 指&lt;strong&gt;事务的参与者&lt;/strong&gt;、&lt;strong&gt;支持事务的服务器&lt;/strong&gt;、&lt;strong&gt;资源服务器&lt;/strong&gt;以及&lt;strong&gt;事务管理器&lt;/strong&gt;分别位于不同的分布式的不同节点之上。&lt;/p&gt;
&lt;p&gt;分布式事务，由不同的服务之间通过&lt;strong&gt;网络远程&lt;/strong&gt;协作完成事务，是一次大活动有多个动作，由不同的小活动组成，这些活动要么全部成功，要么全部失败。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="事务理论和概念"&gt;事务理论和概念&lt;/h2&gt;
&lt;h3 id="1-数据库事务本地事务分布式事务"&gt;1. 数据库事务（本地事务）|分布式事务&lt;/h3&gt;
&lt;p&gt;​	数据库事务在实现时会将一次事务的所有操作全部纳入到一个&lt;strong&gt;不可分割的执行单元&lt;/strong&gt;，该执行单元的所有&lt;strong&gt;操作&lt;/strong&gt;要么都成功，要么都失败，只要其中任一操作执行失败，都将导致整个事务的回滚。支持严格的ACID，高效且可靠，隔离的最小单位受限于资源管理器。&lt;/p&gt;
&lt;p&gt;​	分布式事务是由网络远程协作完成的一系列动作，各个服务是网络分区的；场景覆盖：跨多个进程远程调用，跨数据库实例操作。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;数据库事务
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;begin transaction:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	本地数据库操作：张三-100元
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	本地数据库操作：李四+100元
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end transaction
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;分布式事务
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;begin transaction：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	本地数据库操作：张三-100元
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	远程调用操作:李四+100元
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end transaction
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;​	由于远程调用的李四+100成功，但是网络问题导致远程调用失败，则出现本地事务回滚，导致系统的数据不一致。&lt;/p&gt;
&lt;h3 id="2-分布式事务cap理论"&gt;2. 分布式事务CAP理论&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;一致性 Consistency，多个节点数据是否强一致；
&lt;ul&gt;
&lt;li&gt;数据需要在各个节点同步，所以写操作是有一定的时延。对于一致性会要求对资源暂时锁定，待同步完成后释放锁定资源；如果请求数据同步失败的节点，应当返回失败而不是旧数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;可用性 Availability， 分布式系统活跃的节点都能够处理所有操作且能响应查询，不会出现超时或失败；&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;确保从节点的数据可用性，不应将资源锁定，需要返回数据，即使是返回旧数据，不能返回错误或者响应超时；&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分区容忍性 Partition tolerance， 出现网络故障，节点通信失败，但是系统仍能正常工作；&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据同步失败不影响当前系统的读写操作，系统部分节点故障不影响整个系统对外的响应，分区容忍性是分布式系统具备的基本能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;只能同时满足上述两个要素，不可三者兼得；&lt;/p&gt;
&lt;p&gt;当前大部分分布式系统选择的是AP（&lt;strong&gt;柔性事务&lt;/strong&gt;）,而对于一致性选择的是最终一致性，而不是强一致性，能够接受查询数据在一定时间内不是最新的；延伸出后续的BASE理论。&lt;/p&gt;
&lt;p&gt;CP是放弃了可用性（&lt;strong&gt;刚性事务&lt;/strong&gt;），zookeeper即使用该策略追求强一致性，同时跨行转账需要双方银行均响应后才完成整个事务。&lt;/p&gt;
&lt;p&gt;CA是放弃了分区容忍性，不考虑网络不通或者节点挂掉的场景，&lt;strong&gt;系统将不是一个标准的分布式系统&lt;/strong&gt;；&lt;/p&gt;
&lt;h3 id="3-分布式事务base理论"&gt;3. 分布式事务BASE理论&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;B&lt;/strong&gt;asically &lt;strong&gt;A&lt;/strong&gt;vailable，&lt;strong&gt;S&lt;/strong&gt;oft state，&lt;strong&gt;E&lt;/strong&gt;ventually consistent，牺牲强一致性获得可用性，出现故障允许部分不可用但要保证核心功能可用，允许数据在一段时间是不一致的，这段时间不影响系统可用性，但最终达到一致性状态。通过放宽一致性要求，借助本地事务来实现最终分布式事务一致性的同时也保证了系统的吞吐量。&lt;/p&gt;
&lt;p&gt;基于Base的柔性事务往往分为两类：通知型事务（依赖于消息中间件），补偿型事务（TCC）。&lt;/p&gt;
&lt;h3 id="4-本地事务的acid特性"&gt;4. 本地事务的ACID特性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Atomic 原子性，整个事务过程中的所有操作，要么全部完成，要么全部不做，无中间状态，无部分成功。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于单个事务，原子性就能保证一致性；但是对于多个并发执行的事务，由于执行顺序，最终效果可能不同；&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consistency 一致性，保证多个节点中数据的一致性，所有的节点在任何时间数据都是一致的；&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;业务操作支持重试，不会产生不利影响，需要满足幂等性；&lt;/li&gt;
&lt;li&gt;强一致性，当更新操作完成后，任何多个线程访问都会返回最新的更新过后的数据；&lt;/li&gt;
&lt;li&gt;弱一致性，系统并不保证线程访问返回最新的更新过后的值；不承诺立即，也不承诺具体多长时间；&lt;/li&gt;
&lt;li&gt;最终一致性，弱一致性的特定形式，系统保证没有后续更新值前提下，系统最终返回上一次更新操作的值；期间不一致的主要因素主要有：&lt;strong&gt;通信延迟、系统负载、副本个数&lt;/strong&gt;等；&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Isolation 隔离性，多个事务之间往往是并发的，多个事务之间互相不干扰，一个事务不能看到其他事务的运行过程的中间状态；&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;每个事务都是有起止时间，每个事务的执行过程就是实现维度上的一个时间片段，多个时间片段上的并发交错，出现了不同的隔离性问题。数据库事务的隔离isolation级别：Read uncommitted，Read committed，Repeatable read，Serializable&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/06/27/ONbcMJS4ie6aUKA.jpg" alt="一张图说明事务隔离级别" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Durability 持久性，事务完成之后，该事务对数据的更改会被持久化到数据库，且不会被回滚。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="分布式事务解决方案"&gt;分布式事务解决方案&lt;/h2&gt;
&lt;h3 id="1-刚性事务-数据库事务"&gt;1. 刚性事务-数据库事务&lt;/h3&gt;
&lt;p&gt;数据库一般由两个文件组成，&lt;strong&gt;数据文件及日志文件&lt;/strong&gt;，往往日志文件比数据文件更大。对于任何数据库的写操作都是先写操作日志。
对于事务操作，数据库会先记录这个事务的redo日志，把日志文件写入磁盘，之后再开始操作数据库数据。即便在断电后操作尚未完成，重新启动时候会读取日志文件进行redo前滚或者是undo回滚，以保证数据的一致性；&lt;/p&gt;
&lt;h3 id="2-缓存最终一致性"&gt;2. 缓存最终一致性&lt;/h3&gt;
&lt;p&gt;现象：缓存用在数据库前面，作为数据读取缓存，使得I/O操作不直接落在数据库上。存在缓存数据与数据库数据不一致现象。&lt;/p&gt;
&lt;p&gt;解决方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;设置缓存过期时间，该时间即系统可以达到最终一致性的容忍时间；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;数据在数据库更新成功后，同时刷新缓存中的数据；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-两阶段提交-强一致性-2pc-2-phase-commit"&gt;3. 两阶段提交-强一致性 （2PC, 2 Phase Commit）&lt;/h3&gt;
&lt;p&gt;具有强一致性，是&lt;strong&gt;CP系统&lt;/strong&gt;的典型实现；通常两个角色，&lt;strong&gt;协调器&lt;/strong&gt;（事务管理器）及&lt;strong&gt;事务执行者&lt;/strong&gt;，协调器负责整个分布式系统的提交和回滚，事务执行者负责本地事务的提交和回滚。&lt;/p&gt;
&lt;p&gt;高并发场景涉及到性能问题，C系统需要等待多个资源，耗时较长。&lt;strong&gt;同步阻塞&lt;/strong&gt;，执行者在事务未提交之前会一直锁定其占有的本地资源对象。&lt;strong&gt;单点故障&lt;/strong&gt;，如果协调者出现故障后，所有的执行着会进入阻塞状态，导致本地被锁的资源无法被其他进程使用。&lt;strong&gt;数据不一致&lt;/strong&gt;，当doCommit消息发送后由于网路抖动导致部分事务执行者没有搜到消息而不提交事务，导致最终不一致。&lt;/p&gt;
&lt;p&gt;协调器的状态包括：init，preparing，committed，aborted&lt;/p&gt;
&lt;p&gt;事务执行者的状态包括：working，prepared，committed&lt;/p&gt;
&lt;p&gt;两个步骤：prepare极端、commit提交或rollback回滚阶段
















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/c962xoZInlCDR5r.png" alt="2PC" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;统一标准组织定义了分布式事务处理模型DTP（Distributed Transaction Processing Reference Model）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AP (Application Process) 应用程序，使用DTP分布式系统的程序&lt;/li&gt;
&lt;li&gt;RM (Resource Manager) 资源管理器，事务的参与者，资源管理器控制着&lt;strong&gt;分支事务&lt;/strong&gt;，负责本地事务的提交；&lt;/li&gt;
&lt;li&gt;TM (Transaction Manager) 事务管理器，负责协调和管理事务，控制着&lt;strong&gt;全局事务&lt;/strong&gt;，管理事务的生命周期，同时协调各个资源管理器。&lt;/li&gt;
&lt;li&gt;CRM (Communication Resource Manager) 通信资源管理器，控制一个TM域内或者跨TM域的分布式应用之间的通信。&lt;/li&gt;
&lt;li&gt;CP (Communication Protocol)，通信协议，提供分布式应用之间的底层通信服务。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个分布式事务即包含若干分支事务的全局事务，全局事务协调分支事务要么全部提交，要么全部回滚。&lt;/p&gt;
&lt;p&gt;DTP模型定义了TM和RM直接通讯接口的规范（叫XA），TM向AP提供应用程序编程接口，AP通过TM进行事务提交和回滚事务；TM通过XA接口来通知RM事务的开始、结束以及提交和回滚。&lt;/p&gt;
&lt;p&gt;对于2PC使用DTP来描述为：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;准备阶段&lt;/strong&gt;，RM执行实际的业务操作，但不提交事务，并且同时锁定资源。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;提交阶段&lt;/strong&gt;，TM接受RM在准备阶段的回复，任何一个RM失败，TM通知所有的RM执行回滚操作；否则，TM通知RM进行分支事务的提交。提交阶段结束后释放锁定资源。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="4-补偿模式-最终一致性tcc-try-confirm-cancel"&gt;4. 补偿模式-最终一致性（TCC, Try-Confirm-Cancel）&lt;/h3&gt;
&lt;p&gt;服务化的二阶段提交协议，要求分支事务实现三个操作：预处理Try，确认Confirm，撤销Cancel。预处理做业务检查和资源预留，确认做业务确认操作，撤销实现一个和确认完全相反的操作，回滚。TCC任务只要Confirm阶段或者Cancel阶段不会出错，只要Try成功，Confirm一定成功。若真出现失败，需要支持重试机制和人工处理介入。在事务链中的任何一个正向事务Confirm操作, 都必须存在一个完全符合回滚Cancel规则的可逆事务。&lt;/p&gt;
&lt;p&gt;如果涉及重试，则需要实现为幂等，对于同一个操作无论执行多少次结果均相同。&lt;/p&gt;
&lt;p&gt;TCC需要区分异常的处理机制，支持不同场景的异常处理：空回滚、幂等、悬挂。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;空回滚&lt;/strong&gt;：往往服务宕机和网络故障的时候，对于Try阶段就故障的时候，在故障恢复后，需要识别出是空回滚。依赖与全局事务的ID在分布式事务调用链的持久化。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;幂等&lt;/strong&gt;：确认/撤销操作的幂等性，确保不会重复使用或者重复释放资源。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;悬挂&lt;/strong&gt;：由于网络时延导致，第一阶段TM认为Try网络拥堵超时了，直接执行了第二阶段Cancel，但是第二阶段执行结束后，第一阶段Try才达到真正的执行者。&lt;/p&gt;
&lt;p&gt;解决方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务调用链关系需要记载；&lt;/li&gt;
&lt;li&gt;每个服务提供则需要额外提供一组业务逻辑相反操作，互为补偿；&lt;/li&gt;
&lt;li&gt;按失败的不同原因执行不同的回滚策略；&lt;/li&gt;
&lt;li&gt;针对各个资源分别进行锁定，分别提交与释放，各个服务之间异步并行执行；
















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/VHhoZcXJe4BDGU7.png" alt="tryconfirmcancel" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;实例（账户扣钱转账30，账户总额100）：&lt;/p&gt;
&lt;p&gt;Try准备阶段，做资源的检查和预留。当前总额是100，但是30已经被冻结，不能用于其他的事务；&lt;/p&gt;
&lt;p&gt;Confirm确认阶段，执行真正的扣钱。冻结的30扣除，账号余额为70；&lt;/p&gt;
&lt;p&gt;Cancel撤销阶段，释放冻结的30，使账号回到最初状态，余额100；&lt;/p&gt;
&lt;p&gt;2PC通常是在跨库的DB层面，TCC则在应用层面，需要通过业务逻辑来实现，对业务有侵入性。可以自行定义数据操作的粒度以降低锁冲突，提高吞吐量，但是侵入性强，每个分支事务均需要实现3个操作。按照网络状态、系统故障等不同的失败场景实现不同的回滚策略。&lt;/p&gt;
&lt;h3 id="5-三阶段提交-3pc"&gt;5. 三阶段提交 (3PC)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;CanCommit（事务询问）&lt;/p&gt;
&lt;p&gt;询问所有参与者是否可以执行事务的操作；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;PreCommit（事务执行）&lt;/p&gt;
&lt;p&gt;在事务询问都是okay的前提条件下，执行事务的操作；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DoCommit（事务提交）&lt;/p&gt;
&lt;p&gt;真正的事务提交；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;针对二阶段的缺陷，解决单点故障问题，减少阻塞；一旦参与者无法及时收到来自协调者的信息之后，会默认执行commit，而不会一直处于阻塞状态。这样会造成最终数据不一致。&lt;/p&gt;
&lt;p&gt;上述解决方案依据具体使用场景而灵活变化，需要适应业务需求。&lt;/p&gt;
&lt;h3 id="6-消息事务-最终一致性"&gt;6. 消息事务-最终一致性&lt;/h3&gt;
&lt;p&gt;基于消息中间件的二阶段提交，将本地事务以及发放消息放在一个分布式事务中。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;系统向消息系统中间发送预备消息；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;消息中间件保存预备消息并返回成功；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;执行本地事务；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;发送提交消息给消息中间件；&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1和2失败时候事务未执行；&lt;/p&gt;
&lt;p&gt;3失败时候，回滚预备消息；系统实现消息中间件的回调接口，失败则回滚。&lt;/p&gt;
&lt;p&gt;4失败时候，3步骤为成功，消息中间件能够检查到系统已经成功执行，消息中间件自行提交完成整个事务。&lt;/p&gt;
&lt;p&gt;对消息中间件要求较高，&lt;strong&gt;保障消息不丢失，消息不重复不乱序&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;针对投递Commit消息，接收订阅方存在三个问题：&lt;strong&gt;消息可能重复消费，消费者消费超时，消费失败&lt;/strong&gt;；&lt;/p&gt;
&lt;p&gt;针对第一个问题需要在消息消费方进行唯一标识识别，消费方对消息的状态进行保存，识别重复消息；&lt;/p&gt;
&lt;p&gt;针对第二个问题即重试即可，直至消息消费成功；&lt;/p&gt;
&lt;p&gt;针对第三个问题，消费失败如果由于系统bug导致，重试多次一样失败，如果此时需要回滚则有复杂的业务逻辑，最好的办法就是通过报警系统及时发现失败情况然后再人工处理。&lt;/p&gt;
&lt;p&gt;往往第三个问题都是致命异常，要&lt;strong&gt;打印详细的错误日志，并设计一个报警系统在后台实时扫描和分析此类日志&lt;/strong&gt;，检查出特殊情况并短信通知人工处理。
















&lt;figure  &gt;
  &lt;div class="d-flex justify-content-center"&gt;
    &lt;div class="w-100" &gt;&lt;img src="https://s2.loli.net/2022/05/15/JRSlC5YoI3HefEU.png" alt="messageTransaction" loading="lazy" data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;关键解决两个问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;本地事务与消息的发送的原子性问题。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;事务参与方接受消息的可靠性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可靠消息最终一致性适合执行周期长实时性要求低的系统，解耦了服务之间的依赖，同时基于消息的异步操作，避免了分布式事务中的同步阻塞问题。&lt;/p&gt;
&lt;h3 id="7-重要结论"&gt;7. 重要结论&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;如果业务场景需要强一致性, 那么尽量避免将它们放在不同服务中, 也就是尽量使用本地事务, 避免使用强一致性的分布式事务.&lt;/li&gt;
&lt;li&gt;如果业务场景能够接受最终一致性, 那么最好是使用基于消息的最终一致性的方案(异步确保型)来解决.&lt;/li&gt;
&lt;li&gt;如果业务场景需要强一致性, 并且只能够进行分布式服务部署, 那么最好是使用TCC（try-confirm-cancel）方案而不是2PC方案来解决.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;刚性事务：严格遵循&lt;strong&gt;ACID原则&lt;/strong&gt;的事务，如单机数据库事务；&lt;/p&gt;
&lt;p&gt;柔性事务：遵循&lt;strong&gt;BASE理论&lt;/strong&gt;的事务，实现方式：两阶段提交、TCC补偿提交、消息异步确保、最大努力通知型&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可见性，各个服务需要提供查询接口，来判断操作的处理情况。&lt;/li&gt;
&lt;li&gt;幂等性，可重复操作，调用多次返回的业务结果相同。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本地事务采用刚性事务，分布式事务采用柔性事务。&lt;/p&gt;
&lt;h2 id="mysql的事务"&gt;MySQL的事务&lt;/h2&gt;
&lt;p&gt;隐式事务和显示事务，mysql默认就是隐式事务模式，当insert，update，delete时，数据库自动开启事务、提交或回滚事务。由autocommit控制，可以由下述命令进行查询；&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;show&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;autocommit&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="1-事务的实现"&gt;1. 事务的实现&lt;/h3&gt;
&lt;p&gt;Mysql的Innodb存储引擎基于日志和锁来实现ACID，默认的事务隔离级别是Repeatable Read。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;通过数据库锁机制和MVCC，确保事务的隔离性；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过Redo Log重做日志，来保障事务的持久性；&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Redo Log是记录新数据的备份，事务提交前，将Redo Log持久化而不是数据持久化，当系统崩溃时，虽然数据没有持久化，但是Redo Log持久化，系统恢复后通过Redo Log恢复到崩溃之前的状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过Undo Log撤销日志，来保障事务的原子性和一致性；&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;操作任何数据之前，先将数据备份到Undo Log，然后进行数据的修改。对于数据的每行数据，可能会存在多个版本的数据。如果出现Rollback，利用Undo Log中的备份数据恢复到事务开始的状态；&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-事务的隔离"&gt;2. 事务的隔离&lt;/h3&gt;
&lt;p&gt;事务隔离级别主要是为了解决多个事务之间&lt;strong&gt;数据可见性及数据正确性&lt;/strong&gt;的问题。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;读未提交，Read Uncommitted&lt;/p&gt;
&lt;p&gt;可以读取到其他事务还未提交的数据，多次读取的结果不一致。出现脏读，不可重复读，幻读；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;读已提交，Read Committed&lt;/p&gt;
&lt;p&gt;无法读取到其他事务还未提交的数据，可以读取到其他事务已经提交的数据，多次读取结果不一致，不可重复读和幻读；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可重复读，Repeatable Read&lt;/p&gt;
&lt;p&gt;无法读取到其他事务已经提交的数据，多次读取的结果一致，可重复读；会出现幻读；当两个事务，数据库唯一索引，基于事务中查询后插入的场景。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;串行，Serializable&lt;/p&gt;
&lt;p&gt;让并发的事务串行化，多个事务之间读写，写读，写写会产生互斥，多个事务间读读不会产生互斥。不会出现脏读，不可重复读、读已提交和幻读。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="3-并发控制"&gt;3. 并发控制&lt;/h3&gt;
&lt;p&gt;mysql并发控制主要通过&lt;strong&gt;加锁&lt;/strong&gt;来实现。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;读锁 read lock，也叫共享锁share lock，多个读请求可以同时共享一把锁来读取数据而不会阻塞；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;写锁 write lock，也叫排他锁exclusive lock，写锁会排斥其他的所有获取锁的请求，一直阻塞直到数据写入；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;锁的粒度分为表锁和行锁&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表锁 table lock，锁定整张表，维护锁的开销最小但是降低了表的读写效率。一般alter table会进行表锁；&lt;/li&gt;
&lt;li&gt;行锁 row lock，最大程度的支持并发，数据库锁的维护开销大。行锁一般由各个引擎实现，而非mysql服务器层面实现；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MVCC版本管理，多版本并发控制，借此做到的读写分离，实现不加锁实现读写并行。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mysql innodb引擎通过在每行记录后保存两个列（创建时间和过期时间，逻辑时间的版本号），每开启一个新的事务，系统版本号会增长，事务开始的版本号会作为事务号，用来和查询的每行记录的版本号进行比较。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="spring事务管理"&gt;Spring事务管理&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;编程式事务管理&lt;/strong&gt;，通过TransactionTemplate或者TransactionManager手动管理事务；相关代码逻辑&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@Autowired&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;PlatformTransactionManager&lt;/span&gt; &lt;span class="n"&gt;transactionManager&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testTransaction&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;TransactionStatus&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transactionManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTransaction&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DefaultTransactionDefinition&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;          &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;               &lt;span class="c1"&gt;// ....  业务代码
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;              &lt;span class="n"&gt;transactionManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;          &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;              &lt;span class="n"&gt;transactionManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rollback&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;          &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;声明式事务管理&lt;/strong&gt;，通过AOP实现，基于@Transaction注解实现。如果@Transaction使用在类上，表明该注解对该类中的所有public方法均生效。如果同一个内中的方法调用了@Transanction标记的方法，则事务会失效，因为其依赖的AOP实现机制底层是动态代理，对于外部类调用时候才生效。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propagation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Propagation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;REQUIRED&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;aMethod&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="c1"&gt;//do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;  &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bMethod&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cMethod&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;spring事务框架在于接口的定义&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PlatformTransactionManager：平台事务管理器，事务策略的核心，事务的管理接口；&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.transaction&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.lang.Nullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PlatformTransactionManager&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;//获得事务
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="n"&gt;TransactionStatus&lt;/span&gt; &lt;span class="nf"&gt;getTransaction&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Nullable&lt;/span&gt; &lt;span class="n"&gt;TransactionDefinition&lt;/span&gt; &lt;span class="n"&gt;var1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="n"&gt;TransactionException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;//提交事务
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TransactionStatus&lt;/span&gt; &lt;span class="n"&gt;var1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="n"&gt;TransactionException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="c1"&gt;//回滚事务
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;rollback&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TransactionStatus&lt;/span&gt; &lt;span class="n"&gt;var1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="n"&gt;TransactionException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;TransactionDefinition：事务定义信息，包括&lt;strong&gt;事务的传播、隔离级别、超时、只读、回滚规则&lt;/strong&gt;等；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;TransactionStatus：事务运行状态，定义了一组方法用于获取事务相应状态信息；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;事务传播行为&lt;/strong&gt;，为了解决业务层方法之间互相调用的事务问题；当事务方法被另一个事务方法调用的时候，必须指定事务应该如何传播。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Class&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propagation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;aMethod&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;        &lt;span class="c1"&gt;//do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bMethod&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Class&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propagation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;bMethod&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;       &lt;span class="c1"&gt;//do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;TransactionDefinition.PROPAGATION_REQUIRED&lt;/code&gt;&lt;/strong&gt;，如果当前存在事务，则加入该事务；如果没有事务，则创建一个新的事务。
&lt;ul&gt;
&lt;li&gt;对于上述代码X和Y均为PROPAGATION_REQUIRED，只要aMethod或者bMethod任何方法回滚，整个事务就回滚；&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;TransactionDefinition.PROPAGATION_REQUIRES_NEW&lt;/code&gt;&lt;/strong&gt;，创建一个新的事务，如果当前事务存在则挂起。不管外部是否有事务，当前方法均会开始新的事物，且开启的事务相互独立，互不干扰。
&lt;ul&gt;
&lt;li&gt;对于上述代码，X为PROPAGATION_REQUIRED，Y为PROPAGATION_REQUIRED_NEW，aMethod的回滚不会导致bMethod的回滚，如果bMethod的方法回滚，&lt;strong&gt;且抛出了未被捕获的异常满足&lt;/strong&gt;aMethod回滚的规则，则aMethod也会回滚。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;TransactionDefinition.PROPAGATION_NESTED&lt;/code&gt;&lt;/strong&gt;，外部开启事务的条件是，内部开启开启新的事务，作为嵌套事务存在。如果外部不存在，则单独开启一个事务，效果同PROPAGATION_REQUIRED。
&lt;ul&gt;
&lt;li&gt;对于上述代码，X为PROPAGATION_REQUIRED，Y为PROPAGATION_NESTED，如果bMethod回滚后，aMethod也会跟着回滚。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;TransactionDefinition.PROPAGATION_MANDATORY&lt;/code&gt;&lt;/strong&gt;，如果当前存在事务，则加入该事务；如果没有事务，则直接抛出异常；使用场景较少；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;TransactionDefinition.PROPAGATION_SUPPORTS&lt;/code&gt;&lt;/strong&gt;，如果当前存在事务，则加入事务；如果没有事务，则按照非事务的方式继续运行；使用场景较少；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;TransactionDefinition.PROPAGATION_NOT_SUPPORTED&lt;/code&gt;&lt;/strong&gt;，以非事务的方式执行，如果当前存在事务，则把当前事务挂起；使用场景较少；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;TransactionDefinition.PROPAGATION_NEVER&lt;/code&gt;&lt;/strong&gt;，以非实物的方式执行，如果当前存在事务，则直接抛出异常；使用场景较少；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;事务超时行为&lt;/strong&gt;，一个事务所允许执行的最长时间，如果超过该时间限制但事务还没有完成，则自动回滚事务。默认值为-1，表示没有超时时间或者取决于底层事务系统；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;事务只读属性&lt;/strong&gt;，对于只有数据查询的事务，可以指定事务类型为read only，只读事务不涉及数据的修改，数据库会提供一些优化手段，适用于有多条数据查询的操作的方法中。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mysql默认对每个新建的连接使用autocommit模式，该模式下，每个发送到Mysql的服务器的sql都会在一个独立的事务中进行处理，事务处理后自动提交，然后开启一个新的事务。给方法加上@Transaction注解，该方法执行的sql会被放在一个事务中，如果是只读事务，mysql会去优化它的执行。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;事务回滚机制&lt;/strong&gt;，规则定义了哪些异常会导致事务回滚而哪些不会。默认情况下，事务遇到运行时异常和Error时才会回滚，对于受检异常时不会回滚。&lt;/p&gt;
</description>
</item>
<item>
<title>Example Project</title>
<link>https://liaolile.com/project/example/</link>
<pubDate>Wed, 27 Apr 2016 00:00:00 +0000</pubDate>
<guid>https://liaolile.com/project/example/</guid>
<description>&lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis posuere tellus ac convallis placerat. Proin tincidunt magna sed ex sollicitudin condimentum. Sed ac faucibus dolor, scelerisque sollicitudin nisi. Cras purus urna, suscipit quis sapien eu, pulvinar tempor diam. Quisque risus orci, mollis id ante sit amet, gravida egestas nisl. Sed ac tempus magna. Proin in dui enim. Donec condimentum, sem id dapibus fringilla, tellus enim condimentum arcu, nec volutpat est felis vel metus. Vestibulum sit amet erat at nulla eleifend gravida.&lt;/p&gt;
&lt;p&gt;Nullam vel molestie justo. Curabitur vitae efficitur leo. In hac habitasse platea dictumst. Sed pulvinar mauris dui, eget varius purus congue ac. Nulla euismod, lorem vel elementum dapibus, nunc justo porta mi, sed tempus est est vel tellus. Nam et enim eleifend, laoreet sem sit amet, elementum sem. Morbi ut leo congue, maximus velit ut, finibus arcu. In et libero cursus, rutrum risus non, molestie leo. Nullam congue quam et volutpat malesuada. Sed risus tortor, pulvinar et dictum nec, sodales non mi. Phasellus lacinia commodo laoreet. Nam mollis, erat in feugiat consectetur, purus eros egestas tellus, in auctor urna odio at nibh. Mauris imperdiet nisi ac magna convallis, at rhoncus ligula cursus.&lt;/p&gt;
&lt;p&gt;Cras aliquam rhoncus ipsum, in hendrerit nunc mattis vitae. Duis vitae efficitur metus, ac tempus leo. Cras nec fringilla lacus. Quisque sit amet risus at ipsum pharetra commodo. Sed aliquam mauris at consequat eleifend. Praesent porta, augue sed viverra bibendum, neque ante euismod ante, in vehicula justo lorem ac eros. Suspendisse augue libero, venenatis eget tincidunt ut, malesuada at lorem. Donec vitae bibendum arcu. Aenean maximus nulla non pretium iaculis. Quisque imperdiet, nulla in pulvinar aliquet, velit quam ultrices quam, sit amet fringilla leo sem vel nunc. Mauris in lacinia lacus.&lt;/p&gt;
&lt;p&gt;Suspendisse a tincidunt lacus. Curabitur at urna sagittis, dictum ante sit amet, euismod magna. Sed rutrum massa id tortor commodo, vitae elementum turpis tempus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean purus turpis, venenatis a ullamcorper nec, tincidunt et massa. Integer posuere quam rutrum arcu vehicula imperdiet. Mauris ullamcorper quam vitae purus congue, quis euismod magna eleifend. Vestibulum semper vel augue eget tincidunt. Fusce eget justo sodales, dapibus odio eu, ultrices lorem. Duis condimentum lorem id eros commodo, in facilisis mauris scelerisque. Morbi sed auctor leo. Nullam volutpat a lacus quis pharetra. Nulla congue rutrum magna a ornare.&lt;/p&gt;
&lt;p&gt;Aliquam in turpis accumsan, malesuada nibh ut, hendrerit justo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque sed erat nec justo posuere suscipit. Donec ut efficitur arcu, in malesuada neque. Nunc dignissim nisl massa, id vulputate nunc pretium nec. Quisque eget urna in risus suscipit ultricies. Pellentesque odio odio, tincidunt in eleifend sed, posuere a diam. Nam gravida nisl convallis semper elementum. Morbi vitae felis faucibus, vulputate orci placerat, aliquet nisi. Aliquam erat volutpat. Maecenas sagittis pulvinar purus, sed porta quam laoreet at.&lt;/p&gt;
</description>
</item>
<item>
<title>An example conference paper</title>
<link>https://liaolile.com/publication/example/</link>
<pubDate>Mon, 01 Jul 2013 00:00:00 +0000</pubDate>
<guid>https://liaolile.com/publication/example/</guid>
<description>&lt;div class="alert alert-note"&gt;
  &lt;div&gt;
    Click the &lt;em&gt;Cite&lt;/em&gt; button above to demo the feature to enable visitors to import publication metadata into their reference management software.
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class="alert alert-note"&gt;
  &lt;div&gt;
    Create your slides in Markdown - click the &lt;em&gt;Slides&lt;/em&gt; button to check out the example.
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Supplementary notes can be added here, including &lt;a href="https://wowchemy.com/docs/writing-markdown-latex/" target="_blank" rel="noopener"&gt;code, math, and images&lt;/a&gt;.&lt;/p&gt;
</description>
</item>
<item>
<title/>
<link>https://liaolile.com/admin/config.yml</link>
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
<guid>https://liaolile.com/admin/config.yml</guid>
<description/>
</item>
</channel>
</rss>