一文讀懂 Apache Kudu

前言

Apache Kudu是由Cloudera開(kāi)源的存儲(chǔ)引擎挑豌,可以同時(shí)提供低延遲的隨機(jī)讀寫(xiě)和高效的數(shù)據(jù)分析能力墩崩。Kudu支持水平擴(kuò)展,使用Raft協(xié)議進(jìn)行一致性保證鹦筹,并且與Cloudera Impala和Apache Spark等當(dāng)前流行的大數(shù)據(jù)查詢(xún)和分析工具結(jié)合緊密。本文將為您介紹Kudu的一些基本概念和架構(gòu)以及在企業(yè)中的應(yīng)用铐拐,使您對(duì)Kudu有一個(gè)較為全面的了解。

一遍蟋、為什么需要Kudu

Kudu這個(gè)名字聽(tīng)起來(lái)可能有些奇怪,實(shí)際上匿值,Kudu是一種非洲的大羚羊,中文名叫“捻角羚”挟憔,就是下圖這個(gè)樣子:

捻角羚,圖片來(lái)源見(jiàn)水印

比較有意思的是绊谭,同為Cloudera公司開(kāi)源的另一款產(chǎn)品Impala,是另一種非洲的羚羊达传,叫做“黑斑羚”,也叫“高角羚”宪赶。不知道Cloudera公司為什么這么喜歡羚羊,也許是因?yàn)榱缪虻乃俣瓤彀伞?br> 言歸正傳搂妻,現(xiàn)在提起大數(shù)據(jù)存儲(chǔ),我們能想到的技術(shù)有很多欲主,比如HDFS邓厕,以及在HDFS上的列式存儲(chǔ)技術(shù)Apache Parquet,Apache ORC详恼,還有以KV形式存儲(chǔ)半結(jié)構(gòu)化數(shù)據(jù)的Apache HBase和Apache Cassandra等等。既然有了如此多的存儲(chǔ)技術(shù)昧互,Cloudera公司為什么要開(kāi)發(fā)出一款全新的存儲(chǔ)引擎Kudu呢?
事實(shí)上硅堆,當(dāng)前的這些存儲(chǔ)技術(shù)都存在著一定的局限性。對(duì)于會(huì)被用來(lái)進(jìn)行分析的靜態(tài)數(shù)據(jù)集來(lái)說(shuō)渐逃,使用Parquet或者ORC存儲(chǔ)是一種明智的選擇。但是目前的列式存儲(chǔ)技術(shù)都不能更新數(shù)據(jù)茄菊,而且隨機(jī)讀寫(xiě)性能感人。而可以進(jìn)行高效隨機(jī)讀寫(xiě)的HBase面殖、Cassandra等數(shù)據(jù)庫(kù),卻并不適用于基于SQL的數(shù)據(jù)分析方向脊僚。所以現(xiàn)在的企業(yè)中,經(jīng)常會(huì)存儲(chǔ)兩套數(shù)據(jù)分別用于實(shí)時(shí)讀寫(xiě)與數(shù)據(jù)分析辽幌,先將數(shù)據(jù)寫(xiě)入HBase中增淹,再定期通過(guò)ETL到Parquet進(jìn)行數(shù)據(jù)同步虑润。但是這樣做有很多缺點(diǎn):

  1. 用戶需要在兩套系統(tǒng)間編寫(xiě)和維護(hù)復(fù)雜的ETL邏輯。
  2. 時(shí)效性較差拳喻。因?yàn)镋TL通常是一個(gè)小時(shí)、幾個(gè)小時(shí)甚至是一天一次猪腕,那么可供分析的數(shù)據(jù)就需要一個(gè)小時(shí)至一天的時(shí)間后才進(jìn)入到可用狀態(tài),也就是說(shuō)從數(shù)據(jù)到達(dá)到可被分析之間是會(huì)存在一個(gè)較為明顯的“空檔期”的码撰。
  3. 更新需求難以滿足个盆。在實(shí)際情況中可能會(huì)有一些對(duì)已經(jīng)寫(xiě)入的數(shù)據(jù)的更新需求朵栖,這種情況往往需要對(duì)歷史數(shù)據(jù)進(jìn)行更新,而對(duì)Parquet這種靜態(tài)數(shù)據(jù)集的更新操作陨溅,代價(jià)是非常昂貴的。
  4. 存儲(chǔ)資源浪費(fèi)绍在。兩套存儲(chǔ)系統(tǒng)意味著占用的磁盤(pán)資源翻倍了,造成了成本的提升偿渡。

我們知道,基于HDFS的存儲(chǔ)技術(shù)溜宽,比如Parquet,具有高吞吐量連續(xù)讀取數(shù)據(jù)的能力适揉;而HBase和Cassandra等技術(shù)適用于低延遲的隨機(jī)讀寫(xiě)場(chǎng)景,那么有沒(méi)有一種技術(shù)可以同時(shí)具備這兩種優(yōu)點(diǎn)呢嫉嘀?Kudu提供了一種“happy medium”的選擇:

kudu的定位

Kudu不但提供了行級(jí)的插入、更新剪侮、刪除API,同時(shí)也提供了接近Parquet性能的批量掃描操作瓣俯。使用同一份存儲(chǔ),既可以進(jìn)行隨機(jī)讀寫(xiě)降铸,也可以滿足數(shù)據(jù)分析的要求在旱。

二桶蝎、Kudu總覽

Tables和Schemas

從用戶角度來(lái)看,Kudu是一種存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù)表的存儲(chǔ)系統(tǒng)谅畅。在一個(gè)Kudu集群中可以定義任意數(shù)量的table,每個(gè)table都需要預(yù)先定義好schema毡泻。每個(gè)table的列數(shù)是確定的,每一列都需要有名字和類(lèi)型,每個(gè)表中可以把其中一列或多列定義為主鍵雹顺。這么看來(lái),Kudu更像關(guān)系型數(shù)據(jù)庫(kù)廊遍,而不是像HBase、Cassandra和MongoDB這些NoSQL數(shù)據(jù)庫(kù)喉前。不過(guò)Kudu目前還不能像關(guān)系型數(shù)據(jù)一樣支持二級(jí)索引。
Kudu使用確定的列類(lèi)型卵迂,而不是類(lèi)似于NoSQL的“everything is byte”。這可以帶來(lái)兩點(diǎn)好處:

  1. 確定的列類(lèi)型使Kudu可以進(jìn)行類(lèi)型特有的編碼见咒。
  2. 可以提供 SQL-like 元數(shù)據(jù)給其他上層查詢(xún)工具,比如BI工具论颅。

讀寫(xiě)操作

用戶可以使用 InsertUpdateDelete API對(duì)表進(jìn)行寫(xiě)操作恃疯。不論使用哪種API,都必須指定主鍵今妄。但批量的刪除和更新操作需要依賴(lài)更高層次的組件(比如Impala郑口、Spark)犬性。Kudu目前還不支持多行事務(wù)。
而在讀操作方面腾仅,Kudu只提供了Scan操作來(lái)獲取數(shù)據(jù)。用戶可以通過(guò)指定過(guò)濾條件來(lái)獲取自己想要讀取的數(shù)據(jù)推励,但目前只提供了兩種類(lèi)型的過(guò)濾條件:主鍵范圍和列值與常數(shù)的比較。由于Kudu在硬盤(pán)中的數(shù)據(jù)采用列式存儲(chǔ)验辞,所以只掃描需要的列將極大地提高讀取性能。

一致性模型

Kudu為用戶提供了兩種一致性模型跌造。默認(rèn)的一致性模型是snapshot consistency。這種一致性模型保證用戶每次讀取出來(lái)的都是一個(gè)可用的快照,但這種一致性模型只能保證單個(gè)client可以看到最新的數(shù)據(jù)陵珍,但不能保證多個(gè)client每次取出的都是最新的數(shù)據(jù)。另一種一致性模型external consistency可以在多個(gè)client之間保證每次取到的都是最新數(shù)據(jù)撑教,但是Kudu沒(méi)有提供默認(rèn)的實(shí)現(xiàn)醉拓,需要用戶做一些額外工作伟姐。
為了實(shí)現(xiàn)external consistency亿卤,Kudu提供了兩種方式:

  1. 在client之間傳播timestamp token。在一個(gè)client完成一次寫(xiě)入后排吴,會(huì)得到一個(gè)timestamp token,然后這個(gè)client把這個(gè)token傳播到其他client钻哩,這樣其他client就可以通過(guò)token取到最新數(shù)據(jù)了。不過(guò)這個(gè)方式的復(fù)雜度很高街氢。
  2. 通過(guò)commit-wait方式,這有些類(lèi)似于Google的Spanner珊肃。但是目前基于NTP的commit-wait方式延遲實(shí)在有點(diǎn)高。不過(guò)Kudu相信伦乔,隨著Spanner的出現(xiàn)厉亏,未來(lái)幾年內(nèi)基于real-time clock的技術(shù)將會(huì)逐漸成熟烈和。

三爱只、Kudu的架構(gòu)

與HDFS和HBase相似招刹,Kudu使用單個(gè)的Master節(jié)點(diǎn),用來(lái)管理集群的元數(shù)據(jù)蔗喂,并且使用任意數(shù)量的Tablet Server節(jié)點(diǎn)用來(lái)存儲(chǔ)實(shí)際數(shù)據(jù)$侄可以部署多個(gè)Master節(jié)點(diǎn)來(lái)提高容錯(cuò)性畦粮。

Kudu架構(gòu)圖宣赔,圖片來(lái)源于官網(wǎng)

Master

Kudu的master節(jié)點(diǎn)負(fù)責(zé)整個(gè)集群的元數(shù)據(jù)管理和服務(wù)協(xié)調(diào)。它承擔(dān)著以下功能:

  1. 作為catalog manager儒将,master節(jié)點(diǎn)管理著集群中所有table和tablet的schema及一些其他的元數(shù)據(jù)。
  2. 作為cluster coordinator钩蚊,master節(jié)點(diǎn)追蹤著所有server節(jié)點(diǎn)是否存活,并且當(dāng)server節(jié)點(diǎn)掛掉后協(xié)調(diào)數(shù)據(jù)的重新分布砰逻。
  3. 作為tablet directory鸣驱,master跟蹤每個(gè)tablet的位置蝠咆。

Catalog Manager

Kudu的master節(jié)點(diǎn)會(huì)持有一個(gè)單tablet的table——catalog table,但是用戶是不能直接訪問(wèn)的刚操。master將內(nèi)部的catalog信息寫(xiě)入該tablet,并且將整個(gè)catalog的信息緩存到內(nèi)存中菊霜。隨著現(xiàn)在商用服務(wù)器上的內(nèi)存越來(lái)越大,并且元數(shù)據(jù)信息占用的空間其實(shí)并不大占卧,所以master不容易存在性能瓶頸。catalog table保存了所有table的schema的版本以及table的狀態(tài)(創(chuàng)建华蜒、運(yùn)行辙纬、刪除等)贺拣。

Cluster Coordination

Kudu集群中的每個(gè)tablet server都需要配置master的主機(jī)名列表。當(dāng)集群?jiǎn)?dòng)時(shí)捂蕴,tablet server會(huì)向master注冊(cè),并發(fā)送所有tablet的信息啥辨。tablet server第一次向master發(fā)送信息時(shí)會(huì)發(fā)送所有tablet的全量信息,后續(xù)每次發(fā)送則只會(huì)發(fā)送增量信息溉知,僅包含新創(chuàng)建腕够、刪除或修改的tablet的信息。
作為cluster coordination帚湘,master只是集群狀態(tài)的觀察者。對(duì)于tablet server中tablet的副本位置甚淡、Raft配置和schema版本等信息的控制和修改由tablet server自身完成。master只需要下發(fā)命令贯卦,tablet server執(zhí)行成功后會(huì)自動(dòng)上報(bào)處理的結(jié)果。

Tablet Directory

因?yàn)閙aster上緩存了集群的元數(shù)據(jù)脸侥,所以client讀寫(xiě)數(shù)據(jù)的時(shí)候盈厘,肯定是要通過(guò)master才能獲取到tablet的位置等信息睁枕。但是如果每次讀寫(xiě)都要通過(guò)master節(jié)點(diǎn)的話沸手,那master就會(huì)變成這個(gè)集群的性能瓶頸,所以client會(huì)在本地緩存一份它需要訪問(wèn)的tablet的位置信息契吉,這樣就不用每次讀寫(xiě)都從master中獲取。
因?yàn)閠ablet的位置可能也會(huì)發(fā)生變化(比如某個(gè)tablet server節(jié)點(diǎn)crash掉了)捐晶,所以當(dāng)tablet的位置發(fā)生變化的時(shí)候,client會(huì)收到相應(yīng)的通知惑灵,然后再去master上獲取一份新的元數(shù)據(jù)信息山上。

Tablet存儲(chǔ)

在數(shù)據(jù)存儲(chǔ)方面英支,Kudu選擇完全由自己實(shí)現(xiàn),而沒(méi)有借助于已有的開(kāi)源方案干花。tablet存儲(chǔ)主要想要實(shí)現(xiàn)的目標(biāo)為:

  1. 快速的列掃描。
  2. 低延遲的隨機(jī)讀寫(xiě)池凄。
  3. 一致性的性能。

RowSets

在Kudu中肿仑,tablet被細(xì)分為更小的單元桑阶,叫做RowSets。一些RowSet僅存在于內(nèi)存中勾邦,被稱(chēng)為MemRowSets,而另一些則同時(shí)使用內(nèi)存和硬盤(pán)眷篇,被稱(chēng)為DiskRowSets。任何一行未被刪除的數(shù)據(jù)都只能存在于一個(gè)RowSet中蕉饼。
無(wú)論任何時(shí)候,一個(gè)tablet僅有一個(gè)MemRowSet用來(lái)保存最新插入的數(shù)據(jù)昧港,并且有一個(gè)后臺(tái)線程會(huì)定期把內(nèi)存中的數(shù)據(jù)flush到硬盤(pán)上。
當(dāng)一個(gè)MemRowSet被flush到硬盤(pán)上以后创肥,一個(gè)新的MemRowSet會(huì)替代它达舒。而原有的MemRowSet會(huì)變成一到多個(gè)DiskRowSet叹侄。flush操作是完全同步進(jìn)行的,在進(jìn)行flush時(shí)趾代,client同樣可以進(jìn)行讀寫(xiě)操作。

MemRowSet

MemRowSets是一個(gè)可以被并發(fā)訪問(wèn)并進(jìn)行過(guò)鎖優(yōu)化的B-tree撒强,主要是基于MassTree來(lái)設(shè)計(jì)的,但存在幾點(diǎn)不同:

  1. Kudu并不支持直接刪除操作飘哨,由于使用了MVCC胚想,所以在Kudu中刪除操作其實(shí)是插入一條標(biāo)志著刪除的數(shù)據(jù)顿仇,這樣就可以推遲刪除操作。
  2. 類(lèi)似刪除操作摆马,Kudu也不支持原地更新操作。
  3. 將tree的leaf鏈接起來(lái)囤采,就像B+-tree。這一步關(guān)鍵的操作可以明顯地提升scan操作的性能蕉毯。
  4. 沒(méi)有實(shí)現(xiàn)字典樹(shù)(trie樹(shù))思犁,而是只用了單個(gè)tree,因?yàn)镵udu并不適用于極高的隨機(jī)讀寫(xiě)的場(chǎng)景进肯。

與Kudu中其他模塊中的數(shù)據(jù)結(jié)構(gòu)不同,MemRowSet中的數(shù)據(jù)使用行式存儲(chǔ)江掩。因?yàn)閿?shù)據(jù)都在內(nèi)存中,所以性能也是可以接受的环形,而且Kudu對(duì)在MemRowSet中的數(shù)據(jù)結(jié)構(gòu)進(jìn)行了一定的優(yōu)化。

DiskRowSet

當(dāng)MemRowSet被flush到硬盤(pán)上抬吟,就變成了DiskRowSet萨咕。當(dāng)MemRowSet被flush到硬盤(pán)的時(shí)候危队,每32M就會(huì)形成一個(gè)新的DiskRowSet,這主要是為了保證每個(gè)DiskRowSet不會(huì)太大发侵,便于后續(xù)的增量compaction操作妆偏。Kudu通過(guò)將數(shù)據(jù)分為base data和delta data刃鳄,來(lái)實(shí)現(xiàn)數(shù)據(jù)的更新操作叔锐。Kudu會(huì)將數(shù)據(jù)按列存儲(chǔ),數(shù)據(jù)被切分成多個(gè)page见秽,并使用B-tree進(jìn)行索引。除了用戶寫(xiě)入的數(shù)據(jù)解取,Kudu還會(huì)將主鍵索引存入一個(gè)列中,并且提供布隆過(guò)濾器來(lái)進(jìn)行高效查找禀苦。

Compaction

為了提高查詢(xún)性能,Kudu會(huì)定期進(jìn)行compaction操作振乏,合并delta data與base data蔗包,對(duì)標(biāo)記了刪除的數(shù)據(jù)進(jìn)行刪除慧邮,并且會(huì)合并一些DiskRowSet舟陆。

分區(qū)

和許多分布式存儲(chǔ)系統(tǒng)一樣,Kudu的table是水平分區(qū)的秦躯。BigTable只提供了range分區(qū),Cassandra只提供hash分區(qū)宦赠,而Kudu提供了較為靈活的分區(qū)方式。當(dāng)用戶創(chuàng)建一個(gè)table時(shí)米母,可以同時(shí)指定table的的partition schema,partition schema會(huì)將primary key映射為partition key铁瞒。一個(gè)partition schema包括0到多個(gè)hash-partitioning規(guī)則和一個(gè)range-partitioning規(guī)則。通過(guò)靈活地組合各種partition規(guī)則慧耍,用戶可以創(chuàng)造適用于自己業(yè)務(wù)場(chǎng)景的分區(qū)方式。

四芍碧、Kudu的應(yīng)用

Kudu的應(yīng)用場(chǎng)景很廣泛煌珊,比如可以進(jìn)行實(shí)時(shí)的數(shù)據(jù)分析定庵,用于數(shù)據(jù)可能會(huì)存在變化的時(shí)序數(shù)據(jù)應(yīng)用等,甚至還有人探討過(guò)使用Kudu替代Kafka的可行性(詳情請(qǐng)戳這里)踪危。不過(guò)Kudu最有名和最成功的應(yīng)用案例,還是國(guó)內(nèi)的小米贞远。小米公司不僅使用Kudu,還深度參與了Kudu的開(kāi)發(fā)蓝仲。Kudu項(xiàng)目在2012年10月由Cloudera公司發(fā)起,2015年10月對(duì)外公布袱结,2015年12月進(jìn)入Apache孵化器亮隙,但是小米公司早在2014年9月就加入到Kudu的開(kāi)發(fā)中了擎勘。
下面我們可以跟隨Cloudera在宣傳Kudu時(shí)使用的ppt來(lái)看一看Kudu在小米的使用。

小米 use case

從上圖中我們可以看到棚饵,Kudu在小米主要用來(lái)對(duì)手機(jī)app和后端服務(wù)的RPC調(diào)用事件進(jìn)行追蹤掩完,以及對(duì)服務(wù)進(jìn)行監(jiān)控。在小米的使用場(chǎng)景下且蓬,Kudu集群已經(jīng)達(dá)到每天200億次寫(xiě)入,并且還在增長(zhǎng)题翰。
Kudu除了優(yōu)秀的性能,更為重要的是可以簡(jiǎn)化數(shù)據(jù)處理的流程豹障。在使用Kudu以前,小米的數(shù)據(jù)處理流程是這樣的:

before Kudu

可以看到血公,數(shù)據(jù)處理的流程很長(zhǎng)。這種處理模式不但較為復(fù)雜累魔,而且latency較高,通常需要等待較長(zhǎng)的時(shí)間(1 hour - 1day)才能得到分析結(jié)果垦写。下面再來(lái)看看使用Kudu以后的數(shù)據(jù)處理流程是怎樣的:

after Kudu

使用Kudu以后,數(shù)據(jù)處理的鏈路被簡(jiǎn)化了梯投,而且得益于Kudu對(duì)隨機(jī)讀寫(xiě)和數(shù)據(jù)分析操作的支持都很好命辖,可以直接對(duì)Kudu中的數(shù)據(jù)進(jìn)行交互式分析晚伙,降低了系統(tǒng)復(fù)雜度,并且latency被大大縮短(0 ~ 10s)咆疗。

五母债、進(jìn)一步學(xué)習(xí)

如果您看了本文的介紹后想進(jìn)一步學(xué)習(xí)Kudu,以下途徑可以幫助您快速入門(mén):

  1. Documentation毡们,官方文檔永遠(yuǎn)是學(xué)習(xí)開(kāi)源項(xiàng)目的最好去處迅皇。
  2. Paper衙熔,Kudu的論文可以幫助您深入了解Kudu的設(shè)計(jì)思想。
  3. Raft協(xié)議红氯,雖然不屬于Kudu的內(nèi)容咕痛,但是Kudu的一致性協(xié)議使用了Raft協(xié)議,了解Raft協(xié)議可以幫助您更好地了解Kudu及其他分布式開(kāi)源系統(tǒng)茉贡。
  4. Apache Kudu as a More Flexible And Reliable Kafka-style Queue,這篇博客也許能對(duì)您在如何使用Kudu的問(wèn)題上有一些啟發(fā)者铜。

比較遺憾的是,由于Kudu還很年輕作烟,所以并沒(méi)有比較好的相關(guān)書(shū)籍出版。計(jì)算機(jī)是一門(mén)實(shí)踐性較強(qiáng)的學(xué)科拿撩,所以動(dòng)手實(shí)踐是成為Kudu專(zhuān)家的必經(jīng)之路:github地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绷雏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子涎显,更是在濱河造成了極大的恐慌坤检,老刑警劉巖期吓,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異讨勤,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)潭千,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)刨晴,“玉大人屉来,你說(shuō)我怎么就攤上這事狈癞。” “怎么了蝶桶?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我脐雪,道長(zhǎng),這世上最難降的妖魔是什么喂江? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮获询,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吉嚣。我一直安慰自己梢薪,他們只是感情好尝哆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著秋泄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天遍希,我揣著相機(jī)與錄音津坑,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的崭参。 我是一名探鬼主播呵曹,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼阵翎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了郭卫?” 一聲冷哼從身側(cè)響起背稼,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后词疼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贰盗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舵盈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡秽晚,死狀恐怖瓦糟,靈堂內(nèi)的尸體忽然破棺而出赴蝇,到底是詐尸還是另有隱情,我是刑警寧澤句伶,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站考余,受9級(jí)特大地震影響先嬉,放射性物質(zhì)發(fā)生泄漏秃殉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一钾军、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吏恭,春花似錦拗小、人聲如沸樱哼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)阅束。三九已至茄唐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背呼盆。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留访圃,地道東北人厨幻。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓况脆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親圈匆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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