Redis緩存與數(shù)據(jù)庫數(shù)據(jù)一致性

方案一:


image.png

寫流程:

第一步先刪除緩存,刪除之后再更新DB,之后再異步將數(shù)據(jù)刷回緩存

讀流程:

第一步先讀緩存站绪,如果緩存沒讀到,則去讀DB丽柿,之后再異步將數(shù)據(jù)刷回緩存
方案分析
優(yōu)點(diǎn)剖析

1. 實(shí)現(xiàn)起來簡(jiǎn)單

What Should I Say ?

2. “先淘汰緩存恢准,再寫數(shù)據(jù)庫” 合理

為什么說這也算優(yōu)點(diǎn)呢魂挂?試想一下

如果把寫流程改一下:先更新緩存,再更新DB馁筐。 如果我們更新緩存成功涂召,而更新數(shù)據(jù)庫失敗,就會(huì)導(dǎo)致緩存中的數(shù)據(jù)是錯(cuò)誤的敏沉,而我們大部分的業(yè)務(wù)一般能忍受數(shù)據(jù)延遲果正,但是數(shù)據(jù)錯(cuò)誤這是無法接受的,所以先淘汰緩存是比較合理的盟迟。 如果把寫流程改一下:不刪緩存秋泳,先更新DB,再更新緩存攒菠。 如果我們更新DB成功迫皱,而更新緩存失敗,則會(huì)導(dǎo)致緩存中就會(huì)一直是舊的數(shù)據(jù)(也算是一種錯(cuò)誤數(shù)據(jù))要尔,所以先淘汰緩存是比較合理的舍杜。

3. 異步刷新新娜,補(bǔ)缺補(bǔ)漏

在很多業(yè)務(wù)場(chǎng)景中赵辕,緩存只是輔助,所以在很多業(yè)務(wù)中概龄,緩存的讀寫失敗不會(huì)影響主流程还惠,啥意思呢?就是說很多情況下私杜,即使操作緩存失敳霞(比如步驟1.1中的’DEL緩存失敗’),程序還是會(huì)繼續(xù)往下走(繼續(xù)步驟1.2 更新數(shù)據(jù)庫)衰粹,所以這個(gè)時(shí)候異步刷新就能在一定程度上锣光,對(duì)1.1的失敗進(jìn)行錯(cuò)誤數(shù)據(jù)的修補(bǔ)

說完優(yōu)點(diǎn),我們?cè)賮砜纯慈秉c(diǎn)

在很多業(yè)務(wù)場(chǎng)景中铝耻,緩存只是輔助誊爹,所以在很多業(yè)務(wù)中,緩存的讀寫失敗不會(huì)影響主流程瓢捉,啥意思呢频丘?就是說很多情況下,即使操作緩存失斉萏(比如步驟1.1中的’DEL緩存失敗’)搂漠,程序還是會(huì)繼續(xù)往下走(繼續(xù)步驟1.2 更新數(shù)據(jù)庫),所以這個(gè)時(shí)候異步刷新就能在一定程度上某弦,對(duì)1.1的失敗進(jìn)行錯(cuò)誤數(shù)據(jù)的修補(bǔ)

說完優(yōu)點(diǎn)桐汤,我們?cè)賮砜纯慈秉c(diǎn)

缺點(diǎn)剖析

1. 容災(zāi)不足

在分布式領(lǐng)域而克,“Everything will fails”,任何可能出現(xiàn)問題的地方都會(huì)出現(xiàn)問題

我們來分析一下寫流程怔毛,第一步拍摇,’DEL緩存失敗’怎么辦?流程是否還繼續(xù)走馆截?如果繼續(xù)執(zhí)行充活,那么從’更新完DB’到異步’刷新緩存’緩存期間,數(shù)據(jù)處于滯后狀態(tài)蜡娶。而且如果緩存處于不可寫狀態(tài)混卵,那么異步刷新那步也可能會(huì)失敗,那緩存就會(huì)長(zhǎng)期處于舊數(shù)據(jù)窖张,問題就比較嚴(yán)重了

2. 并發(fā)問題

寫寫并發(fā):試想一下幕随,同時(shí)有多個(gè)服務(wù)器的多個(gè)線程進(jìn)行’步驟1.2更新DB’,更新DB完成之后宿接,它們就要進(jìn)行異步刷緩存赘淮,我們都知道多服務(wù)器的異步操作,是無法保證順序的睦霎,所以后面的刷新操作存在相互覆蓋的并發(fā)問題梢卸,也就是說,存在先更新的DB操作副女,反而很晚才去刷新緩存蛤高,那這個(gè)時(shí)候,數(shù)據(jù)也是錯(cuò)的

讀寫并發(fā):再試想一下碑幅,服務(wù)器A在進(jìn)行’讀操作’戴陡,,在A服務(wù)器剛完成2.2時(shí)沟涨,服務(wù)器B在進(jìn)行’寫操作’恤批,假設(shè)B服務(wù)器1.3完成之后,服務(wù)器A的1.3才被執(zhí)行裹赴,這個(gè)時(shí)候就相當(dāng)于更新前的老數(shù)據(jù)寫入緩存喜庞,最終數(shù)據(jù)還是錯(cuò)的

方案總結(jié)

今天介紹的這個(gè)方案呢,適合大部分的業(yè)務(wù)場(chǎng)景篮昧,很多人都在用赋荆,香還是很香的,實(shí)現(xiàn)起來也簡(jiǎn)單懊昨。
適合使用的場(chǎng)景:并發(fā)量窄潭、一致性要求都不是很高的情況
我覺得這個(gè)方案有一個(gè)比較大的缺陷在于刷新緩存有可能會(huì)失敗,而失敗之后緩存中數(shù)據(jù)就一直會(huì)處于錯(cuò)誤狀態(tài)嫉你,所以它并不能保證數(shù)據(jù)的最終一致性月帝。

方案二:


image.png

寫流程:

第一步先刪除緩存,刪除之后再更新DB幽污,我們監(jiān)聽從庫(資源少的話主庫也ok)的binlog嚷辅,通過分析binlog我們解析出需要需要刷新的數(shù)據(jù),然后讀主庫把最新的數(shù)據(jù)寫入緩存距误。

這里需要提一下:最后刷新前的讀主庫或者讀從庫簸搞,甚至不讀庫直接通過binlog解析出需要的數(shù)據(jù)都是ok的,這由業(yè)務(wù)決定准潭,比如刷新的數(shù)據(jù)只是表的一行趁俊,那直接通過binlog就完全能解析出來;然而如果需要刷新的數(shù)據(jù)來自多行刑然,多張表寺擂,甚至多個(gè)庫的話,那就需要讀主庫或是從庫才行

讀流程:

第一步先讀緩存泼掠,如果緩存沒讀到怔软,則去讀DB,之后再異步將數(shù)據(jù)刷回緩存

方案分析

優(yōu)點(diǎn)剖析

1. 容災(zāi)

寫步驟1.4或1.5 如果失敗择镇,可以進(jìn)行日志回放挡逼,再次重試。
無論步驟1.1是否刪除成功沐鼠,后續(xù)的刷新操作是有保證的

媽耶挚瘟,怎么就一個(gè)優(yōu)點(diǎn)叹谁,講道理這個(gè)其實(shí)很常用的饲梭,那我們?cè)賮砜纯慈秉c(diǎn)

缺點(diǎn)剖析

分析缺點(diǎn)之前,我們先來看一下知識(shí)點(diǎn)

  1. 對(duì)于同一張表的同一條記錄的更新焰檩,Databus會(huì)以串行形式的通知下游服務(wù)憔涉,也就是說,只有當(dāng)我們正確返回后析苫,它才會(huì)推送該記錄的下一次更新兜叨。
  1. 對(duì)于同一張表的不同記錄的更新, Databus會(huì)以事件時(shí)間為順序的通知下游服務(wù)衩侥,但并不會(huì)等待我們返回后才推送下一條国旷,也就是說它是非串行的。
  1. 對(duì)于不同表茫死,根據(jù)其下游的消費(fèi)速度跪但,不同表之間沒有明確的時(shí)間順序。

1. 只適合簡(jiǎn)單業(yè)務(wù)峦萎,復(fù)雜業(yè)務(wù)容易發(fā)生并發(fā)問題

這里先來解釋一下這里說的“簡(jiǎn)單業(yè)務(wù)”是啥意思屡久?

簡(jiǎn)單業(yè)務(wù):每次需要刷新的數(shù)據(jù)忆首,都來自單表單行

為什么復(fù)雜業(yè)務(wù)就不行呢被环?我舉個(gè)例子
我們假設(shè) 一個(gè)訂單 = A表信息 + B表信息

image.png

由于A表先變化糙及,經(jīng)過1,2筛欢,3步后浸锨,線程1獲取了A’B (A表是新數(shù)據(jù),B表的老數(shù)據(jù))版姑,當(dāng)線程1還沒來得及刷新緩存時(shí)揣钦,并發(fā)發(fā)生了:

此時(shí),B表發(fā)生了更新漠酿,經(jīng)過4冯凹,5,6炒嘲,7將最新的數(shù)據(jù)A’B’寫入緩存宇姚,此時(shí)此刻緩存數(shù)據(jù)是符合要求的。

但是夫凸,后來線程1進(jìn)行了第8步浑劳,將A’B寫入數(shù)據(jù),使得緩存最終結(jié)果 與 DB 不一致夭拌。

缺點(diǎn)1的改進(jìn)
  • 針對(duì)單庫多表單次更新的改進(jìn):利用事務(wù)
    image.png

    當(dāng)AB表的更新發(fā)生在一個(gè)事務(wù)內(nèi)時(shí)魔熏,不管線程1、線程2如何讀取鸽扁,他們都能獲取兩張表的最新數(shù)據(jù)蒜绽,所以刷新緩存的數(shù)據(jù)都是符合要求的。

但是這種方案具有局限性:那就是只對(duì)單次更新有效桶现,或者說更新頻率低的情況下才適應(yīng)躲雅,比如我們并發(fā)的單獨(dú)更新C表,并發(fā)問題依然會(huì)發(fā)生骡和。

所以這種方案只針對(duì)多表單次更新的情況相赁。

針對(duì)多表多次更新的改進(jìn):增量更新


image.png

每張表的更新,在同步緩存時(shí)慰于,只獲取該表的字段覆蓋緩存钮科。

這樣,線程1婆赠,線程2總能獲取對(duì)應(yīng)表最新的字段绵脯,而且Databus對(duì)于同表同行會(huì)以串行的形式通知下游,所以能保證緩存的最終一致性。

這里有一點(diǎn)需要提一下:更新“某張表多行記錄“時(shí)桨嫁,這個(gè)操作要在一個(gè)事務(wù)內(nèi)植兰,不然并發(fā)問題依然存在,正如前面分析的

2. 依然是并發(fā)問題

即使對(duì)于缺點(diǎn)1我們提出了改進(jìn)方案璃吧,雖然它解決了部分問題楣导,但在極端場(chǎng)景下依然存在并發(fā)問題。
這個(gè)場(chǎng)景畜挨,就是緩存中沒有數(shù)據(jù)的情況:

  • 讀的時(shí)候筒繁,緩存中的數(shù)據(jù)已失效,此時(shí)又發(fā)生了更新
  • 數(shù)據(jù)更新的時(shí)候巴元,緩存中的數(shù)據(jù)已失效毡咏,此時(shí)又發(fā)生了更新

這個(gè)時(shí)候,我們?cè)谏厦嫣岬降摹霸隽扛隆本筒黄鹱饔昧舜伲覀冃枰x取所有的表來拼湊出初始數(shù)據(jù)呕缭,那這個(gè)時(shí)候又涉及到讀所有表的操作了,那我們?cè)?strong>缺點(diǎn)1中提到的并發(fā)問題會(huì)再次發(fā)生
適合使用的場(chǎng)景:業(yè)務(wù)簡(jiǎn)單修己,讀寫QPS比較低的情況恢总。
今天這個(gè)方案呢,優(yōu)缺點(diǎn)都比較明顯睬愤,binlog用來刷新緩存是一個(gè)很棒的選擇片仿,它天然的順序性用來做同步操作很具有優(yōu)勢(shì);其實(shí)它的并發(fā)問題來自于Canal 或 Databus尤辱。拿Databus來說砂豌,由于不同行、表光督、庫的binlog的消費(fèi)并不是時(shí)間串行的阳距,那怎么解決這個(gè)問題呢,篇幅有限可帽,我們后續(xù)文章再繼續(xù)分享

方案三(最終一致性)
讀的時(shí)候娄涩,緩存中的數(shù)據(jù)已失效,此時(shí)又發(fā)生了更新
數(shù)據(jù)更新的時(shí)候映跟,緩存中的數(shù)據(jù)已失效,此時(shí)又發(fā)生了更新
那我們我們可以看到扬虚,這個(gè)問題就來自于“讀數(shù)據(jù)庫” + “寫緩存” 之間的交錯(cuò)并發(fā)努隙,那怎么來避免呢?
有一個(gè)方法就是:串行化辜昵,我們利用MQ將所有“讀數(shù)據(jù)庫” + “寫緩存”的步驟串行化


image.png

寫流程:

第一步先刪除緩存荸镊,刪除之后再更新DB,我們監(jiān)聽從庫(資源少的話主庫也ok)的binlog,通過分析binlog我們解析出需要需要刷新的數(shù)據(jù)標(biāo)識(shí)躬存,然后將數(shù)據(jù)標(biāo)識(shí)寫入MQ张惹,接下來就消費(fèi)MQ,解析MQ消息來讀庫獲取相應(yīng)的數(shù)據(jù)刷新緩存岭洲。

關(guān)于MQ串行化宛逗,大家可以去了解一下 Kafka partition 機(jī)制 ,這里就不詳述了

讀流程:

第一步先讀緩存盾剩,如果緩存沒讀到雷激,則去讀DB,之后再異步將數(shù)據(jù)標(biāo)識(shí)寫入MQ(這里MQ與寫流程的MQ是同一個(gè))告私,接下來就消費(fèi)MQ屎暇,解析MQ消息來讀庫獲取相應(yīng)的數(shù)據(jù)刷新緩存。

方案分析

優(yōu)點(diǎn)剖析

1. 容災(zāi)完善

我們一步一步來分析:

寫流程容災(zāi)分析
  • 寫1.1 DEL緩存失敗:沒關(guān)系驻粟,后面會(huì)覆蓋
  • 寫1.4 寫MQ失敗:沒關(guān)系根悼,Databus或Canal都會(huì)重試
  • 消費(fèi)MQ的:1.5 || 1.6 失敗:沒關(guān)系,重新消費(fèi)即可
讀流程容災(zāi)分析
  • 讀2.3 異步寫MQ失敗:沒關(guān)系蜀撑,緩存為空番挺,是OK的,下次還讀庫就好了

2. 無并發(fā)問題

這個(gè)方案讓“讀庫 + 刷緩存”的操作串行化屯掖,這就不存在老數(shù)據(jù)覆蓋新數(shù)據(jù)的并發(fā)問題了

缺點(diǎn)剖析

要什么自行車?yán)?/p>

方案總結(jié)

經(jīng)過3篇由淺入深的介紹玄柏,我們終于實(shí)現(xiàn)了“最終一致性”。這個(gè)方案優(yōu)點(diǎn)比較明顯贴铜,解決了我們前幾篇一直提到的“容災(zāi)問題”和“并發(fā)問題”粪摘,保證了緩存在最后和DB的一致。如果你的業(yè)務(wù)只需要達(dá)到“最終一致性”要求的話绍坝,這個(gè)方案是比較合理的徘意。

OK,到目前為止轩褐,既然已經(jīng)實(shí)現(xiàn)了“最終一致性”椎咧,那我們?cè)龠M(jìn)一步,“強(qiáng)一致性”又該如何實(shí)現(xiàn)呢把介?我們下一期繼續(xù)分享
方案四(強(qiáng)一致性)
強(qiáng)一致性勤讽,包含兩種含義:

緩存和DB數(shù)據(jù)一致
緩存中沒有數(shù)據(jù)(或者說:不會(huì)去讀緩存中的老版本數(shù)據(jù))
首先我們來分析一下,既然已經(jīng)實(shí)現(xiàn)了“最終一致性”拗踢,那它和“強(qiáng)一致性”的區(qū)別是什么呢脚牍?沒錯(cuò),就是“時(shí)間差”巢墅,所以:

“最終一致性方案” + “時(shí)間差” = “強(qiáng)一致性方案”

那我們的工作呢诸狭,就是加上時(shí)間差券膀,實(shí)現(xiàn)方式:我們加一個(gè)緩存,將近期被修改的數(shù)據(jù)進(jìn)行標(biāo)記鎖定驯遇。讀的時(shí)候芹彬,標(biāo)記鎖定的數(shù)據(jù)強(qiáng)行走DB,沒鎖定的數(shù)據(jù)叉庐,先走緩存


image.png

寫流程:

我們把修改的數(shù)據(jù)通過Cache_0標(biāo)記“正在被修改”舒帮,如果標(biāo)記成功,則繼續(xù)往下走眨唬,后面的步驟與上一篇是一致的《緩存與數(shù)據(jù)庫一致性系列-03》会前;那如果標(biāo)記失敗,則要放棄這次修改匾竿。

何為標(biāo)記鎖定呢瓦宜?比如你可以設(shè)定一個(gè)有效期為10S的key,Key存在即為鎖定岭妖。一般來說10S對(duì)于后面的同步操作來說基本是夠了~

如果說临庇,還想更嚴(yán)謹(jǐn)一點(diǎn),怕DB主從延遲太久昵慌、MQ延遲太久假夺,或Databus監(jiān)聽的從庫掛機(jī)之類的情況,我們可以考慮增加一個(gè)監(jiān)控定時(shí)任務(wù)斋攀。
比如我們?cè)黾右粋€(gè)時(shí)間間隔2S的worker的去對(duì)比以下兩個(gè)數(shù)據(jù):

  • 時(shí)間1: 最后修改數(shù)據(jù)庫的時(shí)間
    VS
  • 時(shí)間2: 最后由更新引起的’MQ刷新緩存對(duì)應(yīng)數(shù)據(jù)的實(shí)際更新數(shù)據(jù)庫’的時(shí)間

數(shù)據(jù)1: 可由步驟1.1獲得已卷,并存儲(chǔ)
數(shù)據(jù)2: 需要由binlog中解析獲得,需要透?jìng)鞯組Q淳蔼,這樣后面就能存儲(chǔ)了
這里提一下:如果多庫的情況的話侧蘸,存儲(chǔ)這兩個(gè)key需要與庫一一對(duì)應(yīng)

如果 時(shí)間1 VS 時(shí)間2 相差超過5S,那我們就自動(dòng)把相應(yīng)的緩存分片讀降級(jí)鹉梨。

讀流程:

先讀Cache_0讳癌,看看要讀的數(shù)據(jù)是否被標(biāo)記,如果被標(biāo)記存皂,則直接讀主庫晌坤;如果沒有被標(biāo)記,后面的步驟與方案三一致旦袋。

方案分析

優(yōu)點(diǎn)剖析

1. 容災(zāi)完善

我們一步一步來分析:

寫流程容災(zāi)分析
  • 寫1.1 標(biāo)記失敗:沒關(guān)系骤菠,放棄整個(gè)更新操作
  • 寫1.3 DEL緩存失敗:沒關(guān)系,后面會(huì)覆蓋
  • 寫1.5 寫MQ失敗:沒關(guān)系猜憎,Databus或Canal都會(huì)重試
  • 消費(fèi)MQ的:1.6 || 1.7 失敗:沒關(guān)系娩怎,重新消費(fèi)即可
讀流程容災(zāi)分析
  • 讀2.1 讀Cache_0失敗:沒關(guān)系,直接讀主庫
  • 讀2.3 異步寫MQ失敗:沒關(guān)系胰柑,緩存為空截亦,是OK的,下次還讀庫就好了

2. 無并發(fā)問題

這個(gè)方案讓“讀庫 + 刷緩存”的操作串行化柬讨,這就不存在老數(shù)據(jù)覆蓋新數(shù)據(jù)的并發(fā)問題了

缺點(diǎn)剖析

1. 增加Cache_0強(qiáng)依賴

這個(gè)其實(shí)有點(diǎn)沒辦法崩瓤,你要強(qiáng)一致性,必然要犧牲一些的踩官。
但是呢却桶,你這個(gè)可以吧Cache_0設(shè)計(jì)成多機(jī)器多分片,這樣的話蔗牡,即使部分分片掛了颖系,也只有小部分流量透過Cache直接打到DB上俊戳,這是完全是可接受的

2. 復(fù)雜度是比較高的

涉及到Databus休溶、MQ仇哆、定時(shí)任務(wù)等等組件谎倔,實(shí)現(xiàn)起來復(fù)雜度還是有的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末搀菩,一起剝皮案震驚了整個(gè)濱河市蘸拔,隨后出現(xiàn)的幾起案子巨缘,更是在濱河造成了極大的恐慌欣鳖,老刑警劉巖督惰,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件不傅,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡赏胚,警方通過查閱死者的電腦和手機(jī)访娶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來觉阅,“玉大人崖疤,你說我怎么就攤上這事×羰埃” “怎么了戳晌?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)痴柔。 經(jīng)常有香客問我沦偎,道長(zhǎng),這世上最難降的妖魔是什么咳蔚? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任豪嚎,我火速辦了婚禮,結(jié)果婚禮上谈火,老公的妹妹穿的比我還像新娘侈询。我一直安慰自己,他們只是感情好糯耍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布扔字。 她就那樣靜靜地躺著囊嘉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪革为。 梳的紋絲不亂的頭發(fā)上扭粱,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音震檩,去河邊找鬼琢蛤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛抛虏,可吹牛的內(nèi)容都是我干的博其。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼迂猴,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼慕淡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起错忱,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤儡率,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后以清,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體儿普,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年掷倔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了眉孩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勒葱,死狀恐怖浪汪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凛虽,我是刑警寧澤死遭,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站凯旋,受9級(jí)特大地震影響呀潭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜至非,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一钠署、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荒椭,春花似錦谐鼎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽身害。三九已至,卻和暖如春隔缀,著一層夾襖步出監(jiān)牢的瞬間题造,已是汗流浹背傍菇。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工猾瘸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丢习。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓牵触,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親咐低。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揽思,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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