喜馬拉雅基于Apache ShardingSphere實(shí)踐

背景

喜馬拉雅成立之初哼鬓,各個(gè)業(yè)務(wù)管理各自的數(shù)據(jù)庫(kù)监右、緩存,個(gè)業(yè)務(wù)都要了解中間件的各種部署情況异希,導(dǎo)致業(yè)務(wù)間的合作健盒,需要運(yùn)維、開(kāi)發(fā)等方面的人工介入称簿,效率較低扣癣,擴(kuò)展困難,安全風(fēng)險(xiǎn)也很高憨降,資源利用率也不高父虑。喜馬拉雅在發(fā)展中,逐漸意識(shí)到需要在公司層面券册,提供統(tǒng)一的定制化的數(shù)據(jù)訪問(wèn)平臺(tái)的重要性频轿。為此垂涯,我們推出了自己的PaaS化平臺(tái)烁焙,PaaS化就是對(duì)資源的使用做了統(tǒng)一的入口,業(yè)務(wù)只需要申請(qǐng)一個(gè)資源ID耕赘,就能使用數(shù)據(jù)庫(kù)骄蝇,達(dá)到對(duì)資源使用的全部系統(tǒng)化,其中對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)我們基于Apache ShardingSphere來(lái)實(shí)現(xiàn)操骡,并基于Apache ShardingSphere強(qiáng)大功能做些優(yōu)化和增強(qiáng)九火。

整體架構(gòu)

我們PaaS平臺(tái)建設(shè)中赚窃,負(fù)責(zé)和數(shù)據(jù)層通信的dal層中間件我們叫Arena,其中對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)我們叫Arean-Jdbc

Arena-Jdbc 層的能力基本是基于Apache ShardingSphere的能力建設(shè),我們只是基于喜馬拉雅需要的特性做了增強(qiáng)和優(yōu)化,整體架構(gòu)如下:

arena-jdbc-arch.png

Pull Frame

Consul Pull Frame 是我們對(duì)Consul 的配置自動(dòng)拉起封裝為統(tǒng)一的Pull框架岔激,我們除了數(shù)據(jù)庫(kù)勒极,還有緩存,每種還有不同的使用方式虑鼎,我們對(duì)不同的使用方式只需要實(shí)現(xiàn)對(duì)應(yīng)的實(shí)現(xiàn)類和初始化辱匿,更新,切好這些接口就行炫彩,框架會(huì)統(tǒng)一把解析好的數(shù)據(jù)給到匾七,具體一種場(chǎng)景不需要關(guān)心和Consul的交互,為后面的資源PaaS化提供了簡(jiǎn)單的接入能力江兢。

故障容災(zāi)

  • 自動(dòng)重連
    我們對(duì)故障容災(zāi)在設(shè)計(jì)時(shí)就考慮了平時(shí)通用的一些故障場(chǎng)景昨忆,比如數(shù)據(jù)庫(kù)server 掛了,我們最做自動(dòng)重鏈杉允,不需要業(yè)務(wù)做重啟操作邑贴。
  • 本地快照
    本地快照是為了防止Consul不可用時(shí),業(yè)務(wù)不能啟動(dòng)叔磷,所以我們?cè)诶竭h(yuǎn)程配置后痢缎,會(huì)本地存儲(chǔ)一份,在拉配置時(shí)世澜,如果遠(yuǎn)程失敗独旷,就用本地的配置,保證Consul掛了寥裂,不影響業(yè)務(wù)嵌洼,每次拉到新的配置時(shí),會(huì)更新本地的快照封恰。
  • 灰度更新
    灰度更新是為了支持配置變更時(shí)找灰度的邏輯麻养,對(duì)于數(shù)據(jù)庫(kù)層面的變更,是非常危險(xiǎn)的诺舔,如果一下就全量變更鳖昌,有可能會(huì)觸發(fā)線上事故,所以通過(guò)灰度變更的機(jī)制低飒,業(yè)務(wù)可以先選擇一個(gè)容器實(shí)例來(lái)變更许昨,沒(méi)有問(wèn)題后,再全量變更褥赊,把風(fēng)險(xiǎn)降到最低糕档。
  • 密碼安全
    沒(méi)有PaaS化之前,我們的數(shù)據(jù)庫(kù)密碼都是dba統(tǒng)一管理的拌喉,但PaaS化后速那,訪問(wèn)數(shù)據(jù)庫(kù)的密碼就存在配置文件中俐银,如果明文,就太不安全端仰,所以我們對(duì)密碼統(tǒng)一做了加密處理捶惜,在Arean-Jdbc層統(tǒng)一做解密,確保密碼不回泄露出去荔烧。

統(tǒng)一數(shù)據(jù)源

為了讓業(yè)務(wù)做最低成本的改造售躁,Arena-jdbc 需要提供一個(gè)統(tǒng)一的數(shù)據(jù)源,不論上層用什么框架茴晋,不影響,業(yè)務(wù)只需要替換數(shù)據(jù)源接入即可陪捷,對(duì)于數(shù)據(jù)庫(kù)連接池我們默認(rèn)使用HikariCP DataSource也支持個(gè)性化的業(yè)務(wù),業(yè)務(wù)可以通過(guò)配置指定連接池诺擅。

我們基于Apache ShardingSphere的連接池封裝了一個(gè)我們自己的DataSource,我們叫ArenaDataSource,通過(guò)ArenaDataSource封裝了各種不同場(chǎng)景聚合市袖,的使用一個(gè)ArenaDataSource支持三種使用方式:

  1. 支持原生直接連接
  2. 支持Proxy模式,也是Apache ShardingSphere的proxy
  3. 支持直接連接分庫(kù)分表

業(yè)務(wù)只需要一個(gè)DataSource烁涌,即支持分庫(kù)分表苍碟,也支持簡(jiǎn)單的直接連接的模式,這樣的好處是業(yè)務(wù)以后要分庫(kù)分表撮执,就不再需要升級(jí)中間件了微峰,為了徹底解決業(yè)務(wù)升級(jí)的成本,我們做了配置自動(dòng)升級(jí)抒钱,就是你之前是簡(jiǎn)單直接鏈接使用蜓肆,為了PaaS化,后來(lái)業(yè)務(wù)發(fā)展了谋币,需要分庫(kù)分表了仗扬,以及從分庫(kù)分表需要多活部署了,這些都不要再升級(jí)依賴了蕾额,只需要配置動(dòng)即可早芭。

資源動(dòng)態(tài)變更

資源動(dòng)態(tài)變更是PaaS平臺(tái)基本的能力,接入PaaS后诅蝶,業(yè)務(wù)修改數(shù)據(jù)庫(kù)的任何屬性退个,都不再需要業(yè)務(wù)方代碼變更,重新發(fā)布

Apache ShardingSphere也支持?jǐn)?shù)據(jù)庫(kù)屬性的動(dòng)態(tài)變更调炬,我們基于自己的內(nèi)部系統(tǒng)的特征语盈,實(shí)現(xiàn)了基于Consul的資源變根通知。我們的資源存在Consul筐眷。

Arena-Jdbc支持對(duì)使用的資源做無(wú)損的變更黎烈,Arena-Jdbc 收到資源變更時(shí)习柠,會(huì)先對(duì)新下發(fā)的資源做預(yù)熱處理匀谣,預(yù)熱后照棋,再切換使用的數(shù)據(jù)源,切換成功后武翎,再銷毀老的數(shù)據(jù)源烈炭,業(yè)務(wù)無(wú)感知。

如果新的資源預(yù)熱失敗宝恶,則不會(huì)做變更處理符隙,保證下發(fā)的資源時(shí)可用的,規(guī)避錯(cuò)誤下發(fā)的問(wèn)題垫毙。

擴(kuò)容和縮容也是同理霹疫,一期數(shù)據(jù)需要運(yùn)維手動(dòng)遷移,遷移好了后综芥,直接在PaaS平臺(tái)下發(fā)新的配置即可丽蝎,二期支持自動(dòng)遷移數(shù)據(jù)和配置變更結(jié)合。

同時(shí)支持Proxy的無(wú)損上下線機(jī)制膀藐,通過(guò)PaaS平臺(tái)對(duì)Proxy的變更屠阻,把需要下線的Proxy節(jié)點(diǎn)去掉,通知Arena-Jdbc额各,Arena-Jdbc會(huì)把縮容的Proxy節(jié)點(diǎn)去掉国觉,做到無(wú)損下線。

讀寫(xiě)分離

讀寫(xiě)分離我們完全基于Apache ShardingSphere的來(lái)實(shí)現(xiàn)虾啦,我們根據(jù)喜馬拉雅業(yè)務(wù)的特性麻诀,對(duì)強(qiáng)制路由做了增強(qiáng),不需要規(guī)則配置為Hint模式傲醉,只要線程上下文帶有強(qiáng)制路由的標(biāo)志针饥,就可以路由到指定的庫(kù)和表,不受分表規(guī)則的影響需频,我們重寫(xiě)了ShardingStandardRoutingEngine的Sharding時(shí)路由庫(kù)和表的邏輯:

private Collection<String> routeDataSources(final TableRule tableRule, final ShardingStrategy databaseShardingStrategy, final List<ShardingConditionValue> databaseShardingValues) {
        //先判斷是否存在Hint上下文路由標(biāo)丁眼,如果有,則優(yōu)先根據(jù)用戶指定的規(guī)則路由庫(kù)
        Collection<Comparable<?>> databaseShardings = HintManager.getDatabaseShardingValues(tableRule.getLogicTable());
        if (databaseShardings != null && databaseShardings.size() > 0) {
            List<String> list = new ArrayList<>(4);
            for (Comparable<?> databaseSharding : databaseShardings) {
                list.add((String) databaseSharding);
            }
            if (log.isDebugEnabled()) {
                log.debug("route dataSources, find HintManager, so hint to: {}", list);
            }
            return list;
        }
        //沒(méi)有Hint路由規(guī)則,則按Sharding 規(guī)則路由
        if (databaseShardingValues.isEmpty()) {
            return tableRule.getActualDatasourceNames();
        }
        Collection<String> result = new LinkedHashSet<>(databaseShardingStrategy.doSharding(tableRule.getActualDatasourceNames(), databaseShardingValues, properties));
        Preconditions.checkState(!result.isEmpty(), "no database route info");
        Preconditions.checkState(tableRule.getActualDatasourceNames().containsAll(result), 
                "Some routed data sources do not belong to configured data sources. routed data sources: `%s`, configured data sources: `%s`", result, tableRule.getActualDatasourceNames());
        return result;
    }

路由表也是同樣的邏輯昭殉,我們重寫(xiě)了ShardingStandardRoutingEnginerouteTables方法苞七,和上面一樣。先從Hint 的上下文獲取挪丢。這樣通過(guò)上下文的方式能很好的滿足業(yè)務(wù)個(gè)性化的路由規(guī)則蹂风,能和Sharding 規(guī)則共存。

Database Plus

Apache ShardingSphere 除了提供基本的分庫(kù)分表乾蓬,讀寫(xiě)分離的能力外惠啄,在上層還提供了很多的插件和擴(kuò)展的機(jī)制,這讓我們?cè)诨跀?shù)據(jù)庫(kù)提供更偏向業(yè)務(wù)的起的能力非常容易,成本非常低,這叫Database Plus

Database Plus簡(jiǎn)單的說(shuō)就是你用Apache ShardingSphere的數(shù)據(jù)庫(kù)中間件撵渡,不僅僅是提供了分庫(kù)分表這一基本能力融柬,通過(guò)對(duì)底層數(shù)據(jù)的封裝為統(tǒng)一的交互標(biāo)準(zhǔn)插件模式,可以在上面實(shí)現(xiàn)很多業(yè)務(wù)的通用的場(chǎng)景的需求趋距,比如喜馬拉雅除了用到Apache ShardingSphere 基礎(chǔ)的能力外粒氧,我們也享受了Database Plus 的威力,我們?cè)谒幕A(chǔ)上輕松實(shí)現(xiàn)了支持壓測(cè)的影子庫(kù)和影子表节腐,數(shù)據(jù)加解密外盯,機(jī)房級(jí)別容災(zāi)的同城雙讀,分布式唯一ID

影子庫(kù)和影子表

影子庫(kù)影子表我們對(duì)Apache ShardingSphere做了改動(dòng)翼雀,Apache ShardingSphere 需要修改sql饱苟,我們認(rèn)為對(duì)業(yè)務(wù)有改造成本,同時(shí)結(jié)合我們自己的壓測(cè)平臺(tái)狼渊,我們和業(yè)界一樣掷空,我們也實(shí)現(xiàn)了影子標(biāo)記,通過(guò)全鏈路壓測(cè)標(biāo)的傳遞來(lái)判斷是否路由到影子庫(kù)/影子表囤锉,業(yè)務(wù)無(wú)需任何改造圣絮,即可使用影子庫(kù)影子表來(lái)做壓測(cè)跨释,同時(shí)不需要在運(yùn)行時(shí)對(duì)sql改寫(xiě)蹭劈,提升了性能炉媒,我們重寫(xiě)了ShadowSQLRouter,

public class ArenaShadowSQLRouter extends ShadowSQLRouter {

    @Override
    public boolean isShadow(final SQLStatementContext<?> sqlStatementContext, final List<Object> parameters, final ShadowRule rule) {
        if (sqlStatementContext instanceof InsertStatementContext || sqlStatementContext instanceof WhereAvailable
            || sqlStatementContext instanceof UpdateStatementContext) {
                 //這里就是判斷是否有壓測(cè)標(biāo),如果有驱入,ShardingSphere則會(huì)找影子的邏輯赤炒。
                return ArenaUtilities.checkPeakRequest();
        }

        return false;

    }
}

通過(guò)spi的方式把我們自定義的ArenaShadowSQLRouter 給Apache ShardingSphere加載使用,不得不說(shuō)Apache ShardingSphere的插件設(shè)計(jì)很贊亏较,很方便自定義和擴(kuò)展莺褒。

配置還是和Apache ShardingSphere的一樣:

# 配置影子庫(kù)規(guī)則
- !SHADOW
    # true-影子表,false-影子庫(kù)(默認(rèn))
    enableShadowTable: true 
    # 源庫(kù)名稱(對(duì)應(yīng)DataSources數(shù)據(jù)源配置中的名稱)雪情,影子庫(kù)才需要配遵岩,影子表不需要配置
    sourceDataSourceNames:  
      - ds0           # 源庫(kù),與影子庫(kù)shadow_ds0對(duì)應(yīng)
      - ds1           # 源庫(kù)巡通,與影子庫(kù)shadow_ds1對(duì)應(yīng)
    # 影子庫(kù)名稱(對(duì)應(yīng)dataSources數(shù)據(jù)源配置中的名稱)尘执,影子庫(kù)才需要配,影子表不需要配置
    shadowDataSourceNames:  
      - shadow_ds0    # 影子庫(kù)宴凉,與源庫(kù)ds0對(duì)應(yīng)
      - shadow_ds1    # 影子庫(kù)誊锭,與源庫(kù)ds1對(duì)應(yīng)

enableShadowTable 我們新增了該屬性,來(lái)確定是使用影子庫(kù)還是影子表弥锄。

影子庫(kù):

影子庫(kù)丧靡,一定要填sourceDataSourceNames和shadowDataSourceNames蟆沫,enableShadowTable不用設(shè)置,或者設(shè)置為false温治。
sourceDataSourceNames
按順序映射饭庞,一一對(duì)應(yīng):
ds --> shadow_ds
ds1--> shadow_ds1

影子庫(kù)/影子表是最后一個(gè)路由規(guī)則,如果發(fā)現(xiàn)有影子庫(kù)/影子表罐盔,則根據(jù)實(shí)際的庫(kù)找到對(duì)應(yīng)的影子庫(kù)/影子表但绕,執(zhí)行sql

同城多活

基于喜馬拉雅的業(yè)務(wù)特性救崔,讀多寫(xiě)少惶看,我們只實(shí)現(xiàn)了對(duì)讀業(yè)務(wù)的雙機(jī)房部署,寫(xiě)業(yè)務(wù)還是路由到主機(jī)房六孵。

為了增強(qiáng)容災(zāi)能力纬黎,喜馬拉雅搭建了雙機(jī)房,同時(shí)承載業(yè)務(wù)流量劫窒,當(dāng)一個(gè)機(jī)房故障時(shí)本今,可以把流量快速切換到另一個(gè)機(jī)房,我們?cè)赿al層設(shè)計(jì)上支持雙寫(xiě)主巍,這
里充分利用了Apache ShardingSphere的讀寫(xiě)分離功能冠息,讀和寫(xiě)可以配置獨(dú)立的數(shù)據(jù)源,我們只需要在上面做了一層封裝孕索,在切換時(shí)候動(dòng)態(tài)變更對(duì)應(yīng)的數(shù)據(jù)源即可逛艰,為了切換時(shí)不影響業(yè)務(wù)的流量,我們是先預(yù)熱新的數(shù)據(jù)源搞旭,再銷毀老的數(shù)據(jù)源散怖。
架構(gòu)圖如下:

b276cfc1-a4e0-4f13-9377-22cdd4775523.png

另外我們也對(duì)雙寫(xiě)做了研究和探索,關(guān)鍵在于數(shù)據(jù)庫(kù)的雙向同步肄渗,基于阿里開(kāi)源的otter做了改造镇眷,支持基于gtid模式同步,不依賴打標(biāo)翎嫡,打標(biāo)回有性能開(kāi)銷欠动,在一些業(yè)務(wù)做了試用。

分布式唯一ID

分庫(kù)分表后惑申,唯一id是必須要滿足的需求翁垂,Apache ShardingSphere默認(rèn)提供了snowfake和uuid 算法,但不是很時(shí)候db的場(chǎng)景硝桩,db需要保證順序和格式沿猜,所以我們基于Apache ShardingSphere提供的接口,也實(shí)現(xiàn)自己的唯一id生成策略:

數(shù)據(jù)分片后碗脊,不同Mysql實(shí)例生成全局唯一主鍵是非常棘手的問(wèn)題啼肩。Arena-Jdbc實(shí)現(xiàn)了Apache ShardingSphere的分布式主鍵生成器接口橄妆,通過(guò)集成喜馬拉雅內(nèi)部的全局唯一id生成服務(wù),提供了適用于喜馬拉雅內(nèi)部的自增主鍵生成算法-BoushId主鍵生成策略祈坠。

監(jiān)控和報(bào)警:

做一個(gè)數(shù)據(jù)庫(kù)中間件害碾,監(jiān)控是必不可少的部分,就像我們的眼睛赦拘,沒(méi)有監(jiān)控就是瞎抓慌随,以及對(duì)異常情況的報(bào)警也是非常重要的部分,只有完善的監(jiān)控和報(bào)警才能算是一個(gè)完整的產(chǎn)品躺同,得益于Apache ShardingSphere在設(shè)計(jì)時(shí)就提供了鉤子阁猜,我們能非常小的成本就能實(shí)現(xiàn)對(duì)sql層面的監(jiān)控和報(bào)警。

Arena-Jdbc客戶端通過(guò)鉤子回調(diào)蹋艺,從多維度數(shù)據(jù)來(lái)分析使用數(shù)據(jù)庫(kù)的運(yùn)行情況剃袍,以30s為一次統(tǒng)計(jì)周期,每個(gè)周期統(tǒng)計(jì)的數(shù)據(jù)包括:Mysql總請(qǐng)求量捎谨,新增民效、刪除、修改和查詢的請(qǐng)求量涛救,失敗的請(qǐng)求量和慢請(qǐng)求量畏邢,影子庫(kù)的流量,以及統(tǒng)計(jì)響應(yīng)時(shí)間的TP百分比检吆,還有連接池的等待時(shí)間舒萎、建連時(shí)間、連接數(shù)等信息咧栗。這些指標(biāo)會(huì)發(fā)送給專門(mén)的收集指標(biāo)服務(wù)逆甜,并持久化到時(shí)序數(shù)據(jù)庫(kù),PaaS平臺(tái)可以從時(shí)序數(shù)據(jù)庫(kù)中查詢數(shù)據(jù)致板,展示給各個(gè)業(yè)務(wù)交煞,對(duì)于異常sql和慢sql,做報(bào)警等后續(xù)處理斟或。

image.png

其他

我們除了基于Apache ShardingSphere實(shí)現(xiàn)上述關(guān)鍵特性外素征,我們還對(duì)Apache ShardingSphere做了一些優(yōu)化和改進(jìn),以更適合喜馬拉雅的業(yè)務(wù)萝挤。

  • 優(yōu)化分片規(guī)則御毅,啟動(dòng)時(shí),如果分片的真實(shí)表不存在的情況則報(bào)錯(cuò)怜珍,將配置錯(cuò)誤前置

  • 有的業(yè)務(wù)方有幾百端蛆,甚至幾千的分表,這種情況下酥泛,由于Apache ShardingSphere中的聯(lián)邦查詢需要依次掃表今豆,啟動(dòng)速度很慢嫌拣,達(dá)到了分鐘級(jí)別。針對(duì)這種情況呆躲,我們新增了props配置項(xiàng)异逐,不再初始化聯(lián)邦查詢,打打加快了啟動(dòng)速度插掂,并且再使用中灰瞻,也沒(méi)有用聯(lián)邦查詢

  • 優(yōu)化了Apache ShardingSphere,執(zhí)行sql異常不報(bào)錯(cuò)誤的情況

  • 由于有的業(yè)務(wù)方辅甥,對(duì)重要的表采用了大寫(xiě)的表名和列名酝润,我們?nèi)サ鬉pache ShardingSphere中,對(duì)配置中的大寫(xiě)的表名列名強(qiáng)制小寫(xiě)的情況肆氓,允許大寫(xiě)的表名和列名

  • 新增了props配置項(xiàng)袍祖,可以調(diào)節(jié)Apache ShardingSphere的編譯緩存的大小

  • 優(yōu)化Apache ShardingSphere復(fù)合分片算法底瓣,精確匹配分片字段
    在ComplexShardingStrategyConfiguration中谢揪,添加shardingColumnList字段:
    修復(fù)Apache ShardingSphere,批量insert捐凭,不返回主鍵的問(wèn)題拨扶,這個(gè)問(wèn)題在mybatis-plus中比較常見(jiàn)

  • 不分片的表,支持使用默認(rèn)的主鍵id生成策略

總結(jié)

基于Apache ShardingSphere實(shí)現(xiàn)的數(shù)據(jù)庫(kù)中間件Arena-Jdbc茁肠,經(jīng)過(guò)半年的時(shí)間患民,已經(jīng)覆蓋了喜馬拉雅的70%的核心業(yè)務(wù),目前沒(méi)有發(fā)現(xiàn)任何問(wèn)題垦梆,表現(xiàn)的非常穩(wěn)定匹颤,通過(guò)和我們的PaaS平臺(tái)結(jié)合,業(yè)務(wù)也非常愿意接入托猩,另外我們使用Apache ShardingSphere時(shí)印蓖,社區(qū)還沒(méi)有發(fā)布stable的版本,所以我們?cè)谑褂眠^(guò)程中也遇到了些問(wèn)題京腥,基本上我們都解決了赦肃,有的社區(qū)也有對(duì)應(yīng)的解決方案,得益于社區(qū)非彻耍活躍他宛,我們以后也希望把我們做的一些feature能回饋到社區(qū),為Apache ShardingSphere的發(fā)展做出一點(diǎn)點(diǎn)小貢獻(xiàn)欠气。

另外非常感謝亮哥親自來(lái)喜馬拉雅對(duì)Apache ShardingSphere的技術(shù)內(nèi)幕和規(guī)則做了一次全面的分享厅各,非常關(guān)心我們?cè)谑褂肁pache ShardingSphere過(guò)程中遇到的問(wèn)題,在現(xiàn)場(chǎng)對(duì)小伙伴提的問(wèn)題都一一作了 深入的解答预柒,非常感謝亮哥队塘,祝Apache ShardingSphere越來(lái)越好琐鲁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市人灼,隨后出現(xiàn)的幾起案子围段,更是在濱河造成了極大的恐慌,老刑警劉巖投放,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奈泪,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡灸芳,警方通過(guò)查閱死者的電腦和手機(jī)涝桅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)烙样,“玉大人冯遂,你說(shuō)我怎么就攤上這事≮嘶瘢” “怎么了蛤肌?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)批狱。 經(jīng)常有香客問(wèn)我裸准,道長(zhǎng),這世上最難降的妖魔是什么赔硫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任炒俱,我火速辦了婚禮,結(jié)果婚禮上爪膊,老公的妹妹穿的比我還像新娘权悟。我一直安慰自己,他們只是感情好推盛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布峦阁。 她就那樣靜靜地躺著,像睡著了一般小槐。 火紅的嫁衣襯著肌膚如雪拇派。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天凿跳,我揣著相機(jī)與錄音件豌,去河邊找鬼。 笑死控嗜,一個(gè)胖子當(dāng)著我的面吹牛茧彤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疆栏,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼曾掂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惫谤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起珠洗,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤溜歪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后许蓖,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蝴猪,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年膊爪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了自阱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡米酬,死狀恐怖沛豌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赃额,我是刑警寧澤加派,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站爬早,受9級(jí)特大地震影響哼丈,放射性物質(zhì)發(fā)生泄漏启妹。R本人自食惡果不足惜筛严,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望饶米。 院中可真熱鬧桨啃,春花似錦、人聲如沸檬输。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)丧慈。三九已至析命,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逃默,已是汗流浹背鹃愤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留完域,地道東北人软吐。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吟税,于是被迫代替她去往敵國(guó)和親凹耙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子姿现,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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