讓人欲罷不能的Feed流系統是如何設計的?

簡介

差不多十年前,隨著功能機的淘汰和智能機的普及,互聯網開始進入移動互聯網時代,最具代表性的產品就是微博、微信,以及后來的今日頭條、快手等。這些移動化聯網時代的新產品在過去幾年間借著智能手機的風高速成長。

這些產品都是Feed流類型產品,由于Feed流一般是按照時間“從上往下流動”,非常適合在移動設備端瀏覽,最終這一類應用就脫穎而出,迅速搶占了上一代產品的市場空間。

Feed流是Feed + 流,Feed的本意是飼料,Feed流的本意就是有人一直在往一個地方投遞新鮮的飼料,如果需要飼料,只需要盯著投遞點就可以了,這樣就能源源不斷獲取到新鮮的飼料。在信息學里面,Feed其實是一個信息單元,比如一條朋友圈狀態、一條微博、一條咨詢或一條短視頻等,所以Feed流就是不停更新的信息單元,只要關注某些發布者就能獲取到源源不斷的新鮮信息,我們的用戶也就可以在移動設備上逐條去瀏覽這些信息單元。

當前最流行的Feed流產品有微博、微信朋友圈、頭條的資訊推薦、快手抖音的視頻推薦等,還有一些變種,比如私信、通知等,這些系統都是Feed流系統,接下來我們會介紹如何設計一個Feed流系統架構。

Feed流系統特點

Feed流本質上是一個數據流,是將 “N個發布者的信息單元” 通過 “關注關系” 傳送給 “M個接收者”。


image.png

Feed流系統是一個數據流系統,所以我們核心要看數據。從數據層面看,數據分為三類,分別是:

  • 發布者的數據:發布者產生數據,然后數據需要按照發布者組織,需要根據發布者查到所有數據,比如微博的個人頁面、朋友圈的個人相冊等。
  • 關注關系:系統中個體間的關系,微博中是關注,是單向流,朋友圈是好友,是雙向流。不管是單向還是雙向,當發布者發布一條信息時,該條信息的流動永遠是單向的。
  • 接收者的數據:從不同發布者那里獲取到的數據,然后通過某種順序(一般為時間)組織在一起,比如微博的首頁、朋友圈首頁等。這些數據具有時間熱度屬性,越新的數據越有價值,越新的數據就要排在最前面。

針對這三類數據,我們可以有如下定義:

  • 存儲庫:存儲發布者的數據,永久保存。
  • 關注表:用戶關系表,永久保存。
  • 同步庫:存儲接收者的時間熱度數據,只需要保留最近一段時間的數據即可。

設計Feed流系統時最核心的是確定清楚產品層面的定義,需要考慮的因素包括:

  • 產品用戶規模:用戶規模在十萬、千萬、十億級時,設計難度和側重點會不同。
  • 關注關系(單向、雙寫):如果是雙向,那么就不會有大V,否則會有大V存在。

上述是選擇數據存儲系統最核心的幾個考慮點,除此之外,還有一些需要考慮的:

  • 如何實現Meta和Feed內容搜索?
    雖然Feed流系統本身可以不需要搜索,但是一個Feed流產品必須要有搜索,否則信息發現難度會加大,用戶留存率會大幅下降。
  • Feed流的順序是時間還是其他分數,比如個人的喜好程度?
    雙向關系時由于關系很緊密,一定是按時間排序,就算一個關系很緊密的人發了一條空消息或者低價值消息,那我們也會需要關注了解的。
  • 單向關系時,那么可能就會存在大V,大V的粉絲數量理論極限就是整個系統的用戶數,有一些產品會讓所有用戶都默認關注產品負責人,這種產品中,該負責人就是最大的大V,粉絲數就是用戶規模。

接下來,我們看看整個Feed流系統如何設計。

Feed流系統設計

上一節,我們提前思考了Feed流系統的幾個關鍵點,接下來,在這一節,我們自頂向下來設計一個Feed流系統。

1. 產品定義

第一步,我們首先需要定義產品,我們要做的產品是哪一種類型,常見的類型有:

  • 微博類
  • 朋友圈類
  • 抖音類
  • 私信類

接著,再詳細看一下這幾類產品的異同:


image.png

上述對比中,只對比各類產品最核心、或者最根本特點,其他次要的不考慮。比如微博中互相關注后就是雙向關注了,但是這個不是微博的立命之本,只是補充,無法撼動根本。

從上面表格可以看出來,主要分為兩種區分:

關注關系是單向還是雙向:
如果是單向,那么可能就會存在大V效應,同時時效性可以低一些,比如到分鐘級別;
如果是雙向,那就是好友,好友的數量有限,那么就不會有大V,因為每個人的精力有限,他不可能主動加幾千萬的好友,這時候因為關系更精密,時效性要求會更高,需要都秒級別。
排序是時間還是推薦:
用戶對feed流最容易接受的就是時間,目前大部分都是時間。
但是有一些場景,是從全網數據里面根據用戶的喜好給用戶推薦和用戶喜好度最匹配的內容,這個時候就需要用推薦了,這種情況一般也會省略掉關注了,相對于關注了全網所有用戶,比如抖音、頭條等。
確定了產品類型后,還需要繼續確定的是系統設計目標:需要支持的最大用戶數是多少?十萬、百萬、千萬還是億?

用戶數很少的時候,就比較簡單,這里我們主要考慮 億級用戶 的情況,因為如果系統能支持億級,那么其他量級也能支持。為了支持億級規模的用戶,主要子系統選型時需要考慮水平擴展能力以及一些子系統的可用性和可靠性了,因為系統大了后,任何一個子系統的不穩定都很容易波及整個系統。

2. 存儲

我們先來看看最重要的存儲,不管是哪種同步模式,在存儲上都是一樣的,我們定義用戶消息的存儲為存儲庫。存儲庫主要滿足三個需求:

  • 可靠存儲用戶發送的消息,不能丟失。否則就找不到自己曾經發布到朋友圈狀態了。
  • 讀取某個人發布過的所有消息,比如個人主頁等。
  • 數據永久保存。

所以,存儲庫最重要的特征就是兩點:

  • 數據可靠、不丟失。
  • 由于數據要永久保存,數據會一直增長,所以要易于水平擴展。

綜上,可以選為存儲庫的系統大概有兩類:


image.png
  • 對于可靠性,分布式NoSQL的可靠性要高于關系型數據庫,這個可能有違很多人的認知。主要是關系型數據庫發展很長時間了,且很成熟了,數據放在上面大家放心,而分布式NoSQL數據庫發展晚,使用的并不多,不太信任。但是,分布式NoSQL需要存儲的數據量更多,對數據可靠性的要求也加嚴格,所以一般都是存儲三份,可靠性會更高。目前在一些云廠商中的關系型數據庫因為采用了和分布式NoSQL類似的方式,所以可靠性也得到了大幅提高。
  • 水平擴展能力:對于分布式NoSQL數據庫,數據天然是分布在多臺機器上,當一臺機器上的數據量增大后,可以通過自動分裂兩部分,然后將其中一半的數據遷移到另一臺機器上去,這樣就做到了線性擴展。而關系型數據庫需要在擴容時再次分庫分表。

所以,結論是:

  • 如果是自建系統,且不具備分布式NoSQL數據庫運維能力,且數據規模不大,那么可以使用MySQL,這樣可以撐一段時間。
  • 如果是基于云服務,那么就用分布式NoSQL,比如Tablestore或Bigtable。
  • 如果數據規模很大,那么也要用分布式NoSQL,否則就是走上一條不歸路。

如果使用Tablestore,那么存儲庫表設計結構如下:


image.png

到此,我們確定了存儲庫的選型,那么系統架構的輪廓有了:


image.png

3. 同步

系統規模和產品類型,以及存儲系統確定后,我們可以確定同步方式,常見的方式有三種:

  • 推模式(也叫寫擴散):和名字一樣,就是一種推的方式,發送者發送了一個消息后,立即將這個消息推送給接收者,但是接收者此時不一定在線,那么就需要有一個地方存儲這個數據,這個存儲的地方我們稱為:同步庫。推模式也叫寫擴散的原因是,一個消息需要發送個多個粉絲,那么這條消息就會復制多份,寫放大,所以也叫寫擴散。這種模式下,對同步庫的要求就是寫入能力極強和穩定。讀取的時候因為消息已經發到接收者的收件箱了,只需要讀一次自己的收件箱即可,讀請求的量極小,所以對讀的QPS需求不大。歸納下,推模式中對同步庫的要求只有一個:寫入能力強。
  • 拉模式(也叫讀擴散):這種是一種拉的方式,發送者發送了一條消息后,這條消息不會立即推送給粉絲,而是寫入自己的發件箱,當粉絲上線后再去自己關注者的發件箱里面去讀取,一條消息的寫入只有一次,但是讀取最多會和粉絲數一樣,讀會放大,所以也叫讀擴散。拉模式的讀寫比例剛好和寫擴散相反,那么對系統的要求是:讀取能力強。另外這里還有一個誤區,很多人在最開始設計feed流系統時,首先想到的是拉模式,因為這種和用戶的使用體感是一樣的,但是在系統設計上這種方式有不少痛點,最大的是每個粉絲需要記錄自己上次讀到了關注者的哪條消息,如果有1000個關注者,那么這個人需要記錄1000個位置信息,這個量和關注量成正比的,遠比用戶數要大的多,這里要特別注意,雖然在產品前期數據量少的時候這種方式可以應付,但是量大了后就會事倍功半,得不償失,切記切記。
  • 推拉結合模式:推模式在單向關系中,因為存在大V,那么一條消息可能會擴散幾百萬次,但是這些用戶中可能有一半多是僵尸,永遠不會上線,那么就存在資源浪費。而拉模式下,在系統架構上會很復雜,同時需要記錄的位置信息是天量,不好解決,尤其是用戶量多了后會成為第一個故障點。基于此,所以有了推拉結合模式,大部分用戶的消息都是寫擴散,只有大V是讀擴散,這樣既控制了資源浪費,又減少了系統設計復雜度。但是整體設計復雜度還是要比推模式復雜。

用圖表對比:


image.png

介紹完同步模式中所有場景和模式后,我們歸納下:

  • 如果產品中是雙向關系,那么就采用推模式。
  • 如果產品中是單向關系,且用戶數少于1000萬,那么也采用推模式,足夠了。
  • 如果產品是單向關系,單用戶數大于1000萬,那么采用推拉結合模式,這時候可以從推模式演進過來,不需要額外重新推翻重做。
  • 永遠不要只用拉模式。
  • 如果是一個初創企業,先用推模式,快速把系統設計出來,然后讓產品去驗證、迭代,等客戶數大幅上漲到1000萬后,再考慮升級為推拉集合模式。
  • 如果是按推薦排序,那么是另外的考慮了,架構會完全不一樣,這個后面專門文章介紹。

如果選擇了Tablestore,那么同步庫表設計結構如下:


image.png

確定了同步庫的架構如下:


image.png

image.png

確定了同步庫的架構如下:
image.png

4. 元數據

前面介紹了同步和存儲后,整個Feed流系統的基礎功能完成了,但是對于一個完整Feed流產品而言,還缺元數據部分,接下來,我們看元數據如何處理:

Feed流系統中的元數據主要包括:

  • 用戶詳情和列表。
  • 關注或好友關系。
  • 推送session池。

我們接下來逐一來看。

4.1 用戶詳情和列表

主要是用戶的詳情,包括用戶的各種自定義屬性和系統附加的屬性,這部分的要求只需要根據用戶ID查詢到就可以了。

可以采用的分布式NoSQL系統或者關系型數據庫都可以。

如果使用NoSQL數據庫Tablestore,那么用戶詳情表設計結構如下:


image.png
4.2 關注或好友關系

這部分是存儲關系,查詢的時候需要支持查詢關注列表或者粉絲列表,或者直接好友列表,這里就需要根據多個屬性列查詢需要索引能力,這里,存儲系統也可以采用兩類,關系型、分布式NoSQL數據庫。

  • 如果已經有了關系型數據庫了,且數據量較少,則選擇關系型數據庫,比如MySQL等。
  • 如果數據量比較大,這個時候就有兩種選擇:

1: 使用具有索引的系統,比如云上的Tablestore,更簡單,吞吐更高,擴容能力也一并解決了。
2: 需要分布式事務,可以采用支持分布式事務的系統,比如分布式關系型數據庫。

如果使用Tablestore,那么關注關系表設計結構如下:
Table:user_relation_table


image.png

多元索引的索引結構:


image.png

查詢的時候:
  • 如果需要查詢某個人的粉絲列表:使用TermQuery查詢固定user_id,且按照timestamp排序。
  • 如果需要查詢某個人的關注列表:使用TermQuery查詢固定follow_user_id,且按照timestamp排序。
  • 當前數據寫入Table后,需要5~10秒鐘延遲后會在多元索引中查詢到,未來會優化到2秒以內。

除了使用多元索引外,還可以使用GlobalIndex。

4.3 推送session池

思考一個問題,發送者將消息發送后,接收者如何知道自己有新消息來了?客戶端周期性去刷新?如果是這樣子,那么系統的讀請求壓力會隨著客戶端增長而增長,這時候就會有一個風險,比如平時的設備在線率是20%~30%,突然某天平臺爆發了一個熱點消息,大量休眠設備登陸,這個時候就會出現“查詢風暴”,一下子就把系統打垮了,所有的用戶都不能用了。

解決這個問題的一個思路是,在服務端維護一個推送session池,這個里面記錄哪些用戶在線,然后當用戶A發送了一條消息給用戶B后,服務端在寫入存儲庫和同步庫后,再通知一下session池中的用戶B的session,告訴他:你有新消息了。然后session-B再去讀消息,然后有消息后將消息推送給客戶端。或者有消息后給客戶端推送一下有消息了,客戶端再去拉。

這個session池使用在同步中,但是本質還是一個元數據,一般只需要存在于內存中即可,但是考慮到failover情況,那就需要持久化,這部分數據由于只需要指定單Key查詢,用分布式NoSQL或關系型數據庫都可以,一般復用當前的系統即可。

如果使用Tablestore,那么session表設計結構如下:


image.png
4.3 推送session池

思考一個問題,發送者將消息發送后,接收者如何知道自己有新消息來了?客戶端周期性去刷新?如果是這樣子,那么系統的讀請求壓力會隨著客戶端增長而增長,這時候就會有一個風險,比如平時的設備在線率是20%~30%,突然某天平臺爆發了一個熱點消息,大量休眠設備登陸,這個時候就會出現“查詢風暴”,一下子就把系統打垮了,所有的用戶都不能用了。

解決這個問題的一個思路是,在服務端維護一個推送session池,這個里面記錄哪些用戶在線,然后當用戶A發送了一條消息給用戶B后,服務端在寫入存儲庫和同步庫后,再通知一下session池中的用戶B的session,告訴他:你有新消息了。然后session-B再去讀消息,然后有消息后將消息推送給客戶端。或者有消息后給客戶端推送一下有消息了,客戶端再去拉。

這個session池使用在同步中,但是本質還是一個元數據,一般只需要存在于內存中即可,但是考慮到failover情況,那就需要持久化,這部分數據由于只需要指定單Key查詢,用分布式NoSQL或關系型數據庫都可以,一般復用當前的系統即可。

如果使用Tablestore,那么session表設計結構如下:


image.png

5. 評論

除了私信類型外,其他的feed流類型中,都有評論功能,評論的屬性和存儲庫差不多,但是多了一層關系:被評論的消息,所以只要將評論按照被被評論消息分組組織即可,然后查詢時也是一個范圍查詢就行。這種查詢方式很簡單,用不到關系型數據庫中復雜的事務、join等功能,很適合用分布式NoSQL數據庫來存儲。
所以,一般的選擇方式就是:

  • 如果系統中已經有了分布式NoSQL數據庫,比如Tablestore、Bigtable等,那么直接用這些即可。
  • 如果沒有上述系統,那么如果有MySQL等關系型數據庫,那就選關系型數據庫即可。
  • 如果選擇了Tablestore,那么“評論表”設計結構如下:


    image.png

    如果需要搜索評論內容,那么對這張表建立多元索引即可。

6. 贊

最近幾年,“贊”或“like”功能很流行,贊功能的實現和評論類似,只是比評論少了一個內容,所以選擇方式和評論一樣。
如果選擇了Tablestore,那么“贊表”設計結構同評論表,這里就不再贅述了。
系統架構中加了元數據系統后的架構如下:


image.png
7. 搜索

到此,我們已經介紹完了Feed流系統的主題架構,Feed流系統算是完成了。但是Feed流產品上還未結束,對于所有的feed流產品都需要有搜索能力,比如下面場景:

  • 微博中的搜索用戶。
  • 搜索微博內容。
  • 微信中搜索好友等。

這些內容搜索只需要字符匹配到即可,不需要非常復雜的相關性算法,所以只需要有能支持分詞的檢索功能即可,所以一般有兩種做法:

  • 使用搜索引擎,將存儲庫的內容和用戶信息表內容推送給搜索系統,搜索的時候直接訪問搜索系統。
  • 使用具備全文檢索能力的數據庫,比如最新版的MySQL、MongoDB或者Tablestore。

所以,選擇的原則如下:

  • 如果存儲庫使用了MySQL或者Tablestore,那么直接選擇這兩個系統就可以了。
  • 如果整個系統都沒使用MySQL、Tablestore,且已經使用了搜索系統,那么可以直接復用搜索系統,其他場景都不應該再額外加一個搜索系統進來,徒添復雜度。

如果使用Tablestore,那么只需要在相應表上建立多元索引即可:

  • 如果需要對用戶名支持搜索,那么需要對user_table建立多元索引,其中的nick_name需要是Text類型,且單字分詞。
  • 如果需要對Feed流內容支持搜索,那么需要對存儲庫表:store_table建立多元索引,這樣就能直接對Feed流內容進行各種復雜查詢了,包括多條件篩選、全文檢索等。

系統架構中加了搜索功能后的架構如下:


image.png

8. 排序

目前的Feed流系統中的排序方式有兩種,一種是時間,一種是分數。

我們常用的微博、朋友圈、私信這些都是時間線類型的,因為這些產品定義中,需要我們主動關注某些人后才會看到這些人發表的內容,這個時候,最重要的是實時性,而不是發布質量,就算關注人發布了一條垃圾信息,我們也會被動看到。這種類型的產品適用于按照時間線排序。這一篇我們介紹的架構都是基于時間類型的。

另外一種是不需要關注任何人,我們能看到的都是系統希望我們看到的,系統在后臺會分析我們的每個人的愛好,然后給每個人推送差異化的、各自喜歡的內容,這一種的架構和基于時間的完全不一樣,我們在后續的推薦類型中專門介紹。

9. 刪除Feed內容

在Feed流應用中有一個問題,就是如果用戶刪除了之前發表的內容,系統該如何處理?因為系統里面有寫擴散,那么刪除的時候是不是也要寫擴散一遍?這樣的話,刪除就不及時了,很難應對法律法規要求的快速刪除。

針對這個問題,我們在之前設計的時候,同步表中只有消息ID,沒有消息內容,在用戶讀取的時候需要到存儲庫中去讀消息內容,那么我們可以直接刪除存儲庫中的這一條消息,這樣用戶讀取的時候使用消息ID是讀不到數據的,也就相當于刪除的內容,而且刪除速度會很快。除了直接刪除外,另外一種辦法是邏輯刪除,對于刪除的feed內容,只做標記,當查詢到帶有標記的數據時就認為刪除了。

10. 更新Feed內容

更新和刪除Feed處理邏輯一樣,如果使用了支持多版本的存儲系統,比如Tablestore,那么也可以支持編輯版本,和現在的微博一樣。

11. 總結

上面介紹了不同子功能的特點和系統要求,能滿足需求的系統主要有兩類,一類是阿里云的Tablestore單系統,一類是開源組件組成的組合系統。

  • 開源組件組成的組合系統:包括MySQL、RedisHBase等,這些系統單個都不能解決Feed流系統中遇到的問題,需要組合在一起,各司其職才能完成一個Feed流系統,適用于熱衷開源系統,人多且喜歡運維操作的團隊。
  • Tablestore單系統:只使用Tablestore單個系統就能解決上述的所有問題,這時候肯定有人要問?你是不是在吹牛?這里不是吹牛,Tablestore在三年前就已經開始重視Feed流類型業務,之前也發表過多篇文章介紹,功能上也在專門為Feed流系統特別定制設計,所以到今天,只使用Tablestore一款產品,是可以滿足上述需求的。選擇Tablestore做Feed流系統的用戶具有以下一些特征: 產品設計目標規模大,千萬級或億級。 不喜歡運維,喜歡專注于開發。 高效率團隊,希望盡快將產品實現落地。 希望一勞永逸,未來系統隨著用戶規模增長可以自動擴容。 希望能按量付費,用戶少的時候費用低,等用戶增長起來后費用在跟隨用戶數增長。 如果具有上述四個特征的任何一個,那么都是適合于用Tablestore。

架構實踐

上面我們介紹了Feed流系統的設計理論,具體到不同的類型中,會有不同的側重點,下面會逐一介紹。

朋友圈

朋友圈是一種典型的Feed流系統,關系是雙寫關系,關系有上限,排序按照時間,如果有個人持續產生垃圾內容,那就只能屏蔽掉TA,這一種類型就是典型的寫擴散模型。
我們接下來會在文章《朋友圈類系統架構設計》中詳細介紹朋友圈類型Feed流系統的設計。

微博

微博也是一種非常典型的Feed流系統,但不同于朋友圈,關系是單向的,那么也就會產生大V,這個時候就需要讀寫擴散模式,用讀擴散解決大V問題。同時,微博也是主動關注類型的產品,所以排序也只能是時間,如果按照推薦排序,那么效果就會比較差。
接下里會在文章《微博類系統架構設計》中詳細介紹微博類型Feed流系統的設計。

頭條

頭條是最近幾年快速崛起的一款應用,在原有微博的Feed流系統上產生了進化,用戶不需要主動關注其他人,只要初始瀏覽一些內容后,系統就會自動判斷出你的喜好,然后后面再根據你的喜好給你推薦你可能會喜好的內容,訓練時間長了后,推送的內容都會是你最喜歡看的。
后面,我們會在文章《頭條類系統架構設計》中詳細介紹頭條類型Feed流系統的設計。

私信

私信也算是一種簡單的Feed流系統,或者也可以認為是一種變相的IM,都是單對單的,沒有群。我們后面也會有一篇文章《私信類系統架構設計》中做詳細介紹。

總結

上面我們介紹了Feed流系統的整體框架,主要是產品定義、同步、存儲、元數據、評論、贊、排序和搜索等內容,由于篇幅有限,每一章節都介紹的比較簡單。讀者如果對某一部分看完后仍然有疑問,可以繼續再文后提問,我會繼續去完善這篇文章,希望未來讀者看完這篇文章后,就可以輕輕松松設計出一個億級規模的Feed流系統。
另外,我們也歡迎有興趣的讀者一起來完成這個系列,幫忙實現朋友圈、微博、頭條或者私信類型的文章,有任何問題都歡迎來討論。

延伸

Feed類型的系統架構和IM(即時聊天)類型的系統架構非常類似,自從Tablestore從2016年開始優化此類系統,我們研發了Feed流和IM的通用底層框架-Timeline,目前已經演進到了V2版本,一體化支持存儲、同步和搜索功能,我們已經有文章做了介紹:

《億級消息系統的核心存儲:Tablestore發布Timeline 2.0模型》

https://yq.aliyun.com/articles/692900

《現代IM系統中的消息系統架構 - 架構篇》

https://yq.aliyun.com/articles/698301

《現代IM系統中的消息系統架構 - 模型篇》

https://yq.aliyun.com/articles/701593

《Tablestore權威指南》

https://yq.aliyun.com/articles/699676

轉自:https://cloud.tencent.com/developer/article/1461822?from=article.detail.1744756

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容