diff options
| author | muqiuhan <[email protected]> | 2025-03-19 13:09:14 +0000 |
|---|---|---|
| committer | muqiuhan <[email protected]> | 2025-03-19 13:09:14 +0000 |
| commit | d9290e497208af1b1338bee09f47a71e9c9180c1 (patch) | |
| tree | 46db0224ee0698464540ccc937d399a2048e5833 /search.xml | |
| parent | 2bd8b00477ef001199c399d8bc0111314fec08cc (diff) | |
| download | blog-d9290e497208af1b1338bee09f47a71e9c9180c1.tar.gz | |
deploy: bc22b4eaeb6005d9af7f32e09dbb1829a24ceddf
Diffstat (limited to 'search.xml')
| -rw-r--r-- | search.xml | 63 |
1 files changed, 55 insertions, 8 deletions
@@ -3041,7 +3041,7 @@ <h3 id="体态"><a href="#体态" class="headerlink" title="体态"></a>体态</h3><p>遇急重发热患者,应首先测呼吸、脉搏、血压等重要生命体征,并快速进行全面的体格检查,重点检查皮肤、黏膜有无皮疹、淤点以及肝、脾、淋巴结肿大等。发热伴有中毒性休克时,患者面色青灰,脉细速,血压下降或测不出,见于休克型肺炎、暴发性流行性脑脊髓膜炎、中毒性菌痢、脓毒症、流行性出血热等。</p> <h4 id="面容"><a href="#面容" class="headerlink" title="面容"></a>面容</h4><p>一般急性感染多呈急热面容。伤寒、副伤寒者常表情淡漠,即所谓“伤寒面容”。斑疹伤寒、恙虫病、流行性出血热患者常呈醉酒样面容。猩红热患者见口周苍白。麻疹患者常见眼睑水肿、结膜充血、分泌物增多等。急性白血病、再生障碍性贫血和恶性组织细胞病常因贫血亦可呈面色苍白。发热伴面部蝶形红斑是播散性红斑狼疮的特殊病症。口唇疱疹可见于大叶性肺炎、间日疟、流行性脑脊髓膜炎、流行性感冒、大肠杆菌败血症等。</p> <h4 id="皮肤特征"><a href="#皮肤特征" class="headerlink" title="皮肤特征"></a>皮肤特征</h4><p>注意有无皮疹及出血点。皮肤多汗可见于结核病、风湿热、败血症、恶性淋巴瘤。皮肤发疹可见于猩红热、麻疹、风疹、斑疹伤寒、伤寒、水痘、恙虫病、传染性单核细胞增多症、丹毒、红斑狼疮、急性皮肌炎等,根据其特征性皮疹及出疹日期可对急性发疹性传染病作出诊断:</p> -<p><img src="/img/%E6%A0%B9%E6%8D%AE%E7%89%B9%E5%BE%81%E6%80%A7%E7%9A%AE%E7%96%B9%E5%8F%8A%E5%87%BA%E7%96%B9%E6%97%A5%E6%9C%9F%E5%AF%B9%E6%80%A5%E6%80%A7%E5%8F%91%E7%96%B9%E6%80%A7%E4%BC%A0%E6%9F%93%E7%97%85%E4%BD%9C%E5%87%BA%E8%AF%8A%E6%96%AD.png" alt="根据特征性皮疹及出疹日期对急性发疹性传染病作出诊断.png"></p> +<p><img src="/img/%E5%8C%BB%E5%AD%A6/%E6%A0%B9%E6%8D%AE%E7%89%B9%E5%BE%81%E6%80%A7%E7%9A%AE%E7%96%B9%E5%8F%8A%E5%87%BA%E7%96%B9%E6%97%A5%E6%9C%9F%E5%AF%B9%E6%80%A5%E6%80%A7%E5%8F%91%E7%96%B9%E6%80%A7%E4%BC%A0%E6%9F%93%E7%97%85%E4%BD%9C%E5%87%BA%E8%AF%8A%E6%96%AD.png" alt="根据特征性皮疹及出疹日期对急性发疹性传染病作出诊断.png"></p> <p>注意有无皮疹及出血点。皮肤多汗可见于结核病、风湿热、败血症、恶性淋巴瘤。皮肤发疹可见于猩红热、麻疹、风疹、斑疹伤寒、伤寒、水痘、恙虫病、传染性单核细胞增多症、丹毒、红斑狼疮、急性皮肌炎等,根据其特征性皮疹及出疹日期可对急性发疹性传染病作出诊断。</p> <h4 id="淋巴结肿大"><a href="#淋巴结肿大" class="headerlink" title="淋巴结肿大"></a>淋巴结肿大</h4><p>注意有无皮疹及出血点。皮肤多汗可见于结核病、风湿热、败血症、恶性淋巴瘤。皮肤发疹可见于猩红热、麻疹、风疹、斑疹伤寒、伤寒、水痘、恙虫病、传染性单核细胞增多症、丹毒、红斑狼疮、急性皮肌炎等,根据其特征性皮疹及出疹日期可对急性发疹性传染病作出诊断</p> <h4 id="脾大"><a href="#脾大" class="headerlink" title="脾大"></a>脾大</h4><p>注意有无皮疹及出血点。皮肤多汗可见于结核病、风湿热、败血症、恶性淋巴瘤。皮肤发疹可见于猩红热、麻疹、风疹、斑疹伤寒、伤寒、水痘、恙虫病、传染性单核细胞增多症、丹毒、红斑狼疮、急性皮肌炎等,根据其特征性皮疹及出疹日期可对急性发疹性传染病作出诊断。</p> @@ -3166,7 +3166,7 @@ <entry> <title>奥司他韦</title> <url>/2023/03/05/%E5%A5%A5%E5%8F%B8%E4%BB%96%E9%9F%A6/</url> - <content><![CDATA[<p><img src="/img/%E5%A5%A5%E5%8F%B8%E4%BB%96%E9%9F%A6.jpg" alt="奥司他韦.jpg"></p> + <content><![CDATA[<p><img src="/img/%E5%8C%BB%E5%AD%A6/%E5%A5%A5%E5%8F%B8%E4%BB%96%E9%9F%A6.jpg" alt="奥司他韦.jpg"></p> <p>目前市场上销售的达菲为罗氏制药独家生产的抗流感药物,其通用名称为磷酸奥司他韦(Oseltamivirphosphate)。奥司他韦(Oseltamivir)于1999年在瑞士上市,2001年10月在我国上市。达菲是一种非常有效的流感治疗用药,并且可以大大减少并发症(主要是气管与支气管炎、肺炎、咽炎等)的发生和抗生素的使用,因而是目前治疗流感的最常用药物之一,也是公认的抗禽流感、甲型H1N1病毒最有效的药物之一。 </p> <h2 id="主要原理"><a href="#主要原理" class="headerlink" title="主要原理"></a>主要原理</h2><p>奥司他韦口服后经肝脏和肠道酯酶迅速催化转化为其活性代谢物奥司他韦羧酸,奥司他韦羧酸的构型与神经氨酸的过渡态相似,能够竞争性地与流感病毒神经氨酸酶(NA,neu-raminidase,也有称作神经氨酸苷酶)的活动位点结合,因而是一种强效的高选择性的流感病毒NA抑制剂(NAIs),它主要通过干扰病毒从被感染的宿主细胞中释放,从而减少甲型或乙型流感病毒的传播。 </p> <h2 id="特殊人群"><a href="#特殊人群" class="headerlink" title="特殊人群"></a>特殊人群</h2><ol> @@ -3530,7 +3530,7 @@ <entry> <title>气胸</title> <url>/2023/03/01/%E6%B0%94%E8%83%B8/</url> - <content><![CDATA[<p><img src="/img/%E6%B0%94%E8%83%B8.jpg" alt="气胸.jpg"></p> + <content><![CDATA[<p><img src="/img/%E5%8C%BB%E5%AD%A6/%E6%B0%94%E8%83%B8/%E6%B0%94%E8%83%B8.jpg" alt="气胸.jpg"></p> <p>这个病多见于瘦高的年轻男性,一般感觉起来就是:</p> <ol> <li>胸腔有刺痛感,针刺的感觉,想想那种拿小针针撮你小胸胸的感觉。</li> @@ -3538,7 +3538,7 @@ <li>呼吸困难,就像有人捂住你的口鼻,有点窒息的感觉。</li> </ol> <p>通俗来讲造成这种感觉的原因是肺泡破裂,肺漏气了。然后气体在胸腔里聚集就压缩了肺。</p> -<p><img src="/img/%E6%B0%94%E8%83%B82.jpeg" alt="气胸2.jpeg"><br>图中是一位右侧气胸患者(图中右面)的电脑断层扫描影像。在胸腔的边缘有着引流管,而图中黑色一片就是邻近于肺膜间(黑)和肋骨(白)的内腔。心脏则在图中央。医学专科胸腔医学、胸腔外科学症状胸痛、呼吸困难、疲劳常见始发于突发性肇因未知、创伤风险因子慢性阻塞性肺病(COPD)、结核病、抽烟诊断方法胸部X光、超声波、电脑断层扫描相似疾病或共病肺部大疱、血胸预防禁烟或戒烟治疗保守治疗、空针穿刺、胸管置放、肋膜黏连术盛行率约每10万人中20例外伤性气胸。</p> +<p><img src="/img/%E5%8C%BB%E5%AD%A6/%E6%B0%94%E8%83%B8/%E6%B0%94%E8%83%B82.jpeg" alt="气胸2.jpeg"><br>图中是一位右侧气胸患者(图中右面)的电脑断层扫描影像。在胸腔的边缘有着引流管,而图中黑色一片就是邻近于肺膜间(黑)和肋骨(白)的内腔。心脏则在图中央。医学专科胸腔医学、胸腔外科学症状胸痛、呼吸困难、疲劳常见始发于突发性肇因未知、创伤风险因子慢性阻塞性肺病(COPD)、结核病、抽烟诊断方法胸部X光、超声波、电脑断层扫描相似疾病或共病肺部大疱、血胸预防禁烟或戒烟治疗保守治疗、空针穿刺、胸管置放、肋膜黏连术盛行率约每10万人中20例外伤性气胸。</p> <h2 id="临床表现"><a href="#临床表现" class="headerlink" title="临床表现"></a>临床表现</h2><p>在医学上的临床表现中,气胸具有如下症状:<br>患者常有持重物、屏气、剧烈运动等诱发因素,但也有在睡眠中发生气胸者,病人突感一侧胸痛、气急、憋气,可有咳嗽、但痰少,小量闭合性气胸先有气急,但数小时后逐渐平稳,X线也不一定能显示肺压缩。若积气量较大者或者原来已有广泛肺部疾患,病人常不能平卧。如果侧卧,则被迫使气胸患侧在上,以减轻气急。病人呼吸困难程度与积气量的多寡以及原来肺内病变范围有关。当有胸膜粘连和肺功能减损时,即使小量局限性气胸也可能明显胸痛和气急。</p> <h2 id="初步诊断方式"><a href="#初步诊断方式" class="headerlink" title="初步诊断方式"></a>初步诊断方式</h2><p>突发一侧胸痛,伴有呼吸困难并有气胸体征,即可作出初步诊断。X线显示气胸征是确诊依据。在无条件或病情危重不允许作X线检查时,可在患侧胸腔积气体征最明确处试穿,抽气测压,若为正压且抽出气体,说明有气胸存在,即应抽出气体以缓解症状,并观察抽气后胸腔内压力的变化以判断气胸类型。在原有严重哮喘或肺气肿基础上并发气胸时,气急、胸闷等症状有时不易觉察,要与原先症状仔细比较。 </p> <h2 id="类似病症需要区别开来"><a href="#类似病症需要区别开来" class="headerlink" title="类似病症需要区别开来"></a>类似病症需要区别开来</h2><ol> @@ -3584,11 +3584,11 @@ <title>灯笼草</title> <url>/2023/06/22/%E7%81%AF%E7%AC%BC%E8%8D%89/</url> <content><![CDATA[<p>今天在菜园子里看到了野生的灯笼草,都结果了:</p> -<p><img src="/img/%E7%81%AF%E7%AC%BC%E8%8D%89.jpg"></p> +<p><img src="/img/%E7%94%9F%E6%B4%BB/%E7%81%AF%E7%AC%BC%E8%8D%89.jpg"></p> <p>灯笼果别名为小果酸浆、秘鲁苦蘵、打头泡、灯笼草等,茄科酸浆属多年生草本植物。<br>灯笼果茎直立,叶较厚,阔卵形或心脏形,两面密生柔毛;花单独腋生,花萼阔钟状,花冠阔钟状,黄色而喉部有紫色斑纹,花丝及花药蓝紫色,花药长约3毫米。果萼薄纸质,淡绿色或淡黄色,浆果成熟时黄色,种子黄色,圆盘状,夏季开花结果。生于田间、路旁、村边。我国南北各地均有分市。</p> <p><strong>不要与<a href="https://en.wikipedia.org/wiki/Gooseberry">醋栗</a>混淆</strong></p> <p>醋栗长这样:</p> -<p><img src="/img/%E9%86%8B%E6%A0%97.jpg"></p> +<p><img src="/img/%E7%94%9F%E6%B4%BB/%E9%86%8B%E6%A0%97.jpg"></p> <hr> <h2 id="性味"><a href="#性味" class="headerlink" title="性味"></a>性味</h2><ul> <li><p>《陆川本草》:”甘淡,微寒。”</p> @@ -3869,7 +3869,7 @@ <entry> <title>肝功能检查化验单阅读指南</title> <url>/2023/10/13/%E8%82%9D%E5%8A%9F%E8%83%BD%E6%A3%80%E6%9F%A5%E5%8C%96%E9%AA%8C%E5%8D%95/</url> - <content><![CDATA[<p><img src="/img/%E8%82%9D%E5%8A%9F%E8%83%BD%E6%A3%80%E6%9F%A5%E5%8C%96%E9%AA%8C%E5%8D%95Demo.jpeg"></p> + <content><![CDATA[<p><img src="/img/%E5%8C%BB%E5%AD%A6/%E8%82%9D%E5%8A%9F%E8%83%BD%E6%A3%80%E6%9F%A5%E5%8C%96%E9%AA%8C%E5%8D%95Demo.jpeg"></p> <ul> <li><p>谷丙转氨酶 (ALT)</p> <ul> @@ -4132,7 +4132,7 @@ <title>血常规化验结果阅读指南</title> <url>/2023/10/12/%E8%A1%80%E5%B8%B8%E8%A7%84%E5%8C%96%E9%AA%8C%E7%BB%93%E6%9E%9C%E9%98%85%E8%AF%BB%E6%8C%87%E5%8D%97/</url> <content><![CDATA[<p>这里我给出一些常见的值,更详细的听医生说哦,我们以下图为例:</p> -<p><img src="/img/%E8%A1%80%E5%B8%B8%E8%A7%84%E5%8C%96%E9%AA%8C%E5%8D%95Demo.jpeg" alt="血常规化验单Demo"></p> +<p><img src="/img/%E5%8C%BB%E5%AD%A6/%E8%A1%80%E5%B8%B8%E8%A7%84%E5%8C%96%E9%AA%8C%E5%8D%95Demo.jpeg" alt="血常规化验单Demo"></p> <ul> <li>红细胞 (RBC)<ul> <li>正常情况: 男性 <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="20.587ex" height="2.52ex" role="img" focusable="false" viewBox="0 -864 9099.6 1114"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path></g><g data-mml-node="mn" transform="translate(389,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(778,0)"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(1278,0)"></path></g><g data-mml-node="mo" transform="translate(2389.2,0)"><path data-c="B1" d="M56 320T56 333T70 353H369V502Q369 651 371 655Q376 666 388 666Q402 666 405 654T409 596V500V353H707Q722 345 722 333Q722 320 707 313H409V40H707Q722 32 722 20T707 0H70Q56 7 56 20T70 40H369V313H70Q56 320 56 333Z"></path></g><g data-mml-node="mn" transform="translate(3389.4,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(778,0)"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(1278,0)"></path></g><g data-mml-node="mo" transform="translate(5167.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path></g><g data-mml-node="mi" transform="translate(5556.4,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z"></path></g><g data-mml-node="msup" transform="translate(6128.4,0)"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)"></path></g><g data-mml-node="TeXAtom" transform="translate(1033,393.1) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)"></path></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(7918.6,0)"><g data-mml-node="mo"><path data-c="2F" d="M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z"></path></g></g><g data-mml-node="mi" transform="translate(8418.6,0)"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z"></path></g></g></g></svg></mjx-container> , 女性 <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="20.587ex" height="2.52ex" role="img" focusable="false" viewBox="0 -864 9099.6 1114"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path></g><g data-mml-node="mn" transform="translate(389,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(778,0)"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(1278,0)"></path></g><g data-mml-node="mo" transform="translate(2389.2,0)"><path data-c="B1" d="M56 320T56 333T70 353H369V502Q369 651 371 655Q376 666 388 666Q402 666 405 654T409 596V500V353H707Q722 345 722 333Q722 320 707 313H409V40H707Q722 32 722 20T707 0H70Q56 7 56 20T70 40H369V313H70Q56 320 56 333Z"></path></g><g data-mml-node="mn" transform="translate(3389.4,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(778,0)"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(1278,0)"></path></g><g data-mml-node="mo" transform="translate(5167.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path></g><g data-mml-node="mi" transform="translate(5556.4,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z"></path></g><g data-mml-node="msup" transform="translate(6128.4,0)"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)"></path></g><g data-mml-node="TeXAtom" transform="translate(1033,393.1) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)"></path></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(7918.6,0)"><g data-mml-node="mo"><path data-c="2F" d="M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z"></path></g></g><g data-mml-node="mi" transform="translate(8418.6,0)"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z"></path></g></g></g></svg></mjx-container></li> @@ -5548,6 +5548,53 @@ </tags> </entry> <entry> + <title>领域驱动设计中聚合根持久化和事件发布可能导致数据不一致问题</title> + <url>/2025/03/19/%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1%E4%B8%AD%E8%81%9A%E5%90%88%E6%A0%B9%E6%8C%81%E4%B9%85%E5%8C%96%E5%92%8C%E4%BA%8B%E4%BB%B6%E5%8F%91%E5%B8%83%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E6%95%B0%E6%8D%AE%E4%B8%8D%E4%B8%80%E8%87%B4%E9%97%AE%E9%A2%98/</url> + <content><![CDATA[<p>使用领域事件的一种直接做法是:在 <strong>应用服务</strong> (Application Service) 中产生事件并发布出去。例如,对于“用户昵称更新”的场景来讲,对应的应用服务 <code>UserCommandService</code> 实现如下:</p> +<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">member</span> <span class="keyword">public</span> this.UpdateMyName (command<span class="operator">:</span> UpdateUsernameCommand) (user<span class="operator">:</span> User) <span class="operator">=</span></span><br><span class="line"> <span class="keyword">let</span> user <span class="operator">=</span> userRepository.GetById user.Id</span><br><span class="line"> <span class="keyword">let</span> oldName <span class="operator">=</span> user.Username</span><br><span class="line"> <span class="keyword">let</span> newName <span class="operator">=</span> command.Username</span><br><span class="line"></span><br><span class="line"> user.UpdateUsername newName</span><br><span class="line"> <span class="operator">|></span> userRepository.Save</span><br><span class="line"> </span><br><span class="line"> UsernameChangeEvent (user.Id, newName, oldName) </span><br><span class="line"> <span class="operator">|></span> eventPublisher.Publish</span><br></pre></td></tr></table></figure> + +<p>这里,在更新了用户姓名之后,即刻调用事件发布器 <code>eventPublisher.Publish</code> 将事件发送到消息队列中。虽然这种方式比较流行,但它至少存在两个问题:</p> +<ol> +<li>领域事件本应属于领域模型的一部分,也即应该从领域模型中产生,而这里却在应用服务中产生</li> +<li>对聚合根(本例中的 <code>User</code> )的持久化和对事件的发布可能导致数据不一致问题。</li> +</ol> +<p>对于第1个问题,可以采用“从领域模型中返回领域事件”的方式:</p> +<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">member</span> <span class="keyword">public</span> this.UpdateMyName (command<span class="operator">:</span> UpdateUsernameCommand) (user<span class="operator">:</span> User) <span class="operator">=</span></span><br><span class="line"> <span class="keyword">let</span> user <span class="operator">=</span> userRepository.GetById user.Id</span><br><span class="line"> <span class="keyword">let</span> oldName <span class="operator">=</span> user.Username</span><br><span class="line"> <span class="keyword">let</span> newName <span class="operator">=</span> command.Username</span><br><span class="line"></span><br><span class="line"> user.UpdateUsername newName <span class="comment">// UpdateUsername 中构建 UsernameChangeEvent</span></span><br><span class="line"> <span class="operator">|></span> <span class="keyword">fun</span> user event <span class="operator">-></span> </span><br><span class="line"> userRepository.Save user</span><br><span class="line"> eventPublisher.Publish event</span><br></pre></td></tr></table></figure> + +<p>这种方式保证了领域事件是从领域模型中产生,但仍然存在第二个问题。</p> +<p>第二个问题中所谓的“数据一致性”,表示的是将聚合根保存到数据库和将领域事件发布到消息队列之间的一致性。由于数据库和消息队列属于异构的数据源,要保证他们之间的数据一致性需要引入分布式事务。</p> +<p>但是分布式事务通常是比较重量级的,再加上当下的诸多常见消息队列均不支持分布式事务(比如Kafka),因此并不建议使用分布式事务来解决这个问题。</p> +<p><a href="https://microservices.io/patterns/data/transactional-outbox.html">Transactional Outbox</a> 便是一种方案,概括来说,这种方式将一个分布式事务的问题拆解为多个本地事务,并采用“至少一次投递(At Least Once Delivery)”原则保证消息的发布。具体来讲,发布方在与业务数据相同的数据库中为领域事件创建相应的事件发布表(Outbox table),然后在保存业务数据的同时将所产生的事件保存到事件发布表中,由于此时二者都属于同一个数据库的本地事务所管辖,因此保证了“业务操作”与“事件产生”之间的一致性。此时的代码变成了:</p> +<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">member</span> <span class="keyword">public</span> this.UpdateMyName (command<span class="operator">:</span> UpdateUsernameCommand) (user<span class="operator">:</span> User) <span class="operator">=</span></span><br><span class="line"> <span class="keyword">let</span> user <span class="operator">=</span> userRepository.GetById user.Id</span><br><span class="line"> <span class="keyword">let</span> oldName <span class="operator">=</span> user.Username</span><br><span class="line"> <span class="keyword">let</span> newName <span class="operator">=</span> command.Username</span><br><span class="line"></span><br><span class="line"> user.UpdateUsername newName <span class="comment">// UpdateUsername 中构建 UsernameChangeEvent</span></span><br><span class="line"> <span class="operator">|></span> <span class="keyword">fun</span> user event <span class="operator">-></span> </span><br><span class="line"> userRepository.Save user</span><br><span class="line"> eventStore.Save event <span class="comment">// 这儿用 eventStore 代替 eventPublisher 啦</span></span><br></pre></td></tr></table></figure> + +<p>应用服务不再将事件直接发布出去,而是将事件保存到数据库中,之后,另一个模块将从数据库中读取事件并发布。</p> +<p>然而,这种方式依然有个缺点:每个需要产生领域事件的场景都需要应用服务先后调用<code>repository.Save()</code>和<code>eventStore.Save()</code>,导致了代码重复。解决方法也很简单——在聚合根中临时保存领域事件,然后在资源库中同时保存聚合根和领域事件到数据库。</p> +<p>在这种方式下,首先需要在聚合根的基类中完成与领域事件相关的各种设施,包括创建临时性的事件容器<code>events</code>以及通用的事件产生方法<code>RaiseEvent()</code>:</p> +<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="meta">[<AbstractClass>]</span></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">IAggregateRoot</span> <span class="operator">=</span> </span><br><span class="line"> <span class="operator">...</span></span><br><span class="line"> <span class="keyword">let</span> events <span class="operator">=</span> Collections.Generic.List<span class="operator"><</span>DomainEvent<span class="operator">></span> ()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">member</span> <span class="keyword">private</span> this.RaiseEvent (event<span class="operator">:</span> DomainEvent) <span class="operator">=</span></span><br><span class="line"> events.Add event</span><br><span class="line"> </span><br><span class="line"> <span class="operator">...</span></span><br></pre></td></tr></table></figure> + +<p>在聚合根基类<code>AggregateRoot</code>中,<code>events</code>字段用于临时保存聚合根中所产生的所有事件,各实际的聚合根类通过调用<code>RaiseEvent()</code>向<code>events</code>中添加事件。比如,对于“用户修改昵称”而言,<code>User</code>实现如下:</p> +<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">member</span> <span class="keyword">public</span> this.UpdateUsername (name<span class="operator">:</span> <span class="type">string</span>, user<span class="operator">:</span> User) <span class="operator">=</span></span><br><span class="line"> <span class="keyword">if</span> this.Username <span class="operator">=</span> name <span class="keyword">then</span></span><br><span class="line"> ()</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">let</span> oldName <span class="operator">=</span> this.Username</span><br><span class="line"> this.Username <span class="operator"><-</span> name</span><br><span class="line"> UsernameChangeEvent (user.Id, name, oldName) </span><br><span class="line"> <span class="operator">|></span> this.RaiseEvent</span><br></pre></td></tr></table></figure> + +<p>这里,聚合根 <code>User</code> 不再返回领域事件,而是将领域事件通过<code>AggregateRoot.RaiseEvent()</code>暂时性地保存到自身的<code>events</code>中。之后在保存<code>User</code>时,资源库的公共基类<code>BaseRepository</code>的<code>Save()</code>方法同时完成对聚合根和领域事件的持久化:</p> +<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">member</span> <span class="keyword">public</span> this.Save<span class="operator"><</span>AR<span class="operator">:</span> <span class="keyword">when</span> AR <span class="operator">:></span> AggrateRoot<span class="operator">></span> (it<span class="operator">:</span> AR) <span class="operator">=</span></span><br><span class="line"> <span class="keyword">match</span> it <span class="keyword">with</span></span><br><span class="line"> <span class="operator">|</span> <span class="literal">null</span> <span class="operator">-></span> <span class="built_in">failwith</span> <span class="string">"..."</span></span><br><span class="line"> <span class="operator">|</span> it <span class="keyword">when</span> it.Events <span class="operator">|></span> isEmpty <span class="operator">|></span> <span class="built_in">not</span> <span class="operator">-></span> </span><br><span class="line"> this.SaveEvents it.Events</span><br><span class="line"> this.CleanEvents ()</span><br><span class="line"> <span class="operator">|</span> _ <span class="operator">-></span> ()</span><br><span class="line"></span><br><span class="line"> db.Save it</span><br></pre></td></tr></table></figure> + +<p>在<code>Save()</code>方法中,首先获取到聚合根中的所有领域事件,然后通过<code>SaveEvents()</code>方法将它们保存到发布事件表中,最后通过<code>db.Save it</code>保存聚合根。需要注意的是,在这种方式下,<code>AggregateRoot</code>中的<code>events</code>字段是不能被持久化的,因为需要保证每次从数据库中加载出聚合根时<code>events</code>都是空的,为此在<code>SaveEvents()</code>保存了领域事件后,立即调用<code>it.clearEvents()</code>将所有的领域事件清空掉,以免领域事件随着聚合根一道被持久化到数据库中。</p> +<p>到目前为止,对领域事件的处理都还没有涉及到与任何消息中间件相关的内容,也即事件的产生是一个完全独立于消息队列的关注点,此时不用关心领域事件之后将以何种形式发布出去,Kafka 也好,RabbitMQ 也罢。除了关注点分离的好处外,这种解耦也使得系统在有可能切换消息中间件时更加的简单。</p> +<p>对于“在应用服务中通过<code>eventPublisher.Publish()</code>直接发布事件”而言,事件的产生和发布是同时完成的;但是对于“在聚合根中临时性保存领域事件”的方式来说,它只解决了事件的产生问题,并未解决事件的发布问题,事件的发布方应该采用“发射后不管(Fire And Forget)”的原则,即发布方无需了解消费方是如何处理领域事件的,甚至都不需要知道事件被哪些消费方所消费。</p> +<p>但是因为发送事件需要操作消息中间件,而更新事件状态需要操作数据库。在不使用分布式事务的情况下,此时的代码对于“事件发布成功 + 数据库落库成功”来讲是皆大欢喜的,但是依然无法排除有很小的概率导致事件发送成功了但是状态却为得到更新的情况。要解决这个问题,有一个选择是做妥协,即事件发布方无法保证事件的“<a href="https://www.cloudcomputingpatterns.org/exactly_once_delivery/">精确一次性投递(Exactly Once)</a>”,而是保证“<a href="https://www.cloudcomputingpatterns.org/at_least_once_delivery/">至少一次投递(At Least Once)</a>”。假设在事件发布成功之后,由于种种原因导致事件的状态未得到更新,即依然为<code>CREATED</code>状态,那么稍后,当事件兜底机制启动时,它将加载系统中尚未发布的事件进行发布,其中就包含状态为<code>CREATED</code>的事件,进而导致事件的重复投递。</p> +<p>“至少一次投递”将更多的负担转嫁给了事件的消费方,使得事件发送方得以全身而退。</p> +<p>事件消费的重点在于如何解决发布方的“至少一次投递”问题。举个例子,假设在电商系统中,订单子系统发布了“订单已成交”(<code>OrderPlacedEvent</code>)事件,积分子系统消费这个事件时会给用户新增与订单价格等额的积分,但是对事件的“至少一次投递”有可能导致该事件被重复投递进而导致重复给用户积分的情况产生。解决这个问题通常有2种方式:</p> +<ol> +<li>将消费方自身的处理逻辑设计为幂等的,即多次执行和一次执行的结果是相同的</li> +<li>消费方在数据库中建立一个事件消费表,用于跟踪已经被消费的事件</li> +</ol> +<p>第一种方式是最理想的,消费方不用引入额外的支撑性机制,但是这种方式对消费方的要求太高,并不是所有场景都能将消费方本身的处理逻辑设计为幂等。因此,实践中主要采用第二种方式。</p> +]]></content> + <tags> + <tag>Techinique</tag> + </tags> + </entry> + <entry> <title>关于</title> <url>/about.html</url> <content><