【MQ】鏡像隊(duì)列


title: 【MQ】鏡像隊(duì)列
date: 2017-12-08 21:57:51
tags: MQ
categories: MQ


前面提到持久化和消息確認(rèn)可以確保消息的可靠,但在默認(rèn)情況下 MQ 的可靠性完全沒(méi)有保障毁习,通過(guò)集群的方式確保服務(wù)的可靠往往是高可用的第一步。本文記錄一下 Rabbit MQ 的集群和鏡像俏险。

集群

集群能夠帶來(lái)的好處主要有兩點(diǎn):

  1. 允許消費(fèi)者和生產(chǎn)者在 Rabbit MQ 節(jié)點(diǎn)崩潰的情況下繼續(xù)運(yùn)行
  2. 通過(guò)添加更多節(jié)點(diǎn)線性的擴(kuò)展消息通信吞吐量

模式

在介紹集群之前先看看從單節(jié)點(diǎn)到集群的模式異同:

  • 相同:任何模式下節(jié)點(diǎn)內(nèi)部都需要維護(hù)基本元數(shù)據(jù)信息:隊(duì)列元數(shù)據(jù)仇轻、交換器元數(shù)據(jù)、綁定元數(shù)據(jù)焦人、vhost 元數(shù)據(jù)挥吵。不同模式

  • 差異:

    • 單一節(jié)點(diǎn)模式:

      默認(rèn)基本元數(shù)據(jù)信息存儲(chǔ)在內(nèi)存,被標(biāo)記持久化的隊(duì)列和交換器已經(jīng)它們的綁定存儲(chǔ)到磁盤

    • 普通集群模式

      cluster.PNG
      cluster.PNG

      除了基本元數(shù)據(jù)花椭,還有集群相關(guān)元數(shù)據(jù)忽匈。與單一節(jié)點(diǎn)模式的不同主要在集群對(duì)隊(duì)列,交換器矿辽,數(shù)據(jù)存儲(chǔ)的差異丹允。

      隊(duì)列:只會(huì)在單個(gè)節(jié)點(diǎn)而不是所有節(jié)點(diǎn)上創(chuàng)建完整隊(duì)列信息郭厌,其余節(jié)點(diǎn)只保存隊(duì)列的元數(shù)據(jù)。雖然只在一個(gè)節(jié)點(diǎn)保存完整隊(duì)列雕蔽,但消息可以在不同節(jié)點(diǎn)之間臨時(shí)傳輸(消費(fèi)者感知到每個(gè)節(jié)點(diǎn)都有完整的隊(duì)列)折柠。如果保存隊(duì)列的單個(gè)節(jié)點(diǎn)掛了,則消費(fèi)者對(duì)其訂閱丟失批狐,即將投遞到該隊(duì)列的信息消息也丟失液走。如果掛掉的隊(duì)列是持久化隊(duì)列則無(wú)法重新創(chuàng)建隊(duì)列,必須恢復(fù)該隊(duì)列

      交換器:交換器實(shí)質(zhì)是一張查詢表(消息的轉(zhuǎn)發(fā)路由是由信道完成)贾陷,集群內(nèi)所有的節(jié)點(diǎn)擁有所有交換器的信息

      數(shù)據(jù)存儲(chǔ):分為內(nèi)存節(jié)點(diǎn)和硬盤節(jié)點(diǎn)缘眶,硬盤節(jié)點(diǎn)防止重啟后元數(shù)據(jù)信息丟失。元數(shù)據(jù)的創(chuàng)建更新在集群所有節(jié)點(diǎn)操作完成后才返回髓废。集群下要求任何時(shí)刻集群中至少有一個(gè)磁盤節(jié)點(diǎn)巷懈,如果唯一的磁盤節(jié)點(diǎn)掛了,集群只能路由消息但不能創(chuàng)建更新元數(shù)據(jù)

    • 鏡像隊(duì)列

      image_queues.PNG

      鏡像不在單獨(dú)存在在唯一節(jié)點(diǎn)慌洪,而是冗余在多個(gè)節(jié)點(diǎn)

鏡像隊(duì)列

因?yàn)槠胀耗J较鄬?duì)基礎(chǔ)顶燕,而鏡像隊(duì)列復(fù)雜,這里重點(diǎn)討論一下鏡像隊(duì)列冈爹。

概述

隊(duì)列鏡像通常包括一個(gè) master 節(jié)點(diǎn)和多個(gè) slave 節(jié)點(diǎn)涌攻,每個(gè)節(jié)點(diǎn)都復(fù)制隊(duì)列數(shù)據(jù)。當(dāng)一個(gè)節(jié)點(diǎn)失效時(shí)频伤,可以自動(dòng)切換到另一個(gè)節(jié)點(diǎn)確笨一眩可用。在鏡像隊(duì)列模式下憋肖,除了 publish 外的所有動(dòng)作都只會(huì)向 master 發(fā)送因痛,然后 master 將命令執(zhí)行的結(jié)果廣播為所有 slave,publish 到鏡像的所有消息總是被直接 publish 到所有 slave 之上(類似與 fanout 交換器)岸更。

原理

普通隊(duì)列結(jié)構(gòu)

普通隊(duì)列由兩部分組成:

  • AMQQueue:主要負(fù)責(zé) AMQP 協(xié)議的邏輯功能
  • BackingQueue:存儲(chǔ)消息

對(duì)于 BackingQueue 又由五個(gè)子隊(duì)列組成:Q1, Q1, Delta, Q3, Q4鸵膏,MQ 的消息進(jìn)入隊(duì)列后會(huì)隨著系統(tǒng)負(fù)載在隊(duì)列中流動(dòng),BackingQueue 中的消息可以分為四個(gè)狀態(tài):

  • Alpha:消息的內(nèi)容和索引都在內(nèi)存中怎炊,Q1 和 Q4 的狀態(tài)
  • Beta:消息的內(nèi)容在硬盤谭企,消息的索引在內(nèi)存,Q2 和 Q3 的狀態(tài)
  • Gamma:消息內(nèi)容在硬盤评肆,消息的索引在硬盤和內(nèi)存都有债查,Q2 和 Q3 的狀態(tài)
  • Delta:消息的內(nèi)容和消息的索引都在硬盤上,Delta 狀態(tài)

對(duì)于持久化的消息糟港,消息內(nèi)容和消息索引都必須先保存到磁盤上攀操,才會(huì)處于上述狀態(tài)中的一種,而Gamma狀態(tài)的消息只有持久化的消息才會(huì)有該狀態(tài)秸抚。

從 Q1 到 Q4速和,基本的經(jīng)歷是由內(nèi)存到硬盤再到內(nèi)存的設(shè)計(jì)歹垫,分層的好處使得整個(gè)隊(duì)列有很好的彈性:

  • 當(dāng)隊(duì)列負(fù)載很高的情況下,能夠通過(guò)將一部分消息由磁盤保存來(lái)節(jié)省內(nèi)存空間
  • 當(dāng)負(fù)載降低的時(shí)候颠放,這部分消息又漸漸回到內(nèi)存排惨,被消費(fèi)者獲取

引起消息流動(dòng)的兩種情況:消費(fèi)者獲取消息,內(nèi)存不足

當(dāng)系統(tǒng)處于正常負(fù)載碰凶,對(duì)消息的消費(fèi)速度不小于接收速度暮芭,對(duì)于非消息極可能只會(huì)有 Alpha 狀態(tài)。對(duì)于持久化消息一定會(huì)進(jìn)入 gamma 狀態(tài)欲低。如果開啟 confirm 機(jī)制辕宏,只有到了這個(gè)階段才會(huì)確認(rèn)消息已經(jīng)被接受,當(dāng)消費(fèi)足夠快且內(nèi)存充足消息不會(huì)繼續(xù)走到下一狀態(tài)砾莱。

當(dāng)系統(tǒng)處于高負(fù)載瑞筐,已接受的消息不能很快被消費(fèi),這些消息就會(huì)進(jìn)入很深的隊(duì)列中去腊瑟,增加處理每個(gè)消息的平均開銷聚假。因?yàn)槠骄_銷增加,處理速度更慢闰非,由此惡性循環(huán)膘格,使得系統(tǒng)的處理能力大大降低。

改善措施:

  1. 進(jìn)行流程控制
  2. 增加 prefetch 的值财松,一次發(fā)送更多消息給消費(fèi)者
  3. 采用 multiple ack

鏡像隊(duì)列結(jié)構(gòu)

在鏡像隊(duì)列中 AMQQueue 仍舊負(fù)責(zé) AMQP 協(xié)議的邏輯功能瘪贱,而 backing_queue 已不是簡(jiǎn)單的單節(jié)點(diǎn) backing_queue 了。

backing_queue 是由 master 和 slave 節(jié)點(diǎn)組成的特殊 backing_queue游岳,所有對(duì) mirror_queue_master 的操作政敢,會(huì)通過(guò) GM 同步到 slave 節(jié)點(diǎn)其徙,slave 節(jié)點(diǎn)上 mirror_queue_slave 負(fù)責(zé)回調(diào)胚迫,master 節(jié)點(diǎn)上 coordinato 負(fù)責(zé)回調(diào)。

鏡像隊(duì)列對(duì)消息的操作:

  • basic.publish 操作:操作直接同步到所有節(jié)點(diǎn)
  • 其他操作:通過(guò) master 操作唾那,由 master 將結(jié)果給 slave
GM

GM(Guarenteed Multicast)访锻,實(shí)現(xiàn)可靠組播通訊協(xié)議的模塊,確保組播消息的原子性:

  • 將所有節(jié)點(diǎn)形成一個(gè)收尾相連的循環(huán)鏈表
  • 當(dāng)有節(jié)點(diǎn)新增時(shí)闹获,相鄰的節(jié)點(diǎn)保證當(dāng)前廣播的消息會(huì)復(fù)制到新的節(jié)點(diǎn)上
  • 當(dāng)有節(jié)點(diǎn)失效時(shí)期犬,相鄰的節(jié)點(diǎn)會(huì)接管保證本次廣播的消息會(huì)復(fù)制到所有節(jié)點(diǎn)
  • 消息從master節(jié)點(diǎn)對(duì)應(yīng)的gm發(fā)出后,順著鏈表依次傳送到所有節(jié)點(diǎn)

鏡像隊(duì)列細(xì)節(jié)備忘

鏡像隊(duì)列細(xì)節(jié)太多避诽,這里整理網(wǎng)上一個(gè)注意事項(xiàng):

  1. 鏡像隊(duì)列不能作為負(fù)載均衡使用龟虎,因?yàn)槊總€(gè)操作在所有節(jié)點(diǎn)都要做一遍

  2. ha-mode 參數(shù)與 durable, declare 對(duì) exclusive 隊(duì)列都不生效。exclusive隊(duì)列是連接獨(dú)占的沙庐,當(dāng)連接斷開鲤妥,隊(duì)列自動(dòng)刪除佳吞,這兩個(gè)參數(shù)對(duì)exclusive隊(duì)列沒(méi)有意義

  3. 將新節(jié)點(diǎn)加入已存在的鏡像隊(duì)列時(shí),默認(rèn)情況下 ha-sync-mode=manual棉安,鏡像隊(duì)列中的消息不會(huì)主動(dòng)同步到新節(jié)點(diǎn)底扳,除非顯式調(diào)用同步命令。當(dāng)調(diào)用同步命令后贡耽,隊(duì)列開始阻塞衷模,無(wú)法對(duì)其進(jìn)行操作,直到同步完畢蒲赂。當(dāng) ha-sync-mode=automatic 時(shí)阱冶,新加入節(jié)點(diǎn)時(shí)會(huì)默認(rèn)同步已知的鏡像隊(duì)列。由于同步過(guò)程的限制滥嘴,所以不建議在生產(chǎn)環(huán)境的active隊(duì)列(有生產(chǎn)消費(fèi)消息)中操作

  4. 每當(dāng)一個(gè)節(jié)點(diǎn)加入或者重新加入(例如從網(wǎng)絡(luò)分區(qū)中恢復(fù)回來(lái))鏡像隊(duì)列熙揍,之前保存的隊(duì)列內(nèi)容會(huì)被清空

  5. 鏡像隊(duì)列有主從之分,一個(gè)主節(jié)點(diǎn)(master)氏涩,0個(gè)或多個(gè)從節(jié)點(diǎn)(slave)届囚。當(dāng) master 宕掉后,會(huì)在 slave中 選舉新的master是尖。選舉算法為最早啟動(dòng)的節(jié)點(diǎn)

  6. 當(dāng)所有slave都處在(與master)未同步狀態(tài)時(shí)意系,并且 ha-promote-on-shutdown policy 設(shè)置為 when-syned(默認(rèn)) 時(shí),如果 master 因?yàn)橹鲃?dòng)的原因停掉饺汹,比如是通過(guò) rabbitmqctl stop 命令停止或者優(yōu)雅關(guān)閉 OS蛔添,那么slave不會(huì)接管 master,也就是說(shuō)此時(shí)鏡像隊(duì)列不可用

    但是如果master因?yàn)楸粍?dòng)原因停掉兜辞,比如 VM 或者 OS crash了迎瞧,那么 slave 會(huì)接管 master。這個(gè)配置項(xiàng)隱含的價(jià)值取向是優(yōu)先保證消息可靠不丟失逸吵,放棄可用性凶硅。

    如果 ha-promote-on-shutdown policy 設(shè)置為 alway,那么不論 master 因?yàn)楹畏N原因停止扫皱,slave 都會(huì)接管 master足绅,優(yōu)先保證可用性

  7. 鏡像隊(duì)列中最后一個(gè)停止的節(jié)點(diǎn)會(huì)是 master,啟動(dòng)順序必須是 master 先起韩脑,如果 slave 先起氢妈,它會(huì)有 30 秒的等待時(shí)間,等待 master 啟動(dòng)段多,然后加入 cluster首量。

    當(dāng)所有節(jié)點(diǎn)因故(斷電等)同時(shí)離線時(shí),每個(gè)節(jié)點(diǎn)都認(rèn)為自己不是最后一個(gè)停止的節(jié)點(diǎn)。要恢復(fù)鏡像隊(duì)列加缘,可以嘗試在 30 秒之內(nèi)同時(shí)啟動(dòng)所有節(jié)點(diǎn)

  8. 對(duì)于鏡像隊(duì)列粥航,客戶端basic.publish操作會(huì)同步到所有節(jié)點(diǎn);而其他操作則是通過(guò)master中轉(zhuǎn)生百,再由master將操作作用于salve递雀。比如一個(gè)basic.get操作,假如客戶端與slave建立了TCP連接蚀浆,首先是slave將basic.get請(qǐng)求發(fā)送至master缀程,由master備好數(shù)據(jù),返回至slave市俊,投遞給消費(fèi)者

  9. 當(dāng) slave 宕掉時(shí)杨凑,除了與 slave 相連的客戶端連接全部斷開之外,沒(méi)有其他影響摆昧。

    當(dāng) master 宕掉時(shí)撩满,會(huì)有以下連鎖反應(yīng):

    1. 與 master 相連的客戶端連接全部斷開。
    2. 選舉最老的 slave 為 master绅你。若此時(shí)所有 slave 處于未同步狀態(tài)伺帘,則未同步部分消息丟失。
    3. 新的 master 節(jié)點(diǎn) requeue 所有 unack 消息忌锯,因?yàn)檫@個(gè)新節(jié)點(diǎn)無(wú)法區(qū)分這些 unack 消息是否已經(jīng)到達(dá)客戶端伪嫁,亦或是 ack 消息丟失在到老master的通路上,亦或是丟在老 master 組播 ack 消息到所有 slave 的通路上偶垮。所以處于消息可靠性的考慮张咳,requeue 所有 unack 的消息。此時(shí)客戶端可能受到重復(fù)消息似舵。
    4. 如果客戶端連著 slave脚猾,并且 basic.consume 消息時(shí)指定了x-cancel-on-ha-failover參數(shù),那么客戶端會(huì)收到一個(gè) Consumer Cancellation Notification 通知砚哗,Java SDK中會(huì)回調(diào) Consumer 接口的handleCancel() 方法龙助,故需覆蓋此方法。如果不指定 x-cancel-on-ha-failover 參數(shù)频祝,那么消費(fèi)者就無(wú)法感知 master 宕機(jī)泌参,會(huì)一直等待下去

鏡像隊(duì)列的恢復(fù)

前提:兩個(gè)節(jié)點(diǎn) A 和 B 組成以鏡像隊(duì)列

  • 場(chǎng)景一:A 先停,B 后停

    該場(chǎng)景下 B 是 master常空,只要先啟動(dòng) B,再啟動(dòng) A 即可盖溺±觳冢或者先啟動(dòng) A,再在 30s 之內(nèi)啟動(dòng) B 即可恢復(fù)鏡像隊(duì)列烘嘱。如果沒(méi)有在 30s 內(nèi)恢復(fù) B昆禽,那么 A 自己就停掉自己

  • 場(chǎng)景二:A蝗蛙,B 同時(shí)停

    該場(chǎng)景可能是由掉電等原因造成,只需在 30s 之內(nèi)連續(xù)啟動(dòng) A 和 B 即可恢復(fù)鏡像隊(duì)列

  • 場(chǎng)景三:A 先停醉鳖,B 后停捡硅,且 A 無(wú)法恢復(fù)

    因?yàn)?B 是 master,所以等 B 起來(lái)后盗棵,在 B 節(jié)點(diǎn)上調(diào)用 rabbitmqctl forget_cluster_node A 以解除 A 的 cluster 關(guān)系壮韭,再將新的 slave 節(jié)點(diǎn)加入 B 即可重新恢復(fù)鏡像隊(duì)列

  • 場(chǎng)景四:A 先停,B 后停纹因,且 B 無(wú)法恢復(fù)

    此時(shí) B 是 master喷屋,所以直接啟動(dòng) A 是不行的,當(dāng) A 無(wú)法啟動(dòng)時(shí)瞭恰,也就沒(méi)辦法在 A 節(jié)點(diǎn)上調(diào)用 rabbitmqctl forget_cluster_node B屯曹。新版本中,forget_cluster_node 支持 --offline 參數(shù)惊畏,offline 參數(shù)允許 rabbitmqctl 在離線節(jié)點(diǎn)上執(zhí)行 forget_cluster_node 命令恶耽,迫使 RabbitMQ 在未啟動(dòng)的 slave 節(jié)點(diǎn)中選擇一個(gè)作為 master。當(dāng)在 A 節(jié)點(diǎn)執(zhí)行 rabbitmqctl forget_cluster_node --offline B 時(shí)颜启,RabbitMQ 會(huì) mock 一個(gè)節(jié)點(diǎn)代表 A驳棱,執(zhí)行 forget_cluster_node 命令將 B 剔出 cluster,然后 A 就能正常啟動(dòng)了农曲。最后將新的 slave 節(jié)點(diǎn)加入 A 即可重新恢復(fù)鏡像隊(duì)列

  • 場(chǎng)景五:A 先停社搅,B 后停,且 A 和 B 均無(wú)法恢復(fù)乳规,但是能得到 A 或 B 的磁盤文件

    這個(gè)場(chǎng)景更加難以處理形葬。將A或B的數(shù)據(jù)庫(kù)文件($RabbitMQ_HOME/var/lib目錄中)copy至新節(jié)點(diǎn)C的目錄下,再將 C 的 hostname 改成 A 或者 B 的 hostname暮的。如果 copy 過(guò)來(lái)的是 A 節(jié)點(diǎn)磁盤文件笙以,按場(chǎng)景四處理,如果拷貝過(guò)來(lái)的是 B 節(jié)點(diǎn)的磁盤文件冻辩,按場(chǎng)景三處理猖腕。最后將新的 slave 節(jié)點(diǎn)加入 C 即可重新恢復(fù)鏡像隊(duì)列

  • 場(chǎng)景六:A 先停,B 后停恨闪,且 A 和 B 均無(wú)法恢復(fù)倘感,且無(wú)法得到 A 和 B 的磁盤文件

    跑路吧


參考:

RabbitMQ分布式集群架構(gòu)和高可用性(HA)

rabbitmq——鏡像隊(duì)列

RabbitMQ源碼分析 - 隊(duì)列機(jī)制

RabbitMQ系列三 (深入消息隊(duì)列)

RabbitMQ鏡像隊(duì)列的故障恢復(fù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市咙咽,隨后出現(xiàn)的幾起案子老玛,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜡豹,死亡現(xiàn)場(chǎng)離奇詭異麸粮,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)镜廉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門弄诲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人娇唯,你說(shuō)我怎么就攤上這事齐遵。” “怎么了视乐?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵洛搀,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我佑淀,道長(zhǎng)留美,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任伸刃,我火速辦了婚禮谎砾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捧颅。我一直安慰自己景图,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布碉哑。 她就那樣靜靜地躺著挚币,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扣典。 梳的紋絲不亂的頭發(fā)上妆毕,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音贮尖,去河邊找鬼笛粘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛湿硝,可吹牛的內(nèi)容都是我干的薪前。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼关斜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼示括!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蚤吹,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤例诀,失蹤者是張志新(化名)和其女友劉穎随抠,沒(méi)想到半個(gè)月后裁着,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體繁涂,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年二驰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扔罪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡桶雀,死狀恐怖矿酵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情矗积,我是刑警寧澤全肮,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站棘捣,受9級(jí)特大地震影響辜腺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乍恐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一评疗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茵烈,春花似錦百匆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至仑荐,卻和暖如春雕拼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背释漆。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工悲没, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人男图。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓示姿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逊笆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子栈戳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容