实践:OBD部署源码编译OceanBase社区版本

排版不好,请看原文
https://www.yuque.com/yiyezhou/rgak0e/lcxg27okp4c6506w?singleDoc# 《实践:OBD部署源码编译OceanBase社区版本》
本文主要描述了

  1. 单机环境下 如何用 源码编译 和OBD 启动集群。
  1. OBD 插件机制 提供压测前优化

不确定:obd部署集群,定制组件observer 本地镜像 变更后如何替换问题。

  1. 该方法不使用生产上的版本升级问题 obd mirror update 【没有验证】

    如何升级部署自己通过源码编译的observer(v3.1.2)到已运行的observer集群

  2. 如果是作为开发变更代码,OBD 定制组件方式部署后 【验证没有问题】

oceanbase-ce: <br /> tag: my-oceanbase<br />然后make install /cp observer方式 ,然后obd直接重启集群。

obd 升级部署 obd mirror update 和直接make install /cp **observer ** 有什么区别,
有清楚麻烦留言告知告知。

<a name="B0HIa"></a>

一、前言:

之前公司分配服务器被回收,没有足够资源部署。<br />结合 OceanBase 数据库社区版部署概述快速体验 OceanBase 数据库 这2篇文章。

  1. 本次采用 mac, Docker 镜像, obd 方式源码 ,部署进行 单机部署,体验OceanBase 4.1。
  • 并没使用方案三:部署 OceanBase 容器环境

    主要原因就是Docker 镜像当作一个centos系统来使用,为后续开发作准备

  1. 用sysbench做简单的测试
  • MySQL OceanBase TiDB 与在体系架构上的差别非常大,很多方面都很难找到一个共同的基准点,尤其是单机情况下,所以大家不要消耗过多精力在这类基准测试上,应该更多关注 在应用程序使用场景上的区别

Docker设置<br />
image.png

<a name="Lr5bu"></a>

二、使用源码构建 OceanBase 数据库

<a name="tYHef"></a>

2.1 编译

参考:https://www.oceanbase.com/docs/community-observer-cn-0000000000160092
cat /etc/*-release
CentOS Linux release 7.9.2009 (Core)

git clone git@github.com:watchpoints/oceanbase.git
# 进入代码根目录
cd oceanbase/
# DEBUG 构建
bash build.sh debug --init --make -j4  //稍微等待

cd build_debug/src/observerbuild_debug/src/observer


查看版本:后续有用

## 环境变量
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
make install

## 查看版本
[root@3346da816048 observer]# observer --version
observer --version
observer (OceanBase_CE 4.2.0.0)


必须设置环境变量设置环境变量 不然出现libaio.so错误。
ldd ~/oceanbase/build_debug/src/observer/observer              
            linux-vdso.so.1 =>  (0x00007ffc6ef37000)
            librt.so.1 => /lib64/librt.so.1 (0x00007fbe2d1bf000)
            libdl.so.2 => /lib64/libdl.so.2 (0x00007fbe2cfbb000)
            libm.so.6 => /lib64/libm.so.6 (0x00007fbe2ccb9000)
            libaio.so.1 => not found
            libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fbe2ca9d000)
            libc.so.6 => /lib64/libc.so.6 (0x00007fbe2c6cf000)
            /lib64/ld-linux-x86-64.so.2 (0x00007fbe6c361000

<a name="KXcm6"></a>

2.2 下载 OBD

  • 下载安装oceanbase-all-in-one ,主要获取obd(也可以直接安装obd)
bash -c "$(curl -s https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/download-center/opensource/oceanbase-all-in-one/installer.sh)"

Install Finished 
=====================================================================
Setup Environment:     source ~/.oceanbase-all-in-one/bin/env.sh 
Start Web Service:     obd web 
Quick Start:           obd demo 
More Details:          obd -h 
=====================================================================

which obd
/root/.oceanbase-all-in-one/obd/usr/bin/obd
obd --version
OceanBase Deploy: 2.0.1

<a name="bSen2"></a>

2.2.2 obd工具说明

  • obd 安装目录(后续有用)
    :::warning
    ~/obd <br />cluster[obd 部署目录] <br /> mirror <br />remote和local 2个目录<br />optimize【集成测试自动调优】 <br />plugins

相关阅读:<br />分析obd日志了解其部署集群过程<br />https://zhuanlan.zhihu.com/p/464512232
:::

├── config_parser 配置解析器<br />├── docs 文档<br />├── example 样例<br />├── optimize 集成测试自动调优<br />├── plugins 业务插件<br />├── profile 命令行自动补齐<br />├── rpm RPM打包配置<br />├── service 白屏后端<br />└── web 白屏前端

  • 关键文件

├── _cmd.py 命令层入口 <br />├── core.py 核心编排<br />├── _deploy.py 配置管理<br />├── _environ.py 环境变量管理<br />├── _mirror.py 远程镜像仓库管理<br />├── _optimize.py 自动调优管理<br />├── _plugin.py 插件管理<br />├── _repository.py 仓库管理<br />├── ssh.py SSH客户端<br />└── _stdio.py 命令行IO
<a name="Oaz69"></a>

2.3 制作本地镜像

参考:https://gitee.com/oceanbase/obdeploy

# 离线安装部署,禁用远程仓库
obd mirror disable remote,

[root@3346da816048 ~]# obd mirror disable remote
Disable remote ok

#obd mirror create

使用该命令可以以本地目录为基础创建一个镜像。
此命令主要用于使用 OBD 启动自行编译的 OceanBase 开源软件,
您可以通过此命令将编译产物加入本地仓库

make DESTDIR=./ install && 
obd mirror create -n oceanbase-ce -V 4.2.0.0 -p /usr/local -t my-oceanbase
package ok
name: oceanbase-ce
version: 4.2.0.0  // observer --version 查询最新版本号
release:20230514112232
arch: x86_64
md5: 630917f3350b447488c3fdce9c7967d5 

# 细心你发现 -p /usr/local 和文档上有区别

# 记住这个hash值或者 my-oceanbase名字

<a name="vn7QO"></a>

2.4 配置文件启动

  • 在配置文件中,增加定制版本

ceanbase-ce:<br /> package_hash:630917f3350b447488c3fdce9c7967d5 //记住这个hash值


//修改配置:
https://github.com/oceanbase/obdeploy/blob/master/example/mini-local-example.yaml
ceanbase-ce:
  package_hash:630917f3350b447488c3fdce9c7967d5
  servers:
    # Please don't use hostname, only IP can be supported
    - 127.0.0.1
  global:
    #  The working directory for OceanBase Database. OceanBase Database is started under this directory. This is a required field.
    home_path: /root/observer
    # The directory for data storage. The default value is $home_path/store.
    data_dir: /data/observer/data
    # The directory for clog, ilog, and slog. The default value is the same as the data_dir value.
    redo_dir: /root/observer/redo
      
//启动 
obd cluster deploy watchpoints -c ./mini-local-example.yaml
//修改配置:
obd cluster edit-config  watchpoints
obd cluster redeploy watchpoints  
      
obd cluster start watchpoints

Wait for observer init ok
+---------------------------------------------+
|                   observer                  |
+-----------+---------+------+-------+--------+
| ip        | version | port | zone  | status |
+-----------+---------+------+-------+--------+
| 127.0.0.1 | 4.2.0.0 | 2881 | zone1 | ACTIVE |
+-----------+---------+------+-------+--------+

    
obclient -h127.0.0.1 -P2881 -uroot -Doceanbase -A
        
  • 每次代码变动怎么办?
    :::success
    我之前采用tag 声明后,make install 或者cp是可用的。不使用版本升级使用。<br />遗留任务:每次启动是否检查hash值?了解obd源码在在回答。

Q: 如何指定使用特定版本的组件?<br />A: 在部署配置文件中使用 package_hash 或 tag 声明。 如果您给自己编译的 OceanBase-CE 设置了 tag,您可以使用 tag 来指定。如:<br />oceanbase-ce:<br /> tag: my-oceanbase

您也可以通过 package_hash 来指定特定的版本。当您使用 obd mirror 相关命令时会打印出组件的 md5值,这个值即为 package_hash。<br />oceanbase-ce:<br /> package_hash: 929df53459404d9b0c1f945e7e23ea4b89972069
:::

<a name="zWYQW"></a>

三. OceanBase性能测试:

采用Sysbench进行测试,为后续开发寻找性能瓶颈做准备,不是纯粹的跑分,也没有过多优化参数。

在OceanBase 入门到实战教程 实践练习六(必选):查看 OceanBase 执行计划 介绍三个测试工具<br />OLTP

  • TPC-C(Transaction Processing Performance Council)是针对 OLTP 的基准测试模型
  • Sysbench 是一个基于 LuaJIT 的可编写脚本的多线程基准测试工具,可以用于数据库性能(OLTP 基准测试)

OLAP

  • TPC-H可以说是世界上最为流行的OLAP workload的benchmark程序,是评估OLAP数据库最常见的工具

这里采用Sysbench
<a name="Ncwfu"></a>

3.1 创建普通测试租户



obclient -uroot@sys -h127.0.0.1 -P2881 oceanbase  # 这里没有obproxy,因此端口不是2883

# 修改最新规格为1G
在分配资源池时,普通租户的内存的最小规格由隐藏配置项 __min_full_resource_pool_memory 控制,
默认值为 5G,社区版本默认2g

alter system __min_full_resource_pool_memory=1073741824;
SELECT * FROM oceanbase.__all_virtual_sys_parameter_stat WHERE name='__min_full_resource_pool_memory'\G;


# 创建资源单元(1c/1g/2G):UNIT=sysbench_unit_1c1g

 CREATE RESOURCE UNIT sysbench_unit_1c1g MAX_CPU 1, MEMORY_SIZE '1g',LOG_DISK_SIZE '2G';

# 查看新创建的资源单元:sysbench_unit_1c1g
SELECT * FROM __all_unit_config where name='sysbench_unit_1c1g' \G;
unit_config_id: 1006
          name: sysbench_unit_1c1g
       max_cpu: 1
       min_cpu: 1
   memory_size: 1073741824
 log_disk_size: 2147483648
      max_iops: 10000
      min_iops: 10000
   iops_weight: 1

# 创建资源池:POOL=sysbench_pool
create resource pool sysbench_pool unit = 'sysbench_unit_1c1g', unit_num = 1;
# 查看资源池
SELECT * FROM __all_resource_pool \G;
*************************** 2. row ***************************
        gmt_create: 2023-05-20 14:59:15.650372
      gmt_modified: 2023-05-20 14:59:15.650372
  resource_pool_id: 1007
              name: sysbench_pool
        unit_count: 1
    unit_config_id: 1006
         zone_list: zone1
         tenant_id: -1
      replica_type: 0
is_tenant_sys_pool: 0


# 创建租户:tenant=tpctest
drop TENANT tpctest;
CREATE TENANT tpctest resource_pool_list=('sysbench_pool') set variables ob_compatibility_mode='mysql', ob_tcp_invited_nodes='%';

# 查看创建成功的租户
select tenant_id,tenant_name,primary_zone from __all_tenant;


## 创建数据库
obclient -uroot@tpctest -h127.0.0.1 -P2881
create database sysbench_test;

<a name="bAOBO"></a>

遇到错误1:

  • 现象:创建租户失败
ERROR 4733 (HY000): zone 'zone1' resource not enough to hold 1 unit. You can check resource info by views: DBA_OB_UNITS, GV$OB_UNITS, GV$OB_SERVERS.
server '"127.0.0.1:2882"' MEMORY resource not enough
  • 相关概念:

https://gw.alipayobjects.com/os/bmw-prod/5b8f5011-e3ae-441d-ba0e-e8fea1e90508.pdf
<a name="VcOqd"></a>

image.png

image.png

memory_limit 参数可用于调整 OceanBase 数据库的最大可使用内存数
system_memory 参数用于配置租户 ID 为 500 的租户的内存,即程序运行内存。
需要增加memory_limit大小。

  • 方法:增加 observer内存上限5g

:::warning
memory_limit 改为5g<br />obd cluster edit-config watchpoints<br />obd cluster reload watchpoints //之前创建租户没有了。
:::

<a name="nj5wR"></a>

3.2 Sysbench 测试

  • 通过 OBD test 命令一键进行 Sysbench 测试。
  • ./ob_sysbench.sh
 yum install ob-sysbench
./ob_sysbench.sh

#!/bin/bash
export ENABLE_PROTOCOL_OB20=0
echo "run oltp_read_only test"
obd test sysbench watchpoints --tenant=tpctest --script-name=oltp_read_only.lua --table-size=1000 --threads=1 --rand-type=uniform
echo "run oltp_write_only test"
obd test sysbench watchpoints  --tenant=tpctest --script-name=oltp_write_only.lua --table-size=1000 --threads=1 --rand-type=uniform

echo "run oltp_read_write test"
obd test sysbench watchpoints --tenant=tpctest --script-name=oltp_read_write.lua --table-size=1000 --threads=1--rand-type=uniform

<a name="lIMTt"></a>

遇到错误2 :

  • obclient [oceanbase]> alter system set _trace_control_info='%s' tenant='tpctest';

ERROR 4179 (HY000): alter the parameter _trace_control_info not allowed

3.3 测试结果:

下面测试结果:是mac docker 4C8G,1千个记录,租户1c1g,1个线程。
目的学习使用,不作为性能对比参考依据。请看官方测试报告
https://www.oceanbase.com/docs/common-oceanbase-database-cn-0000000001954653

# run oltp_read_only test
 10s ] thds:  1 tps: 47.09 qps: 754.89 (r/w/o: 660.60/0.00/94.29) lat (ms,95%): 46.63 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 1 tps: 61.90 qps: 989.33 (r/w/o: 865.53/0.00/123.80) lat (ms,95%): 38.25 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 1 tps: 79.09 qps: 1265.72 (r/w/o: 1107.53/0.00/158.19) lat (ms,95%): 24.83 err/s: 0.00 reconn/s: 0.00
[ 40s ] thds: 1 tps: 77.40 qps: 1238.17 (r/w/o: 1083.36/0.00/154.81) lat (ms,95%): 24.38 err/s: 0.00 reconn/s: 0.00
[ 50s ] thds: 1 tps: 75.20 qps: 1203.97 (r/w/o: 1053.58/0.00/150.40) lat (ms,95%): 22.28 err/s: 0.00 reconn/s: 0.00
[ 60s ] thds: 1 tps: 78.40 qps: 1254.53 (r/w/o: 1097.73/0.00/156.80) lat (ms,95%): 20.37 err/s: 0.00 reconn/s: 0.00
SQL statistics:
# run oltp_write_only test
[ 10s ] thds: 1 tps: 121.18 qps: 727.59 (r/w/o: 0.00/485.13/242.46) lat (ms,95%): 17.95 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 1 tps: 180.70 qps: 1084.11 (r/w/o: 0.00/722.71/361.40) lat (ms,95%): 8.90 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 1 tps: 179.20 qps: 1075.00 (r/w/o: 0.00/716.60/358.40) lat (ms,95%): 8.58 err/s: 0.00 reconn/s: 0.00
[ 40s ] thds: 1 tps: 167.80 qps: 1006.72 (r/w/o: 0.00/671.11/335.61) lat (ms,95%): 9.56 err/s: 0.00 reconn/s: 0.00
[ 50s ] thds: 1 tps: 167.50 qps: 1004.99 (r/w/o: 0.00/669.99/335.00) lat (ms,95%): 8.90 err/s: 0.00 reconn/s: 0.00
[ 60s ] thds: 1 tps: 147.10 qps: 882.98 (r/w/o: 0.00/588.78/294.19) lat (ms,95%): 10.65 err/s: 0.00 reconn/s: 0.0

# run oltp_read_write test
Threads started!
[ 10s ] thds: 1 tps: 16.70 qps: 334.75 (r/w/o: 234.47/66.79/33.50) lat (ms,95%): 87.56 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 1 tps: 22.90 qps: 458.40 (r/w/o: 321.00/91.60/45.80) lat (ms,95%): 64.47 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 1 tps: 23.50 qps: 468.91 (r/w/o: 327.91/94.00/47.00) lat (ms,95%): 66.84 err/s: 0.00 reconn/s: 0.00
[ 40s ] thds: 1 tps: 23.40 qps: 468.49 (r/w/o: 328.09/93.60/46.80) lat (ms,95%): 64.47 err/s: 0.00 reconn/s: 0.00
[ 50s ] thds: 1 tps: 23.80 qps: 476.91 (r/w/o: 334.11/95.20/47.60) lat (ms,95%): 63.32 err/s: 0.00 reconn/s: 0.00
[ 60s ] thds: 1 tps: 22.60 qps: 451.97 (r/w/o: 316.38/90.39/45.20) lat (ms,95%): 65.65 err/s: 0.00 reconn/s: 0.00

<a name="schcu"></a>

四、其他测试

OB(分布式),TiDB 与 MySQL (偏向单机)在体系架构上的差别非常大,很多方面都很难找到一个共同的基准点,所以大家不要消耗过多精力在这类基准测试上,应该更多关注 在应用程序使用场景上的区别.

<a name="iRRv4"></a>

4.1 TIDB

详细最小配置模板 | 最小集群拓扑,包括 tidb-server、tikv-server、pd-server。 |
| HTAP 业务 | 部署 TiFlash 拓扑架构 | 简单 TiFlash 配置模版

详细 TiFlash 配置模版 | 在最小拓扑的基础上部署 TiFlash。TiFlash 是列式存储引擎,已经逐步成为集群拓扑的标配。 |

软件 版本 备注
centOS 8 window+虚拟机
cpu Virtual CPU 4
内存 4G
磁盘 普通
最小拓扑架构 个数
Tidb 1 默认参数
pd 1 默认参数
TiKV 1 默认参数
Tiflash 1 默认参数
image.png

<a name="GaG6e"></a>

手动进行Sysbench 测试

# Building and Installing From Source
https://github.com/akopytov/sysbench#rhelcentos
./configure --with-mysql-includes=/usr/include/mysql/ --with-mysql-libs=/usr/lib64/mysql/ --with-mysql
# 压测时用到的 lua 脚本
/usr/local/share/sysbench/
# 测试类型 
oltp_read_only
oltp_write_only
oltp_read_write

# 准备配置文件:config
mysql-host=127.0.0.1
mysql-port=4000
mysql-user=root
mysql-password=BW07-+5vE36q@b*9RA
mysql-db=sbtest
db-driver=mysql

# 开始导入数据,config 文件为上一步中配置的文件 1w记录
sysbench --config-file=config oltp_point_select --tables=5 --table-size=10000 prepare

# 数据预热与统计信息收集
sysbench --config-file=config oltp_point_select --tables=5 --table-size=10000 prewarm


<a name="Z0KJI"></a>

Read-only 测试命令

sysbench --config-file=config oltp_read_only --tables=5 --table-size=10000  --db-ps-mode=auto  --report-interval=10 --threads=1 --rand-type=uniform run



<a name="iK1gA"></a>
## 4.2 Mysql

- mysql 版本
```shell
# 查找以前是否装有MySQL
rpm -qi mysql-server
Name        : mysql-server
Version     : 8.0.26
# 启动:
service mysqld start
# 默认空密码
mysql -uroot 


mysql-host=127.0.0.1
mysql-port=3306
mysql-user=root
mysql-db=sbtest
db-driver=mysql



# 5、总结:

1. 单机环境下 源码源码后,OBD如何部署替换。
- [https://gitee.com/oceanbase/obdeploy](https://gitee.com/oceanbase/obdeploy)
2. OBD 插件机制 提供压测前优化
- [https://gitee.com/oceanbase/obdeploy/blob/master/plugins/sysbench/4.0.0.0/run_test.py](https://gitee.com/oceanbase/obdeploy/blob/master/plugins/sysbench/4.0.0.0/run_test.py)
- [https://gitee.com/oceanbase/obdeploy/blob/master/optimize/oceanbase/4.0.0.0/sysbench.yaml](https://gitee.com/oceanbase/obdeploy/blob/master/optimize/oceanbase/4.0.0.0/sysbench.yaml)
3. 通过单机测试 MySQL OceanBase ,tidb发现等架构有差异
- 现在说不清楚,预告 下篇文章介绍。https://www.yuque.com/yiyezhou/rgak0e/lcxg27okp4c6506w?singleDoc# 《实践:OBD部署源码编译OceanBase社区版本》https://www.yuque.com/yiyezhou/rgak0e/lcxg27okp4c6506w?singleDoc# 《实践:OBD部署源码编译OceanBase社区版本》




<a name="Q9RUf"></a>
### <br />
<a name="VL8io"></a>
### 
<a name="D8fl3"></a>
### <br />


本文由[mdnice](https://mdnice.com/?platform=6)多平台发布
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容