kafka設計(上)

1.動機

kafka被設計為能扮演一個大公司可能需要的處理所有實時數(shù)據(jù)流的統(tǒng)一平臺模孩。為了達成這個目的尖阔,我們必須考慮相當廣泛的用例。

  • 它必須有很高的吞吐量榨咐,以便能支持高容量的事件流介却,比如實時日志聚合;
  • 它必須能優(yōu)雅的處理大數(shù)據(jù)積壓块茁,能支持從離線系統(tǒng)定期加載數(shù)據(jù)齿坷;
  • 系統(tǒng)必須能低延遲發(fā)布消息;
  • 我們要它能分區(qū)数焊,分布式永淌,實時處理流(這激發(fā)了我們的分區(qū)和消費者模式);
  • 最后佩耳,在將流發(fā)送到其他數(shù)據(jù)系統(tǒng)進行服務的情況下遂蛀,系統(tǒng)必須在機器故障時能保證容錯。

支持這些用途干厚,會讓我們設計有許多獨一無二的元素李滴,而不是一個傳統(tǒng)的消息系統(tǒng)螃宙。我們將在以下部分概述kafka設計的一些元素。

2.持久化

不要恐懼文件系統(tǒng)悬嗓!

kafka嚴重依賴文件系統(tǒng)存儲消息和緩存消息。大家普遍認為"磁盤速度很慢"裕坊,從而讓人們懷疑持久化結構能否提供有競爭力的性能包竹。實際上,磁盤可以比人們預期的更慢籍凝,也可以比人們預期的更快周瞎,這完全取決于如何使用。合理的磁盤結構設計饵蒂,能夠讓它和網(wǎng)絡一樣快声诸。

磁盤性能關鍵因素就是硬盤的吞吐量在過去十年磁盤尋道延遲。結果表明線性寫入一個6塊7200rpm的SATA組成的RAID-5陣列的JBOD配置退盯,能夠達到600MB/秒彼乌。然而隨機寫入的話性能只有100K/秒。性能相差6000倍渊迁。

線性讀寫大部分情況可預測慰照,并且操作系統(tǒng)有針對性的優(yōu)化。現(xiàn)代操作系統(tǒng)提供了 預讀(read-ahead)和后寫(write-behind)技術琉朽,即塊倍數(shù)預讀取數(shù)據(jù)毒租,并且合并非常小的邏輯寫為一個大的物理寫。這個問題更深入的討論可以參考ACM Queue article:https://queue.acm.org/detail.cfm?id=1563874箱叁,結論是:順序?qū)懘疟P的速度在某些情況下比隨機寫內(nèi)存的速度更快墅垮。

為了補償性能差異,現(xiàn)代操作系統(tǒng)越來越積極的使用主內(nèi)存進行磁盤緩存「現(xiàn)在操作系統(tǒng)非常樂意將所有可用內(nèi)存用來磁盤緩存算色,內(nèi)存回收時,幾乎沒有性能損失螟够,所有磁盤的讀和寫將全部通過統(tǒng)一的內(nèi)存剃允。如果不使用直接I/O,這個特性不能輕易的關閉齐鲤。因此斥废,即使一個進程維護了進程內(nèi)數(shù)據(jù)緩存,數(shù)據(jù)還是可能被復制到操作系統(tǒng)的pagecache给郊,所有內(nèi)存都會存儲兩次牡肉。

此外,kafka運行在JVM上淆九,任何對Java內(nèi)存有一定了解的用戶知道兩件事情:

  • 對象的內(nèi)存開銷非常高统锤,通常會使存儲的數(shù)據(jù)大小翻倍(或更糟)毛俏。
  • 隨著堆內(nèi)數(shù)據(jù)的增加,Java垃圾收集變得越來越頻繁和緩慢饲窿。

由于這些因素煌寇,使用文件系統(tǒng)并依賴pagecache優(yōu)于維護內(nèi)存緩存或者其他結構--我們通過自動訪問所有可用內(nèi)存,至少要加倍可用內(nèi)存逾雄。并且可能由于要存儲壓縮字節(jié)結構而不是分離的對象阀溶,需要再次加倍可用內(nèi)存。

這樣做以后鸦泳,將在32G的服務器上產(chǎn)生28~30G的緩存银锻。此外,即使業(yè)務進程重啟做鹰,高速緩存任然是熱的击纬。但是進程內(nèi)緩存將需要在進程內(nèi)重建(10G的數(shù)據(jù)大概需要花10分鐘),否則它將以完全冷緩存啟動(這意味著初始性能非常糟糕)钾麸。

這將極大的簡化了代碼更振,因為維護高速緩存和文件系統(tǒng)一致性的所有邏輯全部都在操作系統(tǒng)中。如果你對磁盤使用有利于線性讀取饭尝,那么預讀將非常高效的預填充每次磁盤讀取的數(shù)據(jù)到緩存中殃饿。

這表明一個非常簡單的設計:不要恐慌性的在內(nèi)存中維護盡可能多數(shù)據(jù)并將其全部刷到文件系統(tǒng)。我們應該反其道而行之芋肠,所有數(shù)據(jù)應該立即寫到文件系統(tǒng)的持久化日志乎芳,而不需要刷到磁盤。實際上帖池,這只意味著它被轉移到操作系統(tǒng)內(nèi)核的pagecache中奈惑。

這種以pagecache為中心的設計風格在一篇關于Varnish的設計中有描述過∷冢可以戳鏈接http://varnish-cache.org/wiki/ArchitectNotes了解更多肴甸。

Varnish是一款高性能的開源HTTP加速器,淘寶曾經(jīng)和拼多多現(xiàn)在都有使用這個開源技術來應對龐大的流量囚巴。

滿足常量時間

消息系統(tǒng)中使用到的持久化數(shù)據(jù)結構通常是每個消費者隊列關聯(lián)一個BTree或者其他通用的隨機訪問數(shù)據(jù)結構原在,用來維護消息元數(shù)據(jù)。

BTree是最通用的數(shù)據(jù)結構彤叉,并且能在消息系統(tǒng)中廣泛的支持事務性或者非事務性語義庶柿。BTree操作復雜度是O(log N),被認為基本上等價于常量時間秽浇。

但是對磁盤操作則不然浮庐,磁盤每次操作大概要10ms,并且每個磁盤在同一時刻只能做一個尋址柬焕,所以并行化非常受到限制审残。因此梭域,即使非常少量的磁盤搜索也會導致非常高的開銷。

由于存儲系統(tǒng)混合了非常高速緩存操作與非常低效的磁盤操作搅轿,因此高速緩存固定的情況下隨著數(shù)據(jù)的增長病涨,數(shù)據(jù)結構的性能通常是超線性的。即璧坟,數(shù)據(jù)加倍既穆,會使性能衰退到原來的1/2。

直觀地沸柔,可以在簡單讀取上構建持久隊列循衰,并將其附加到文件铲敛,這與日志記錄解決方案的情況一樣褐澎。這種結構有所有操作時間復雜度是O(1)的優(yōu)勢。讀不會阻塞寫伐蒋,寫也不會阻塞讀工三。這就有了一個性能完全與數(shù)據(jù)尺寸分離的優(yōu)勢,即不會隨著數(shù)據(jù)量的增加而導致性能衰減先鱼。服務器就能利用很多便宜的俭正,低轉速的硬盤。盡管它們的尋址性能很差焙畔,但是磁盤在大量的讀寫時性能是可接受的掸读,只需要花1/3的錢,就能得到3倍的能力宏多。

在沒有任何性能損失的前提下儿惫,訪問幾乎無限制的磁盤空間,這意味著我們能提供消息系統(tǒng)通常不具備的功能伸但。例如肾请,在kafka中,我們并不是在消息被消費后就嘗試刪除消息更胖,而是能保留消息一段很長的時間(例如一周)铛铁,正如我們將要描述的那樣,為消費者帶來極大的靈活性却妨。

3.效率

我們盡最大努力在效率上饵逐,一個我們主要的用戶場景就是處理web活動數(shù)據(jù),那是非常海量的數(shù)據(jù)量彪标。每次頁面瀏覽可能生成十多條消息梳毙。此外,我們假設每條投遞的消息至少會有一個消息者(通常會有多個)捐下,因此我們努力使消費者盡可能的高效账锹。

前一段我們討論了磁盤效率萌业,糟糕的磁盤訪問模式,這類系統(tǒng)效率低下主要有兩個原因:很多的小I/O操作奸柬,過多的字節(jié)拷貝生年。小I/O問題發(fā)生在客戶端和服務端,以及服務器本身的持久化操作中廓奕。

為了避免這個問題抱婉,我們的協(xié)議圍繞著"消息集合"抽象構建的,很自然的把消息組合到一起桌粉。這就允許網(wǎng)絡請求把消息組合到一起蒸绩,分攤網(wǎng)絡來回的開銷,而不是每次發(fā)送一條單獨的消息铃肯。服務器依次把消息塊追加到它的日志中患亿。然后消費者每次抓取大的線性消息塊。

這個簡單的優(yōu)化產(chǎn)生了不可思議的數(shù)量級速度提升押逼。批量就會導致更大的網(wǎng)絡包步藕,更大的順序磁盤操作等等。所有這些都將允許Kafka將突發(fā)的隨機消息寫入流轉換為流向消費者的線性寫入挑格。

另一個低效率是字節(jié)拷貝咙冗。在低消息速率這不是問題,但是在有負載的情況下這影響是顯著的漂彤。為了避免這個問題雾消,我們制定了一個在生產(chǎn)者,broker和消費者之間共享的標準的二進制消息格式挫望,如此一來數(shù)據(jù)塊在它們中間傳輸不需要任何修改立润。

消息日志被broker維護,其本身只是一個文件目錄士骤。每個文件都由一系列消息集合填充范删,且這些消息已經(jīng)被寫入磁盤,并且和生產(chǎn)者和消費者使用的相同的格式拷肌。維護這個通用格式可以允許最重要操作的優(yōu)化:持久化日志塊的網(wǎng)絡傳輸〉降現(xiàn)代的unix操作系統(tǒng)提供了一個高度優(yōu)化的從pagecache傳輸數(shù)據(jù)到socket的代碼路徑。在Linux系統(tǒng)中巨缘,這是通過sendfile系統(tǒng)調(diào)用完成的添忘。

為了理解sendfile的影響,需要先重點了解通用的數(shù)據(jù)從文件到socket的傳輸路徑:

  1. 操作系統(tǒng)將磁盤中的數(shù)據(jù)讀入內(nèi)核空間的pagecache若锁;
  2. 應用程序?qū)?nèi)核空間中的數(shù)據(jù)讀入用戶空間緩沖區(qū)搁骑;
  3. 應用程序?qū)?shù)據(jù)寫回內(nèi)核空間中的套接字緩沖區(qū);
  4. 操作系統(tǒng)將數(shù)據(jù)從套接字緩沖區(qū)復制到NIC緩沖區(qū),并通過網(wǎng)絡發(fā)送仲器。

很顯然煤率,這樣做效率不高》剑總計有4次拷貝和2次系統(tǒng)調(diào)用蝶糯。然而用sendfile,允許操作系統(tǒng)將數(shù)據(jù)從pagecache直接發(fā)送到網(wǎng)絡辆沦,從而避免了re-copying昼捍。因此在這個優(yōu)化的路徑中,只有最后的拷貝到NIC緩沖區(qū)是必須的肢扯。

我們期望一種普通的用例妒茬,一個topic多個消費者。使用zero-copy優(yōu)化后蔚晨,數(shù)據(jù)只被拷貝到pagecache一次乍钻,能夠在每次消費時被重用。從而不需要存儲在內(nèi)存中蛛株,然后每次讀取的時候团赁,拷貝到用戶空間育拨。這就允許消息以接近網(wǎng)絡連接限制的速率被消費谨履。

pagecache和sendfile的組合,意味著kafka集群在消費者頻繁追趕的時候熬丧,看不到磁盤上行任何讀取活動笋粟,因為它們將完全從緩存提供數(shù)據(jù)。

更多java中支持的sendfile和zero-copy(零拷貝)析蝴,請參考文章:
https://www.ibm.com/developerworks/linux/library/j-zerocopy/

端到端的批量壓縮
在一些場景下害捕,瓶頸實際上不是CPU或者磁盤,而是網(wǎng)絡帶寬闷畸。尤其需要在廣域網(wǎng)下的兩個數(shù)據(jù)中心之間發(fā)送消息的數(shù)據(jù)管道尝盼。當然,用戶能每次壓縮他的消息佑菩,而不需要kafka的支持盾沫。但是這就導致非常差的壓縮率,因為大部分冗余是由于相同類型的消息之間的重復(例如殿漠,JSON中的字段名稱)赴精。

高效的壓縮需要壓縮多條消息在一起而不是獨立的壓縮每條消息。

kafka以一個高效的批量格式支持此功能绞幌。將一批消息捆綁到一起壓縮蕾哟,然后以這種壓縮格式發(fā)送到kafka服務器。批量消息就以壓縮格式保存在日志中,并且只能被消費者解壓谭确。

kafka支持GZIP帘营,Snappy和LZ4這三種壓縮協(xié)議逐哈。

4.生產(chǎn)者

4.1負載均衡

消費者直接發(fā)送數(shù)據(jù)到broker上分區(qū)的leader仪吧,不需要任何中間路由層鞠眉。為了讓生產(chǎn)者做到這點,所有kafka節(jié)點都能回答一個關于哪些broker是存活的械蹋,以及topic分區(qū)的leader在哪里的元數(shù)據(jù)請求出皇。

客戶端控制發(fā)布消息到哪個分區(qū)〗妓遥可以隨機(一種隨機負載均衡實現(xiàn))唯咬,也可以是一些特定分區(qū)纱注。kafka暴露了接口允許用戶指定消息的key從而指定特定分區(qū)(kafka對這個key這個進行hash然后對分區(qū)數(shù)取模從而得到目標分區(qū))。例如如果key是一個userId胆胰,那么這個用戶所有的消息數(shù)據(jù)都被發(fā)送到同一個分區(qū)狞贱。

這將允許消費者對其消費做出地點假設。 這種分區(qū)方式明確設計為允許在消費者中進行對位置敏感的處理瞎嬉。

4.2異步發(fā)送

批處理是效率的重要驅(qū)動因素之一厚柳。kafka生產(chǎn)者試圖把數(shù)據(jù)積累在緩存中,然后每次請求發(fā)送更大的批量别垮。批處理能被配置為兩種方式:消息不超過一定數(shù)量,例如16k烧董。不允許等待超過時間延遲限制移袍,例如100ms。 這種緩沖方式可配置提供了一種機制來權衡少量的額外延遲以獲得更好的吞吐量(低延遲和高吞吐量之間的平衡)葡盗。

5.消費者

kafka消費者通過向broker發(fā)送抓确茸恰(fetch)請求導向它要消費的位置胶背。消費者在每個請求中指定了日志的offset,然后接收從這個位置開始的一塊日志廷粒。消費者可以控制這個位置红且,如果有需要,它能倒回去重新消費已經(jīng)消費過的日志暇番。

5.1Push vs. Pull

我們考慮的一個最初問題就是消費者是應該從broker拉取數(shù)據(jù),還是broker應該把數(shù)據(jù)推送給消費者次酌。在這一方面舆乔,kafka遵循一個更傳統(tǒng)的設計,生產(chǎn)者把數(shù)據(jù)推送到broker希俩,然后消費者從broker拉取數(shù)據(jù)。

一些以日志為中心的系統(tǒng)贫母,比如Scribe和Apache Flume盒刚,遵循一個完全不同的基于Push模式绿贞,數(shù)據(jù)被推送到下游。兩種方式都有利弊籍铁。

然而,基于Push的系統(tǒng)吩愧,由于broker控制數(shù)據(jù)傳輸?shù)乃俾试鱿裕员容^難處理各種不同的消費者。我們的目標一般是消費者能以最大可能的速率消費糖权,不幸的是,在一個Push系統(tǒng)中星澳,這就意味者當消費者消費的速度跟不上生產(chǎn)速度時,消費者會不堪重負腿堤。

基于Pull的系統(tǒng)有更好的特性如暖,消費者可以落后,又可能會追上装处。可以通過某種退避協(xié)議來緩解寝蹈。通過這種協(xié)議登淘,消費者能表明它已經(jīng)超負荷。但是傳輸速率只會充分使用耍鬓,而不會過分使用流妻。以前以這種方式構建系統(tǒng)的嘗試讓我們采用了更傳統(tǒng)的Pull模式。

基于Pull的系統(tǒng)另一個優(yōu)點是系統(tǒng)可以盡可能的批量發(fā)送數(shù)據(jù)到消費者绅这。基于Push的系統(tǒng)必須選擇立即發(fā)送請求度苔,還是積累更多數(shù)據(jù)浑度,并且在不能感知下游消費者是否能馬上處理的情況下發(fā)送。

如果傾向于低延遲的調(diào)整甩骏,這將導致每次只能發(fā)送單條消息,這非常浪費横漏。一個基于Pull的設計就沒有這個問題,因為消費者總是拉取日志中當前位置后所有有效的消息(或者可能收到配置的最大拉取大小的限制扎拣,比如1k)素跺,因此可以在不引入不必要的延遲的情況下得到最佳的批處理。

基于Pull系統(tǒng)的不足就是如果broker沒有數(shù)據(jù)刊愚,消費者可能在循環(huán)中終止輪詢踩验,實際上消費者是在忙著等待數(shù)據(jù)到來。為了避免這個問題箕憾,kafka的poll請求中有參數(shù)允許消費者請求時在長輪詢中阻塞,等待直到broker中有數(shù)據(jù)到來(并且可選的支持等待直到給定數(shù)量字節(jié)可用钠龙,確保大的傳輸數(shù)據(jù)大杏濉)。

你能想象其他可能的設計咬腋,只是拉取谷羞,端到端,生產(chǎn)者將在本地寫入日志湃缎,broker從這里拉取數(shù)據(jù)蠢壹,然后消費者又從broker那里拉取數(shù)據(jù)。類似存儲轉發(fā)(store-and-forward)類型的生產(chǎn)者蹂季。這是非常有趣的設計,但是我們決定不適合我們的有上千個生產(chǎn)者的使用場景撒汉。

我們大規(guī)模運行持久化數(shù)據(jù)系統(tǒng)的經(jīng)驗使我們感到涕滋,在許多應用中涉及系統(tǒng)中成千上萬的磁盤不會使事情更可靠,相反可能是維護的噩夢宾肺。實際上,我們發(fā)現(xiàn)我們可以大規(guī)模運行具有很強SLA的pipeline丰刊,無需生產(chǎn)者持久性增拥。

消費者位置

令人驚訝的是,保持跟蹤已經(jīng)消費的數(shù)據(jù)棵帽,是一個消息系統(tǒng)的關鍵性能點之一渣玲。許多消息系統(tǒng)在broker上保留了什么消息已經(jīng)被消費的元數(shù)據(jù)。當消息傳到消費者時忘衍,broker要么立即記錄枚钓,要么等待消費者的確認。實際上對于單臺服務器來說搀捷,確實不清楚這個狀態(tài)可能去哪里,由于在消息系統(tǒng)中氢烘,用于存儲這個信息的數(shù)據(jù)結構很小家厌,這也是一個務實的選擇----broker知道什么數(shù)據(jù)被消費了,它能立即刪除它蜀踏,從而保持數(shù)據(jù)量小。

可能并不明顯的是果覆,讓broker和消費者就所消費的內(nèi)容達成一致,并不是一個微不足道的問題斑响。如果broker在每次通過網(wǎng)絡分發(fā)消息時燎猛,就記錄消息為已消費,那么如果消費者未能成功處理消息(消費者崩潰或者請求超時等原因)沸停,那么消息可能會丟失昭卓。

為了解決這個問題,需要消息系統(tǒng)增加了確認機制候醒,例如ActiveMQ倒淫。這就意味著消息被發(fā)送后,只被標記已發(fā)送未消費敌土。broker等待消費者把消息標記為已消費的確認。這個機制修復了消息丟失的問題兴枯,但是引入了新的問題矩欠。首先,消費者處理消息后但在發(fā)送確認前出錯躺坟,那么消息將會被消費兩次该默。第二個問題與性能有關,broker必須保持每條消息的多種狀態(tài)栓袖。所以必須處理棘手的問題裹刮,例如如何處理已發(fā)送但從未確認的消息。

kafka處理這種問題的方式完全不同捧弃。我們的topic被分離成有序分區(qū)集合。任何給定時間嘴办,每個分區(qū)只被訂閱這個topic的消費者組里的一個消費者消費买鸽。這就意味著,消費者在每個分區(qū)的位置只是一個整數(shù)妆艘,即下一次消費的消息的偏移量看幼。這就使得已經(jīng)被消費的狀態(tài)非常小,每個分區(qū)只有一個數(shù)字汽煮,還可以定期檢查這個狀態(tài)棚唆。這就使得和消息確認機制等價機制非常低成本。

這個決定有一個另外的好處翎卓,消費者能故意回退到一個舊的offset重新消費摆寄。這違反了隊列的通用性質(zhì),但是卻成為許多消費者必不可少的特征微饥。例如,如果在消息被消費后矩肩,發(fā)現(xiàn)消費者的代碼有一個BUG肃续,消費者就可以在BUG被消費者馬上重新消費這些消息叉袍。

離線數(shù)據(jù)加載

例如批量數(shù)據(jù)加載刽酱,周期性地將數(shù)據(jù)加載到離線系統(tǒng)(如Hadoop或關系數(shù)據(jù)倉庫)中棵里。

在Hadoop的情況下,我們通過將負載分配到各個映射任務來并行化數(shù)據(jù)負載殿怜,每個節(jié)點/主題/分區(qū)組合一個头谜,允許加載中的完全并行。 Hadoop提供任務管理乔夯,失敗的任務可以在沒有重復數(shù)據(jù)危險的情況下重新啟動 - 它們只是從原始位置重新啟動。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侧纯,一起剝皮案震驚了整個濱河市眶熬,隨后出現(xiàn)的幾起案子块请,更是在濱河造成了極大的恐慌,老刑警劉巖墩新,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件海渊,死亡現(xiàn)場離奇詭異,居然都是意外死亡盔憨,警方通過查閱死者的電腦和手機讯沈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來问慎,“玉大人,你說我怎么就攤上這事记餐∞闭” “怎么了囚衔?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵练湿,是天一觀的道長。 經(jīng)常有香客問我肥哎,道長,這世上最難降的妖魔是什么崖飘? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任朱浴,我火速辦了婚禮达椰,結果婚禮上,老公的妹妹穿的比我還像新娘啰劲。我一直安慰自己,他們只是感情好廷支,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布酥泞。 她就那樣靜靜地躺著啃憎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上羡藐,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天仆嗦,我揣著相機與錄音先壕,去河邊找鬼。 笑死垃僚,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的栽燕。 我是一名探鬼主播改淑,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼朵夏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了询吴?” 一聲冷哼從身側響起亮元,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奉瘤,沒想到半個月后煮甥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡卖局,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年砚偶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片染坯。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡单鹿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仲锄,到底是詐尸還是另有隱情,我是刑警寧澤是趴,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布澄惊,位于F島的核電站掸驱,受9級特大地震影響没佑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蛤奢,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一啤贩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧痹屹,春花似錦、人聲如沸暖庄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俘侠。三九已至蔬将,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霞怀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工廉沮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留徐矩,地道東北人。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓坪稽,卻偏偏與公主長得像鳞骤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子豫尽,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361