Feed數(shù)據(jù)架構(gòu)模型

Feed流:可以理解為信息流役纹,解決的是信息生產(chǎn)者與信息消費(fèi)者之間的信息傳遞問題护戳。

我們常見的Feed流場景有:

1 手淘,微淘提供給消費(fèi)者的首頁商品信息缭付,用戶關(guān)注店鋪的新消息等

2 微信朋友圈鉴竭,及時(shí)獲取朋友分享的信息

3 微博歧譬,粉絲獲取關(guān)注明星、大V的信息

4 頭條搏存,用戶獲取系統(tǒng)推薦的新聞瑰步、評論、八卦

關(guān)于Feed流的架構(gòu)設(shè)計(jì)璧眠,包括以上場景中的很多業(yè)內(nèi)專家給出了相應(yīng)的思考缩焦、設(shè)計(jì)和實(shí)踐读虏。本人是大數(shù)據(jù)方向出身的技術(shù)人,所在的團(tuán)隊(duì)參與了阿里手淘袁滥、微淘Feed流的存儲層相關(guān)服務(wù)盖桥,我們的HBase/Lindorm數(shù)據(jù)存儲產(chǎn)品在公有云上也支持著Soul、趣頭條呻拌、惠頭條等一些受歡迎的新媒體葱轩、社交類產(chǎn)品。我們在數(shù)據(jù)存儲產(chǎn)品的功能藐握、性能、可用性上的一些理解垃喊,希望對真實(shí)落地一個(gè)Feed流架構(gòu)可以有一些幫助猾普,以及一起探討Feed流的未來以及數(shù)據(jù)產(chǎn)品如何幫助Feed流進(jìn)一步迭代。

本文希望可以提供兩點(diǎn)價(jià)值:

1 Feed流當(dāng)前的主流架構(gòu)以及落地方案

2 一個(gè)初創(chuàng)公司如何選擇Feed流的架構(gòu)演進(jìn)路徑

業(yè)務(wù)分析

Feed流參與者的價(jià)值

信息生產(chǎn)者

希望信息支持格式豐富(文字本谜、圖片初家、視頻),發(fā)布流暢(生產(chǎn)信息的可用性)乌助,訂閱者及時(shí)收到消息(時(shí)效性)溜在,訂閱者不漏消息(傳遞的可靠性)

信息消費(fèi)者

希望及時(shí)收到關(guān)注的消息(時(shí)效性),希望不錯(cuò)過朋友他托、偶像的消息(傳遞的可靠性)掖肋,希望獲得有價(jià)值的消息(解決信息過載)

平臺

希望吸引更多的生產(chǎn)者和消費(fèi)者(PV、UV)赏参,用戶更長的停留時(shí)間志笼,廣告、商品更高的轉(zhuǎn)化率

Feed信息傳遞方式

一種是基于關(guān)系的消息傳遞把篓,關(guān)系通過加好友纫溃、關(guān)注、訂閱等方式建立韧掩,可能是雙向的也可能是單向的紊浩。一種是基于推薦算法的,系統(tǒng)根據(jù)用戶畫像疗锐、消息畫像利用標(biāo)簽分類或者協(xié)同過濾等算法向用戶推送消息坊谁。微信和微博偏向于基于關(guān)系,頭條窒悔、抖音偏向于基于推薦呜袁。

Feed流的技術(shù)難點(diǎn)

互聯(lián)網(wǎng)場景總是需要一定規(guī)模才能體現(xiàn)出技術(shù)的瓶頸,下面我們先看兩組公開數(shù)據(jù):

新浪微博為例简珠,作為移動(dòng)社交時(shí)代的重量級社交分享平臺阶界,2017年初日活躍用戶1.6億虹钮,月活躍用戶近3.3億,每天新增數(shù)億條數(shù)據(jù)膘融,總數(shù)據(jù)量達(dá)千億級芙粱,核心單個(gè)業(yè)務(wù)的后端數(shù)據(jù)訪問QPS高達(dá)百萬級

(來自?Feed系統(tǒng)架構(gòu)與Feed緩存模型

截止2016年12月底,頭條日活躍用戶7800W氧映,月活躍用戶1.75億春畔,單用戶平均使用時(shí)長76分鐘,用戶行為峰值150w+msg/s岛都,每天訓(xùn)練數(shù)據(jù)300T+(壓縮后)律姨,機(jī)器規(guī)模萬級別

(來自?今日頭條推薦系統(tǒng)架構(gòu)設(shè)計(jì)實(shí)踐

上面還是兩大巨頭的歷史指標(biāo),假設(shè)一條消息1KB那么千億消息約93TB的數(shù)據(jù)量臼疫,日增量在幾百GB規(guī)模且QPS高達(dá)百萬择份,因此需要一個(gè)具備高讀寫吞吐,擴(kuò)展性良好的分布式存儲系統(tǒng)烫堤。用戶瀏覽新消息期望百毫秒響應(yīng)荣赶,希望新消息在秒級或者至少1分鐘左右可見,對系統(tǒng)的實(shí)時(shí)性要求很高鸽斟,這里需要多級的緩存架構(gòu)拔创。系統(tǒng)必須具備高可用,良好的容錯(cuò)性富蓄。最后這個(gè)系統(tǒng)最好不要太貴剩燥。

因此我們需要一個(gè)高吞吐、易擴(kuò)展格粪、低延遲躏吊、高可用、低成本的Feed流架構(gòu)

主流架構(gòu)

圖1是對Feed流的最簡單抽象帐萎,完成一個(gè)從生產(chǎn)者向消費(fèi)者傳遞消息的過程比伏。

圖1 Feed流簡單抽象

消息和關(guān)系

首先,用戶在APP側(cè)獲得的是一個(gè)Feed ID列表疆导,這個(gè)列表不一定包含了所有的新消息赁项,用戶也不一定每一個(gè)都打開瀏覽,如果傳遞整個(gè)消息非常浪費(fèi)資源澈段,因此產(chǎn)生出來的消息首先生成主體和索引兩個(gè)部分悠菜,其中索引包含了消息ID和元數(shù)據(jù)。其次一個(gè)應(yīng)用總是存在關(guān)系败富,基于關(guān)系的傳遞是必不可少的悔醋,也因此一定有一個(gè)關(guān)系的存儲和查詢服務(wù)。

圖2 Feed流消息兽叮、關(guān)系的存儲

消息本身應(yīng)該算是一種半結(jié)構(gòu)化數(shù)據(jù)(包含文字芬骄,圖片猾愿,短視頻,音頻账阻,元數(shù)據(jù)等)蒂秘。其讀寫吞吐量要求高,讀寫比例需要看具體場景淘太∫錾總的存儲空間大,需要很好的擴(kuò)展性來支撐業(yè)務(wù)增長蒲牧。消息可能會有多次更新撇贺,比如內(nèi)容修改,瀏覽數(shù)冰抢,點(diǎn)贊數(shù)显熏,轉(zhuǎn)發(fā)數(shù)(成熟的系統(tǒng)會獨(dú)立一個(gè)counter模塊來服務(wù)這些元數(shù)據(jù))以及標(biāo)記刪除。消息一般不會永久保存晒屎,可能要在1年或者3年后刪除。

綜上缓升,個(gè)人推薦使用HBase存儲

HBase支持結(jié)構(gòu)化和半結(jié)構(gòu)化數(shù)據(jù)鼓鲁;

具有非常好的寫入性能,特別對于Feed流場景可以利用批量寫接口單機(jī)(32核64GB)達(dá)到幾十萬的寫入效率港谊;

HBase具備非常平滑的水平擴(kuò)展能力骇吭,自動(dòng)進(jìn)行Sharding和Balance;

HBase內(nèi)置的BlockCache加上SSD盤可以提供ms級的高并發(fā)讀歧寺;

HBase的TTL特性可以自動(dòng)的淘汰過期數(shù)據(jù)燥狰;

利用數(shù)據(jù)復(fù)制搭建一個(gè)冷熱分離系統(tǒng),新消息存儲在擁有SSD磁盤和大規(guī)格緩存的熱庫斜筐,舊數(shù)據(jù)存儲在冷庫龙致。

運(yùn)用編碼壓縮有效的控制存儲成本,見HBase優(yōu)化之路-合理的使用編碼壓縮

圖3 使用HBase存儲Feed流消息

對于關(guān)系服務(wù)顷链,其寫入操作是建立關(guān)系和刪除關(guān)系目代,讀取操作是獲取關(guān)系列表,邏輯上僅需要一個(gè)KV系統(tǒng)嗤练。如果數(shù)據(jù)量較少可以使用RDS榛了,如果數(shù)據(jù)量較大推薦使用HBase。如果對關(guān)系的QPS壓力大可以考慮用Redis做緩存煞抬。

圖4 用戶關(guān)系存儲

消息傳遞

講到Feed流一定會有關(guān)于推模式和拉模式的討論霜大,推模式是把消息復(fù)制N次發(fā)送到N個(gè)用戶的收信箱,用戶想看消息時(shí)從自己的收信箱直接獲取革答。拉模式相反战坤,生產(chǎn)者的消息寫入自己的發(fā)信箱曙强,用戶想看消息時(shí)從關(guān)注的M個(gè)發(fā)信箱中收集消息。

圖5 消息傳遞的推模式和拉模式

推模式實(shí)現(xiàn)相對簡單湖笨,時(shí)效性也比較好旗扑。拉模式要想獲得好的性能需要多級的緩存架構(gòu)。推模式重寫慈省,拉模式重讀臀防,F(xiàn)eed流場景下寫的聚合效果要優(yōu)于讀,寫可以大批量聚合边败。N越大袱衷,寫入造成的數(shù)據(jù)冗余就越大。M越大笑窜,讀消耗的資源越大致燥。

隨著業(yè)務(wù)的增長,推模式資源浪費(fèi)會越發(fā)嚴(yán)重排截。原因在于兩點(diǎn):第一存在著大量的僵尸賬號嫌蚤,以及大比例的非活躍用戶幾天或者半個(gè)月才登陸一次;第二信息過載断傲,信息太多脱吱,重復(fù)信息太多,垃圾信息太多认罩,用戶感覺有用的信息少箱蝠,消息的閱讀比例低。這種情況下推模式相當(dāng)一部分在做無用功垦垂,白白浪費(fèi)系統(tǒng)資源宦搬。

是推?是拉劫拗?還是混合间校?沒有最好的架構(gòu),只有適合的場景~

基于關(guān)系的傳遞

圖6是純推模式的架構(gòu)杨幼,該架構(gòu)有3個(gè)關(guān)鍵的部分

異步化撇簿。生產(chǎn)者提交消息首先寫入一個(gè)隊(duì)列,成功則表示發(fā)布成功差购,Dispatcher模塊會異步的處理消息四瘫。這一點(diǎn)非常關(guān)鍵,首先生產(chǎn)者的消息發(fā)布體驗(yàn)非常好欲逃,不需要等待消息同步到粉絲的收信箱找蜜,發(fā)布延遲低成功率高;其次Dispatcher可以控制隊(duì)列的處理速度稳析,可以有效的控制大V賬號造成的脈沖壓力洗做。

多級隊(duì)列弓叛。Dispatcher可以根據(jù)消費(fèi)者的狀態(tài),信息的分類等劃分不同的處理方式诚纸,分配不同的資源撰筷。比如對于大V賬號的消息,當(dāng)前活躍用戶選擇直接發(fā)送畦徘,保障消息的時(shí)效性毕籽,非活躍用戶放入隊(duì)列延遲發(fā)送。比如轉(zhuǎn)發(fā)多的消息可以優(yōu)先處理等井辆。隊(duì)列里的消息可以采用批量聚合寫的方式提高吞吐关筒。

收信箱。假如有兩億用戶杯缺,每個(gè)用戶保留最新2000條推送消息蒸播。即便存儲的是索引也是千億的規(guī)模痊乾。收信箱一般的表結(jié)構(gòu)為用戶ID+消息序列 + 消息ID + 消息元數(shù)據(jù)圈浇,消息序列是一個(gè)遞增的ID,需要存儲一個(gè)偏移量表示上次讀到的消息序列ID溉痢。用戶讀取最新消息 select * from inbox where 消息序列 > offset塘揣。

圖6 基于關(guān)系傳遞的純推模式

推薦使用HBase實(shí)現(xiàn)收信箱

HBase單機(jī)批量寫能力在幾十萬并且可以水平擴(kuò)展蜡塌。

HBase的高效前綴掃描非常適合讀取最新的消息。

HBase的TTL功能可以對數(shù)據(jù)定義生命周期勿负,高效的淘汰過期數(shù)據(jù)。

HBase的Filter過濾器和二級索引可以有效的實(shí)現(xiàn)Inbox的搜索能力劳曹。

消費(fèi)者收信箱hbase表設(shè)計(jì)如下奴愉,其中序列號要保證遞增,一般用時(shí)間戳即可铁孵,特別高頻情況下可以用一個(gè)RDS來制造序列號

Rowkey消息元數(shù)據(jù)列狀態(tài)列其它列

MD5(用戶ID)+用戶ID+序列號消息ID锭硼、作者、發(fā)布時(shí)間蜕劝、關(guān)鍵字等已讀檀头、未讀

圖7是推拉結(jié)合的模式

增加發(fā)信箱,大V的發(fā)布進(jìn)入其獨(dú)立的發(fā)信箱岖沛。非大V的發(fā)布直接發(fā)送到用戶的收信箱暑始。其好處是解決大量的僵尸賬號和非活躍賬號的問題。用戶只有在請求新消息的時(shí)候(比如登陸婴削、下拉消息框)才會去消耗系統(tǒng)資源廊镜。

發(fā)信箱的多級緩存架構(gòu)。一個(gè)大V可能有百萬粉絲唉俗,一條熱點(diǎn)消息的傳播窗口也會非常短嗤朴,即短時(shí)間內(nèi)會對發(fā)信箱中的同一條消息大量重復(fù)讀取配椭,對系統(tǒng)挑戰(zhàn)很大。終態(tài)下我們可能會選擇兩級緩存雹姊,收信箱數(shù)據(jù)還是要持久化的股缸,否則升級或者宕機(jī)時(shí)數(shù)據(jù)就丟失了,所以第一層是一個(gè)分布式數(shù)據(jù)存儲吱雏,這個(gè)存儲推薦使用HBase敦姻,原因和Inbox類似。第二層使用redis緩存加速坎背,但是大V過大可能造成熱點(diǎn)問題還需要第三層本地緩存替劈。緩存層的優(yōu)化主要包括兩個(gè)方向:第一提高緩存命中率,常用的方式是對數(shù)據(jù)進(jìn)行編碼壓縮得滤,第二保障緩存的可用性陨献,這里涉及到對緩存的冗余。

圖7 基于關(guān)系傳遞的推拉混合模式

基于推薦的傳遞

圖8是基于推薦的模型懂更,可以看出它是在推拉結(jié)合的模式上融合了推薦系統(tǒng)眨业。

引入畫像系統(tǒng),保存用戶畫像沮协、消息畫像(簡單情況下消息畫像可以放在消息元數(shù)據(jù)中)龄捡。畫像用于推薦系統(tǒng)算法的輸入。

引入了臨時(shí)收信箱慷暂,在信息過載的場景中聘殖,非大V的消息也是總量很大,其中不免充斥著垃圾行瑞、冗余消息奸腺,所以直接進(jìn)入用戶收信箱不太合適。

收信箱和發(fā)信箱都需要有良好的搜索能力血久,這是推薦系統(tǒng)高效運(yùn)行的關(guān)鍵突照。Outbox有緩存層,索引可以做到緩存里面氧吐;Inbox一般情況下二級索引可以滿足大部分需求讹蘑,但如果用戶希望有全文索引或者任意維度的檢索能力,還需要引入搜索系統(tǒng)如Solr/ES

圖8 基于推薦的Feed流架構(gòu)

用戶畫像使用HBase存儲

畫像一般是稀疏表筑舅,畫像總維度可能在200+甚至更多座慰,但單個(gè)用戶的維度可能在幾十,并且維度可能隨業(yè)務(wù)不斷變化翠拣。那么HBase的Schema free和稀疏表的能力非常適合這個(gè)場景角骤,易用且節(jié)省大量存儲空間。

對畫像的訪問一般是單行讀,hbase本身單行Get的性能就非常好邦尊。阿里云HBase在這個(gè)方向上做了非常多的優(yōu)化背桐,包括CCSMAP、SharedBucketCache蝉揍、MemstoreBloomFilter链峭、Index Encoding等,可以達(dá)到平均RT=1-2ms又沾,單庫99.9% <100ms弊仪。阿里內(nèi)部利用雙集群Dual Service可以做到 99.9% < 30ms,這一能力我們也在努力推到公有云杖刷。hbase的讀吞吐隨機(jī)器數(shù)量水平擴(kuò)展励饵。

臨時(shí)收信箱使用云HBase

HBase的讀寫高吞吐、低延遲能力滑燃,這里不再重復(fù)役听。

HBase提供Filter和全局二級索引,滿足不同量級的搜索需求表窘。

阿里云HBase融合HBase與Solr能力典予,提供低成本的全文索引、多維索引能力乐严。

初創(chuàng)公司的迭代路徑

在業(yè)務(wù)發(fā)展的初期瘤袖,用戶量和資源都沒有那么多,團(tuán)隊(duì)的人力投入也是有限的昂验,不可能一上來就搞一個(gè)特別復(fù)雜的架構(gòu)捂敌,“夠用”就行了,重要的是

可以快速的交付

系統(tǒng)要穩(wěn)定

未來可以從容的迭代既琴,避免推倒重來

本人水平有限黍匾,根據(jù)自身的經(jīng)驗(yàn)向大家推薦一種迭代路徑以供參考,如有不同意見歡迎交流

起步架構(gòu)如圖9呛梆,使用云Kafka+云HBase。如果對Inbox有檢索需求磕诊,建議使用HBase的scan+filter即可填物。

消息分為主體和索引

采用純推的模式

采用異步化

圖9 起步架構(gòu)

數(shù)據(jù)量逐漸增大后,對推模式進(jìn)一步迭代霎终,主要需求是

控制大V造成的寫入脈沖高峰

控制存儲成本

提升讀寫性能

提升一定的Inbox搜索能力

進(jìn)一步的迭代架構(gòu)如圖10

消息分為主體和索引

采用純推的模式

采用異步化

采用多級隊(duì)列解決大V問題

采用冷熱分離降低存儲成本

此時(shí)Inbox中的消息也很多滞磺,對搜索的需求增強(qiáng),僅僅Scan+Filter不夠莱褒,可能需要二級索引

圖10 純推模式的演進(jìn)

業(yè)務(wù)迅猛發(fā)展击困,消息和用戶增長迅速,僵尸賬號、非活躍賬號較多阅茶,信息過載嚴(yán)重

消息分為主體和索引

采用推拉結(jié)合模式

采用異步化

引入推薦系統(tǒng)

采用冷熱分離降低存儲成本

Outbox采用多級緩存提高讀取性能

Inbox增加二級索引提升搜索能力

使用云Kafka+云HBase+云Redis

圖11 基于推薦的推拉混合架構(gòu)

總結(jié)

Feed信息流是互聯(lián)網(wǎng)場景中非常普遍的場景蛛枚,遍布于電商、社交脸哀、新媒體等APP蹦浦,因此研究Feed流是非常有價(jià)值的一件事情。本文總結(jié)了Feed流的業(yè)務(wù)場景和主流架構(gòu)撞蜂,分析了不同場景盲镶、體量下技術(shù)的難點(diǎn)與瓶頸。對Dispatcher蝌诡、Inbox溉贿、Outout幾個(gè)組件進(jìn)行了詳細(xì)的演進(jìn)介紹,提供了基于云環(huán)境的落地方案浦旱。本人水平有限宇色,希望可以拋磚引玉,歡迎大家一起探討闽寡。Feed流的架構(gòu)演進(jìn)還在持續(xù)代兵,不同業(yè)務(wù)場景下還有哪些缺陷和痛點(diǎn)?數(shù)據(jù)產(chǎn)品如何從功能和性能上演進(jìn)來支撐Feed流的持續(xù)發(fā)展爷狈?在這些問題的驅(qū)動(dòng)下植影,云HBase未來將會大力投入到Feed流場景的持續(xù)優(yōu)化和賦能!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涎永,一起剝皮案震驚了整個(gè)濱河市思币,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌羡微,老刑警劉巖谷饿,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異妈倔,居然都是意外死亡博投,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門盯蝴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毅哗,“玉大人,你說我怎么就攤上這事捧挺÷敲啵” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵闽烙,是天一觀的道長翅睛。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么捕发? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任疏旨,我火速辦了婚禮,結(jié)果婚禮上爬骤,老公的妹妹穿的比我還像新娘充石。我一直安慰自己,他們只是感情好霞玄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布骤铃。 她就那樣靜靜地躺著,像睡著了一般坷剧。 火紅的嫁衣襯著肌膚如雪惰爬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天惫企,我揣著相機(jī)與錄音撕瞧,去河邊找鬼。 笑死狞尔,一個(gè)胖子當(dāng)著我的面吹牛丛版,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偏序,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼页畦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了研儒?” 一聲冷哼從身側(cè)響起豫缨,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎端朵,沒想到半個(gè)月后好芭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冲呢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年舍败,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敬拓。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邻薯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出恩尾,到底是詐尸還是另有隱情,我是刑警寧澤挽懦,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布翰意,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏冀偶。R本人自食惡果不足惜醒第,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望进鸠。 院中可真熱鬧稠曼,春花似錦、人聲如沸客年。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽量瓜。三九已至司恳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绍傲,已是汗流浹背扔傅。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留烫饼,地道東北人猎塞。 一個(gè)月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像杠纵,于是被迫代替她去往敵國和親荠耽。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

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