67 ShardingSphere 分表分庫(kù)

1老虫,什么是垂直/水平拆分模式

2叶骨,基于客戶端與服務(wù)器端實(shí)現(xiàn)分表分庫(kù)的區(qū)別

3,單表達(dá)到多大的量開(kāi)始分表分庫(kù)
4祈匙,數(shù)據(jù)庫(kù)分表分庫(kù)策略有哪些
5忽刽, shardingSphere 實(shí)戰(zhàn)分庫(kù)分表
6,為什么不推薦使用mycat 實(shí)現(xiàn)分庫(kù)分表
7夺欲,分表分庫(kù)后查詢存在哪些優(yōu)缺點(diǎn)
8跪帝,分表分庫(kù)后如何實(shí)現(xiàn)分頁(yè)查詢
9,分表分庫(kù)后如何實(shí)現(xiàn)排序查詢些阅;

垂直/水平拆分模式
1伞剑,數(shù)據(jù)庫(kù)拆分主要指分庫(kù)分表,其目的主要是分散數(shù)據(jù)庫(kù)壓力市埋,達(dá)到橫向發(fā)展黎泣,滿足均衡訪問(wèn)等。
2缤谎, 數(shù)據(jù)庫(kù)拆分主要有2種形式: 垂直拆分和水平拆分抒倚。
A 垂直拆分:
將不同的業(yè)務(wù)功能相關(guān)的表放到不同的數(shù)據(jù)庫(kù)中,也就是類似于 微服務(wù)架構(gòu)中 會(huì)員數(shù)據(jù)庫(kù)/訂單數(shù)據(jù)庫(kù)/支付數(shù)據(jù)庫(kù)
B 水平拆分:
當(dāng)一張表的業(yè)務(wù)量行數(shù)如果超過(guò) 500 行坷澡,分頁(yè)/排序效率還是非常低托呕,可以對(duì)同一個(gè)表數(shù)據(jù)實(shí)現(xiàn)拆分放到多個(gè)不同的數(shù)據(jù)庫(kù)表中存放。

Mayikt_memberdb01
Mayikt_user
Mayikt_memberdb02
Mayikt_user

基于客戶端與服務(wù)器端實(shí)現(xiàn)分表分庫(kù)的區(qū)別:

1,基于服務(wù)器端mycat 實(shí)現(xiàn)數(shù)據(jù)庫(kù)代理
優(yōu)點(diǎn): 能夠保證數(shù)據(jù)庫(kù) 的安全性
缺點(diǎn): 效率比較低

image.png

2项郊,基于客戶端Shardingjdbc 實(shí)現(xiàn)數(shù)據(jù)庫(kù)代理:
優(yōu)點(diǎn): 效率比較高
缺點(diǎn): 不能夠保證數(shù)據(jù)庫(kù)的安全性馅扣,內(nèi)存溢出;


image.png

單表達(dá)到多大量開(kāi)始分表分庫(kù):
【推薦】單表行數(shù)超過(guò) 500 萬(wàn)行或者單表容量超過(guò) 2GB着降,才推薦進(jìn)行分庫(kù)分表差油。
說(shuō)明:如果預(yù)計(jì)三年后的數(shù)據(jù)量根本達(dá)不到這個(gè)級(jí)別,請(qǐng)不要在創(chuàng)建表時(shí)就分庫(kù)分表任洞。
摘自:阿里巴巴java開(kāi)發(fā)手冊(cè)

數(shù)據(jù)庫(kù)分表分庫(kù)策略有哪些:

取余/取模 均勻存放數(shù)據(jù) 缺點(diǎn): 不夠擴(kuò)容厌殉。
按照范圍分片: 1-500萬(wàn) 501萬(wàn)-10000萬(wàn);
按照日期進(jìn)行分片 日志侈咕,訂單信息 同居
按照枚舉值分片;
二進(jìn)制取模范圍分片:
一致性hash 分片,類似于HashMap 缺點(diǎn) 數(shù)據(jù)存放不均勻器紧。
按照目前字段前綴指定的進(jìn)行分區(qū) mayikt wuhan
按照前綴ASCII 碼和值進(jìn)行取模范圍分片耀销。

主流分片算法: 取余/取模 日期 一致性hash 分片
根據(jù)user_id
Userid=1%2=1
Userid=2%2=0
Userid=3%2=1
Userid=4%2=0

不能實(shí)現(xiàn)擴(kuò)容。

ShardingSphere 實(shí)戰(zhàn)分表分庫(kù)
ShardingSphere 是一套開(kāi)源的分布式數(shù)據(jù)庫(kù)中間件解決方案組成的生態(tài)圈铲汪,它由Sharding-JDBC熊尉, Sharding-PROXY 和 Sahriding 這三款 相互獨(dú)立的產(chǎn)品組成。
他們均提供標(biāo)準(zhǔn)化的數(shù)據(jù)分片掌腰,分布式事務(wù) 和數(shù)據(jù)庫(kù)治理功能狰住,可適用于java同構(gòu),已購(gòu)語(yǔ)言齿梁,云原生等各種多樣化的應(yīng)用場(chǎng)景催植。

image.png

Sharding_JDBC 可以實(shí)現(xiàn)
分庫(kù) & 分表

  • 讀寫分離
  • 分片策略定制化
  • 無(wú)中心化分布式主鍵

SharingdSphere 環(huán)境搭建:
數(shù)據(jù)庫(kù)準(zhǔn)備;

DROP TABLE IF EXISTS `mayikt_user_0`;
CREATE TABLE `mayikt_user_0` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of mayikt_user_0
-- ----------------------------
INSERT INTO `mayikt_user_0` VALUES ('2', 'mayikt2', '2');
INSERT INTO `mayikt_user_0` VALUES ('4', 'mayikt4', '4');
INSERT INTO `mayikt_user_0` VALUES ('6', 'mayikt6', '6');
INSERT INTO `mayikt_user_0` VALUES ('8', 'mayikt8', '8');

-- ----------------------------
-- Table structure for mayikt_user_1
-- ----------------------------
DROP TABLE IF EXISTS `mayikt_user_1`;
CREATE TABLE `mayikt_user_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of mayikt_user_1
-- ----------------------------
INSERT INTO `mayikt_user_1` VALUES ('1', 'mayikt1', '1');
INSERT INTO `mayikt_user_1` VALUES ('3', 'mayikt3', '3');
INSERT INTO `mayikt_user_1` VALUES ('5', 'mayikt5', '5');
INSERT INTO `mayikt_user_1` VALUES ('7', 'mayikt7', '7');
INSERT INTO `mayikt_user_1` VALUES ('9', 'mayikt9', '9');



Maven 依賴:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.taotao</groupId>
    <artifactId>sharding-jdbc</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sharding-jdbc</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-namespace</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


application.yml 配置文件

# 數(shù)據(jù)源 mayiktdb
sharding:
  jdbc:
    datasource:
      names: shard1,shard2
      # 第一個(gè)數(shù)據(jù)庫(kù)
      shard1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/mayikt-member?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
        username: root
        password: root
      shard2:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/mayikt?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
        username: root
        password: root
    # 水平拆分的數(shù)據(jù)庫(kù)(表) 配置分庫(kù) + 分表策略 行表達(dá)式分片策略
    config:
      sharding:
        #默認(rèn)數(shù)據(jù)源(未設(shè)置分表策略的表將默認(rèn)用此數(shù)據(jù)源)
        default-database-name: shard1
        #默認(rèn)分庫(kù)策略
        default-database-strategy:
           standard:
             sharding-column: id
             precise-algorithm-class-name: com.taotao.rfspringboot.config.DataBasePreciseRule
        tables:
          mayikt_user:  ##虛擬表名稱  mayikt_user_0 mayikt_user_1
            actual-data-nodes: shard$->{1..2}.mayikt_user_$->{0..2}  # 沒(méi)有帶上 分片字段
            table-strategy:
              standard:  ##SELECT * FROM  mayikt_user_1 where id =1
                precise-algorithm-class-name: com.taotao.rfspringboot.config.MayiktRangeShardingAlgorithm
                sharding-column: id
      # 打印執(zhí)行的數(shù)據(jù)庫(kù)
      props:
        sql:
          show: true

# 打印執(zhí)行的sql語(yǔ)句
spring:
  main:
    allow-bean-definition-overriding: true
server:
  port: 8081

mybatis-plus:
  # 如果是放在src/main/java目錄下 classpath:/com/yourpackage/*/com.exchange.mapper/*Mapper.com.exchange.mapper
  # 如果是放在resource目錄 classpath:/com.exchange.mapper/*Mapper.com.exchange.mapper
  mapper-locations: classpath:/mapper/*.xml
  #實(shí)體掃描,多個(gè)package用逗號(hào)或者分號(hào)分隔
  typeAliasesPackage: com.taotao.rfspringboot.entity
  global-config:
    #主鍵類型  0:"數(shù)據(jù)庫(kù)ID自增", 1:"用戶輸入ID",2:"全局唯一ID (數(shù)字類型唯一ID)", 3:"全局唯一ID UUID";
    #若采用雪花算法生成id勺择,需要在生成的實(shí)體類中將id的type = IdType.AUTO去掉
    id-type: 0
    #字段策略 0:"忽略判斷",1:"非 NULL 判斷"),2:"非空判斷"
    field-strategy: 2
    #駝峰下劃線轉(zhuǎn)換
    db-column-underline: true
    #刷新mapper 調(diào)試神器
    #refresh-mapper: true
    #數(shù)據(jù)庫(kù)大寫下劃線轉(zhuǎn)換
    #capital-mode: true
    # Sequence序列接口實(shí)現(xiàn)類配置
    #邏輯刪除配置(下面3個(gè)配置)
    logic-delete-value: Y
    logic-not-delete-value: N
    #sql-injector: com.nky.pork.quality.standard.conf.MybatisPlusConfig
    configuration:
      #配置返回?cái)?shù)據(jù)庫(kù)(column下劃線命名&&返回java實(shí)體是駝峰命名)创南,自動(dòng)匹配無(wú)需as(沒(méi)開(kāi)啟這個(gè),SQL需要寫as: select user_id as userId)
      map-underscore-to-camel-case: true
      cache-enabled: false
      #配置JdbcTypeForNull, oracle數(shù)據(jù)庫(kù)必須配置
      jdbc-type-for-null: 'null'

entity:

package com.taotao.shardingjdbc.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

/**
 *@author tom
 *Date  2020/11/6 0006 8:27
 *
 */
@Data
@TableName("mayikt_user")
public class Mayikt_user {
    private Integer id;
    private String name;
    private Integer age;

    public Mayikt_user(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}



數(shù)據(jù)庫(kù)訪問(wèn):

package com.taotao.shardingjdbc.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.taotao.shardingjdbc.entity.MayiktUser;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 *@author tom
 *Date  2020/11/6 0006 8:29
 *
 */
public interface MayiktUserMapper  extends BaseMapper<MayiktUser> {
    /**
     * 查詢所有
     *
     * @return
     */
    @Select("SELECT * FROM mayikt_user")
    List<MayiktUser> userList();

    /**
     * 分頁(yè)查詢
     *
     * @return
     */
    @Select("SELECT * FROM mayikt_user limit 0,2")
    List<MayiktUser> userListPage();

    /**
     * 排序
     *
     * @return
     */
    @Select("SELECT * FROM mayikt_user order by id desc ")
    List<MayiktUser> userOrderBy();

    /**
     * get by id
     *
     * @return
     */
    @Select("SELECT * FROM mayikt_user where id =#{id} ")
    List<MayiktUser> getByUserId(Long id);
}



Controller:

package com.taotao.shardingjdbc.controller;

import com.taotao.shardingjdbc.entity.MayiktUser;
import com.taotao.shardingjdbc.mapper.MayiktUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 *@author tom
 *Date  2020/11/6 0006 8:41
 *
 */
@RestController
public class UserController {
    @Autowired
    private MayiktUserMapper mayiktUserMapper;


    @RequestMapping("/insertUser")
    public  String insertUser(){
        for (int i = 0; i <10 ; i++) {
            MayiktUser mayiktUser=new MayiktUser(i,"mykt"+i,i);
           try {
                mayiktUserMapper.insert(mayiktUser);
           }catch (Exception e){
               e.printStackTrace();
           }
        }
             return  "success";
    }

/**
 * 查詢所有
 */

@RequestMapping("/userList")
public List<MayiktUser> userList(){
    return  mayiktUserMapper.userList();
}

/**
 * 分頁(yè)查詢
 */
@RequestMapping("/userListPage")
public  List<MayiktUser> userListpage(){
    return  mayiktUserMapper.userListPage();
}
/**
 * 排序
 */

@RequestMapping("/userOrderBy")
    public  List<MayiktUser> userOrderBy(){
    return  mayiktUserMapper.userOrderBy();
}

@RequestMapping("/getByUserId")
    public  List<MayiktUser> getByUserId(Long id){
    return  mayiktUserMapper.getByUserId(id);
}
}






package com.taotao.rfspringboot.config;

import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;

import java.util.Collection;

/**
 * 數(shù)據(jù)庫(kù)分片規(guī)則
 *
 * @author Mos
 */
public class DataBasePreciseRule  implements PreciseShardingAlgorithm<Long> {


  @Override
  public String doSharding(Collection<String> databaseNames, PreciseShardingValue<Long> shardingValue) {

    /**
     * databaseNames 所有分片庫(kù)的集合
     * shardingValue 為分片屬性省核,其中 logicTableName 為邏輯表稿辙,columnName 分片健(字段)气忠,value 為從 SQL 中解析出的分片健的值
     */
    for (String databaseName : databaseNames) {

      String value = shardingValue.getValue() % databaseNames.size()+1 + "";
      if (databaseName.endsWith(value)) {
        System.out.println(databaseName+"&&&"+shardingValue.getValue() +"*********"+databaseNames.size());
        return databaseName;
      }
    }
    throw new IllegalArgumentException();


  }
}

package com.taotao.rfspringboot.config;

import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import lombok.extern.slf4j.Slf4j;

import java.util.Collection;

@Slf4j
public class MayiktRangeShardingAlgorithm implements PreciseShardingAlgorithm<Long> {


    @Override
    public String doSharding(Collection<String> databaseNames, PreciseShardingValue<Long> shardingValue) {

        /**
         * databaseNames 所有分片庫(kù)的集合
         * shardingValue 為分片屬性邻储,其中 logicTableName 為邏輯表,columnName 分片骄稍搿(字段)吨娜,value 為從 SQL 中解析出的分片健的值
         */
      for (String databaseName : databaseNames) {
            String value = shardingValue.getValue() % databaseNames.size() + "";
            if (databaseName.endsWith(value)) {
                return databaseName;
            }
        }
        throw new IllegalArgumentException();


    }



}

歸并數(shù)據(jù)原理

1.SELECT * FROM mayikt_user
底層發(fā)出多條語(yǔ)句查詢每張表數(shù)據(jù),在本地實(shí)現(xiàn)數(shù)據(jù)合并

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末舌菜,一起剝皮案震驚了整個(gè)濱河市萌壳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖袱瓮,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缤骨,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡尺借,警方通過(guò)查閱死者的電腦和手機(jī)绊起,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)燎斩,“玉大人虱歪,你說(shuō)我怎么就攤上這事≌け恚” “怎么了笋鄙?”我有些...
    開(kāi)封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)怪瓶。 經(jīng)常有香客問(wèn)我萧落,道長(zhǎng),這世上最難降的妖魔是什么洗贰? 我笑而不...
    開(kāi)封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任找岖,我火速辦了婚禮,結(jié)果婚禮上敛滋,老公的妹妹穿的比我還像新娘许布。我一直安慰自己,他們只是感情好绎晃,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布蜜唾。 她就那樣靜靜地躺著,像睡著了一般庶艾。 火紅的嫁衣襯著肌膚如雪灵妨。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天落竹,我揣著相機(jī)與錄音泌霍,去河邊找鬼。 笑死述召,一個(gè)胖子當(dāng)著我的面吹牛朱转,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播积暖,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼藤为,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了夺刑?” 一聲冷哼從身側(cè)響起缅疟,我...
    開(kāi)封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤分别,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后存淫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體耘斩,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年桅咆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了括授。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岩饼,死狀恐怖荚虚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情籍茧,我是刑警寧澤版述,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站寞冯,受9級(jí)特大地震影響院水,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜简十,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撬腾。 院中可真熱鬧螟蝙,春花似錦、人聲如沸民傻。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)漓踢。三九已至牵署,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間喧半,已是汗流浹背奴迅。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挺据,地道東北人取具。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像扁耐,于是被迫代替她去往敵國(guó)和親暇检。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361