利用Docker搭建一套Mycat2+MySQL8一主一从、读写分离的最简单集群(保姆教程)

文章目录

    • 1、Mycat介绍
      • 1.1、mycat简介
      • 1.2、mycat重要概念
      • 1.3、Mycat1.x与Mycat2功能对比
      • 1.2、主从复制原理
    • 2、前提准备
    • 3、集群规划
    • 4、安装和配置mysql主从复制
      • 4.1、master节点安装mysql8容器
      • 4.2、slave节点安装mysql8容器
      • 4.2、配置主从复制
      • 4.3、测试主从复制配置
    • 5、安装mycat2和配置读写分离集群
      • 5.1、docker部署mycat2
      • 5.2、navicat连接mycat2
      • 5.3、配置主从集群信息实现读写分离
    • 6、测试

1、Mycat介绍

1.1、mycat简介

Mycat是一套布式数据库中间件(虚拟数据库类),它本身并不存储数据库。

其原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的 SQL 语句,首先对 SQL 语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、 缓存分析等,然后将此 SQL 发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.2、mycat重要概念

  • 逻辑库schema、逻辑表:虚拟的逻辑上的库表
    业务开发人员通常在实际应用中并不需要知道中间件的存在,只需 要关注数据库,所以数据库中间件可以被当作一个或多个数据库集 群构成的逻辑库;逻辑库,与MySQL中的Database(数据库)对应,⼀个逻辑库中定义了所包括的Table。
  • 全局表
  • 数据源:真实的mysql数据库
  • 集群配置json

1.3、Mycat1.x与Mycat2功能对比

功能1.6版本2 版本
多语句不支持支持
blob值支持一部分支持
全局二级索引不支持支持
任意跨库join(包含复杂查询)catlet支持支持
分片表与分片表JOIN查询ER表支持支持
关联子查询不支持支持一部分
分库同时分表不支持支持
存储过程支持固定形式的支持更多
支持逻辑视图不支持支持
支持物理视图支持支持
批量插入不支持支持
执行计划管理不支持支持
路由注释支持支持
集群功能支持支持更多集群类型
自动hash分片算法不支持支持
支持第三方监控支持mycat-web支持普罗米斯,kafka日志等监控
流式合拼结果集支持支持
范围查询支持支持
单表映射物理表不支持支持
XA事务弱XA支持,事务自动恢复
支持MySQL8需要更改mysql8的服务器配置支持支持
虚拟表不支持支持
joinClustering不支持支持
union all语法不支持支持
BKAJoin不支持支持
优化器注释不支持支持
ER表支持支持
全局序列号支持支持
保存点不支持支持
离线迁移支持支持(实验)
增量迁移CRC32算法支持BINLOG追平(实验)
安全停机不支持支持(实验)
HAProxy协议不支持支持
会话粘滞update后select会粘滞update后select会粘滞且支持设置时间
全局表插入支持全局序列号不支持支持
全局表插入支持主表插入自增结果作为序列号不支持支持
外部调用的分片算法不支持但可定制支持

Mycat1.x跟Mycat2的配置完全不一样了。

1.2、主从复制原理

在这里插入图片描述
重点理解:通过三个线程的运行过程原理

    1. 主服务将数据的更新记录保存到二进制日志–主服务器线程
    1. 从服务将主服务的二进制日志复制到本地中继日志–从服务IO线程
    1. 从服务读取中继日志,更新本地数据–从服务SQL线程

2、前提准备

  1. 两台Linux服务器,配置为:8c32g5m/ CentOS Linux release 7.9.2009

  2. 都安装docker,docker版本信息如下:
    在这里插入图片描述

  3. 其中一台安装配置好jdk1.8 java环境,因为mycat是用java语言编写的,运行需要jdk环境。

在这里插入图片描述

3、集群规划

主机名公网ip内网地址端口号角色用户名密码
newvts-a39.xxx.xxx.232192.168.1.938066mycatrootxxxxxxxx
newvts-a39.xxx.xxx.232192.168.1.933307masterrootxxxxxxxx
newvts-b39.xxx.xxx.190192.168.1.943308slaverootxxxxxxxx

其中 newvts-a这台机子安装mycat2和mysql8, newvts-b只安装mysql8。

4、安装和配置mysql主从复制

4.1、master节点安装mysql8容器

  1. 拉取mysql8镜像。
#docker拉取mysql8镜像
docker pull mysql:8.0.25
  1. master节点安装mysql,容器名称为:mysql-vts-master1
docker run -p 3307:3306 --name mysql-vts-master1 \
-v /mydata/mysql-vts-master/log:/var/log/mysql \
-v /mydata/mysql-vts-master/data:/var/lib/mysql \
-v /mydata/mysql-vts-master/conf:/etc/mysql \
-v /mydata/mysql-vts-master/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=xxxxxxx \
-d mysql:8.0.25
  1. 修改/mydata/mysql-vts-master/conf目录下的my.cnf,注意server_id为101。
vim /mydata/mysql-vts-master/conf/my.cnf
[mysqld]## 设置server_id,同一局域网中需要唯一
server_id=101 ## 指定不需要同步的数据库名称
binlog-ignore-db=mysql  ## 开启二进制日志功能
log-bin=mall-mysql-bin  ## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M  ## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed  ## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7  ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
  1. 重启mysq-vts-master1容器
docker restart mysql-vts-master1
  1. master节点的mysql数据库中新建一个数据同步用户
#进入容器
docker exec -it mysql-vts-master1 /bin/bash
mysql -uroot -p
xxxxx#新建一个数据同步用户,用户名为vts_slave
CREATE USER 'vts_slave'@'%' IDENTIFIED BY 'xxxxxx';
#给这个用户授予权限
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'vts_slave'@'%';
#考虑到我的MySQL8 ,密码密码必须修改为mysql_native_password的plugin才能被连接,不然无法连接
ALTER USER 'vts_slave'@'%' IDENTIFIED WITH mysql_native_password BY 'xxxxxx';
  1. 通过navicat连接master-mysql

测试连接成功!
在这里插入图片描述

4.2、slave节点安装mysql8容器

  1. 运行slave节点mysql8容器,端口号为3308;容器名:mysql-vts-slave1。
docker run -p 3308:3306 --name mysql-vts-slave1 \
-v /mydata/mysql-vts-slave/log:/var/log/mysql \
-v /mydata/mysql-vts-slave/data:/var/lib/mysql \
-v /mydata/mysql-vts-slave/conf:/etc/mysql \
-v /mydata/mysql-vts-slave/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=xxxx \
-d mysql:8.0.25
  1. 修改/mydata/mysql-vts-slave/conf目录下的my.cnf,注意server_id为102
vim /mydata/mysql-vts-slave/conf/my.cnf
[mysqld]## 设置server_id,同一局域网中需要唯一
server_id=102## 指定不需要同步的数据库名称
binlog-ignore-db=mysql  ## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin  ## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M  ## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed  ## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7  ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062  ## relay_log配置中继日志
relay_log=mall-mysql-relay-bin  ## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1  ## slave设置为只读(具有super权限的用户除外)
read_only=1
  1. 重启mysq-vts-slave1
docker restart mysql-vts-slave1
  1. navicat连接slave节点的mysql8
    测试连接成功!!

在这里插入图片描述

4.2、配置主从复制

  1. 进入主数据库 master容器,查看日志文件信息和位置标号。
#进入主数据库 master容器
docker exec -it mysql-vts-master1 /bin/bash
mysql -uroot -p
# xxxxxx#在主数据库master容器中查看主从状态
show master status;#记着下面两个值
# File mall-mysql-bin.000001
# Postion 1005

在这里插入图片描述

  1. 进入从数据库 slave容器 .在从数据库里面配置主从复制
#进入主数据库 slave
docker exec -it mysql-vts-slave1 /bin/bash
mysql -uroot -p
# xxxxxx#在从数据库里面配置主从复制
change master to master_host='192.168.1.93', master_user='vts_slave', master_password='xxxxx', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=1005, master_connect_retry=30;
  1. 在从数据库slave中开启主从同步、查看主从状态
#在从数据库中查看主从同步状态:
show slave status \G
#在从数据库中开启主从同步
start slave;
#在从数据库中查看主从同步状态:
show slave status \G

在这里插入图片描述

         Slave_IO_Running: YesSlave_SQL_Running: Yes

这两个线程为yes,证明主从复制配置成功。

4.3、测试主从复制配置

  1. 在主数据库中创建库和表,从数据库中也相应自动创建跟主数据库一样的库和表;
  2. 主数据库中的表操作更新,删除,新增时,从数据库中的表也自动更新;
  3. 从数据库操作更新,删除,新增操作时,主数据库不会发生变化。

5、安装mycat2和配置读写分离集群

5.1、docker部署mycat2

mycat2镜像我使用的是docker仓库中的zhangyx1619/mycat2:mysql-1.2.1,再次感谢张同学分享的mycat2镜像,我用着很不错。

#拉取镜像
docker pull zhangyx1619/mycat2:mysql-1.2.1
#查看镜像信息,主要查看环境变量的信息
docker inspect zhangyx1619/mycat2:mysql-1.2.1

在这里插入图片描述

拥有以下环境变量需要根据实际情况进行设置

                "DATA_SOURCE_URL=jdbc:mysql://127.0.0.1:6606/mysql?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8","DATA_SOURCE_USER=mycat","DATA_SOURCE_PASSWORD=!@#123","MYCAT_ROOT_PASSWORD=!@#123","MYCAT_HOME=/usr/local/mycat"

这里我们先通过一下方式运行一个mycat2容器,然后进入此容器拷贝配置文件目录到宿主机

#首先运行一个mycat容器
docker run -d -p 8066:8066 -e DATA_SOURCE_URL=jdbc:mysql://192.168.1.93:3307/mysql  -e DATA_SOURCE_USER=root -e DATA_SOURCE_PASSWORD=xxxxx  -e MYCAT_ROOT_PASSWORD=xxxxx  --name mycat2  zhangyx1619/mycat2:mysql-1.2.1#进入容器
docker exec -it 自己的容器id /bin/bash#拷贝容器内部的mycat配置目录到宿主机
docker cp 03f518d53daf:/usr/local/mycat /usr/local/mycat2#查看宿主机mycat2目录下的文件,确保conf logs两个文件夹的存在#删除刚运行的容器
docker rm -f 03f518d53daf#挂载数据卷(mycat2相应目录)重新运行zhangyx1619/mycat2:mysql-1.2.1,命令如下:
docker run -d -p 8066:8066 -e DATA_SOURCE_URL=jdbc:mysql://192.168.1.93:3307/mysql  -e DATA_SOURCE_USER=root -e DATA_SOURCE_PASSWORD=xxxxx -e MYCAT_ROOT_PASSWORD=xxxxx  -v /usr/local/mycat2/conf/:/usr/local/mycat/conf/ -v /usr/local/mycat2/logs/:/usr/local/mycat/logs/ --name mycat2  zhangyx1619/mycat2:mysql-1.2.1#查看运行的容器
docker ps -a

在这里插入图片描述
mycat2容器运行了,再次查看logs下的wrapper.log

tail -f /usr/local/mycat2/logs/wrapper.log 

显示successful standlone,证明mycat2启动成功!

5.2、navicat连接mycat2

在这里插入图片描述

查看数据库,mycat2中能看到逻辑库了
在这里插入图片描述

5.3、配置主从集群信息实现读写分离

  1. mycat2中创建逻辑库
-- 创建逻辑库
CREATE  DATABASE vts_info_sys;

在这里插入图片描述

此时查看 /usr/local/mycat2/conf/schemas/ 发现mycat自动创建了配置文件vts_info_sys.schema.json

ll  /usr/local/mycat2/conf/schemas/

在这里插入图片描述

  • customTables放置的是mycat默认的表的配置
  • globalTables放置的是全局表的配置
  • shardingTables放置分片表的配置
  • normalTables放置普通表的配置
  1. 修改逻辑库json
-- 修改逻辑库 指定vts_info_sys逻辑库默认的targetName, mycat会自动加载vts_info_sys下已经有的物理表或者视图作为单表.
/*+ mycat:createSchema{"customTables":{},"globalTables":{},"normalTables":{},"schemaName":"vts_info_sys","shardingTables":{},"targetName":"prototype"
} */;
  1. 创建数据源、查看数据源
#添加数据源
/*+mycat:createDataSource{"name":"vts_master1","url":"jdbc:mysql://192.168.1.93:3307/?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true","user":"root","password":"xxxx" } */;/*+mycat:createDataSource{"name":"vts_slave1","url":"jdbc:mysql://192.168.1.94:3308/?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true","user":"root","password":"xxxx" } */;#查看数据源
/*+ mycat:showDataSources{} */;

在这里插入图片描述

  1. 创建修改集群
#创建集群
/*!mycat:createCluster{"name":"vts_info_sys_rw_c","masters":["vts_master1"],"replicas":["vts_slave1"]} */;#查看集群
/*+ mycat:showClusters{} */;

在这里插入图片描述

  1. 查询负载均衡策略readBalanceType
  • BALANCE_ALL( 默认值 ):获取集群中所有数据源
  • BALANCE_ALL_READ:获取集群中允许读的数据源
  • BALANCE_READ_WRITE:获取集群中允许读写的数据源 , 但允许读的数据源优先
  • BALANCE_NONE:获取集群中允许写数据源 , 即主节点中选择
  • switchType
    NOT_SWITCH: 不进行主从切换
    SWITCH: 进行主从切换
  1. 在逻辑库中配置数据源(集群名称)
vim  /usr/local/mycat2/conf/schemas/vts_info_sys.schema.json

在这里插入图片描述
重启Mycat

docker restart mycat2

6、测试

验证读写分离(登录Mycat)

首先,在mycat2中插入4条数据

#插入4条数据
INSERT INTO vts_info_sys.sys VALUES(1, "hh1");
INSERT INTO vts_info_sys.sys VALUES(2, "hh2");
INSERT INTO vts_info_sys.sys VALUES(3, "hh3");
INSERT INTO vts_info_sys.sys VALUES(4, "hh4");

在这里插入图片描述

然后,查看主数据库master1和从数据库slave1中,同时也直接了4条相同的数据

在这里插入图片描述
在这里插入图片描述
此时,我修改从数据库slave1中的第4条数据为hh444,主数据库master1中的数据不会发生改变(这符合主从复制的原理)
在这里插入图片描述

这时,我在mycat2中进行查询操作,可以看到查询语句在主从二个主机间切换;

在这里插入图片描述
在这里插入图片描述

至此,使用MyCat2搭建一主二从数据库集群完成。

在这里插入图片描述


平庸的人用热闹填补空虚,优秀的人则用独处成就自己。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/56860.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yolov11的onnx模型C++ 调用

yolov11的onnx模型C调用 效果图一、python调用二、onnx模型导出三、python的onnx调用调用检测模型调用分割模型 四、C的onnx模型调用五 、视频流的检测后续 效果图 一、python调用 本文只记录生成的yolov11模型如何调用,其他可参考各种yolov11博客 模型下载&#x…

万年历制作

#include<stdio.h> int main() { int year0, month0, day0, y0, m0&#xff1b; scanf_s("%d %d", &year,&month); //判断闰年 for(y1900;y<year;y) { if ((y % 4 0 && y % 100 ! 0) || y % 400 0) …

C语言[求x的y次方]

C语言——求x的y次方 这段 C 代码的目的是从用户输入获取两个整数 x 和 y &#xff0c;然后计算 x 的 y 次幂&#xff08;不过这里有个小错误&#xff0c;实际计算的是 x 的 (y - 1) 次幂&#xff0c;后面会详细说&#xff09;&#xff0c;最后输出结果。 代码如下: #include…

Apache Paimon Catalog

Paimon Catalog可以持久化元数据&#xff0c;当前支持两种类型的metastore&#xff1a; 文件系统&#xff08;默认&#xff09;&#xff1a;将元数据和表文件存储在文件系统中。hive&#xff1a;在 hive metastore中存储元数据。用户可以直接从 Hive 访问表。 2.2.1 文件系统…

centeros7 编译ffmpeg

使用yum安装的路似乎已经堵住了&#xff0c;请求的镜像全是404或503 1.打开终端并使用yum安装EPEL存储库(Extra Packages for Enterprise Linux)&#xff1a;sudo yum install epel-release2.接下来&#xff0c;使用以下命令来安装FFmpeg&#xff1a;sudo yum install ffmpeg …

remote: HTTP Basic: Access denied

解决方法 输入&#xff1a; git config --system --unset credential.helper 再次进行 Git 操作&#xff0c;输入正确的用户名&#xff0c;密码即可。

static、 静态导入、成员变量的初始化、单例模式、final 常量(Content)、嵌套类、局部类、抽象类、接口、Lambda、方法引用

static static 常用来修饰类的成员&#xff1a;成员变量、方法、嵌套类 成员变量 被static修饰&#xff1a;类变量、成员变量、静态字段 在程序中只占用一段固定的内存&#xff08;存储在方法区&#xff09;&#xff0c;所有对象共享可以通过实例、类访问 (一般用类名访问和修…

OpenHarmony(1)开发环境搭建

一&#xff1a;开源项目 OpenHarmony是由开放原子开源基金会&#xff08;OpenAtom Foundation&#xff09;孵化及运营的开源项目&#xff0c;目标是面向全场景、全连接、全智能时代&#xff0c;基于开源的方式&#xff0c;搭建一个智能终端设备操作系统的框架和平台&#xff0…

使用SQL在PostGIS中创建各种空间数据

#1024程序员节&#xff5c;征文# 一、目录 1. 概述 2. 几何&#xff08;Geometry&#xff09;类型 创建点 创建线 创建面 3. 地理&#xff08;Geography&#xff09;类型 地理点&#xff08;GEOGRAPHY POINT&#xff09; 地理线串&#xff08;GEOGRAPHY LINESTRING&#xff…

Redis 单机、主从、哨兵和集群架构详解和搭建

目录 前言 单机部署 检查安装 gcc 环境 下载安装 Redis 启动 Redis 关闭 Redis 配置Redis 主从部署 整体架构图 主从复制配置 重启 Redis 验证 主从复制的作⽤ 主从复制缺点 哨兵部署&#xff08;Sentinel&#xff09; 整体架构图 哨兵模式配置 启动哨兵 验证…

MySQL-32.索引-操作语法

一.语法 二.代码实现 指定某个字段为主键&#xff0c;其实就是建立一个主键索引。而指定某个字段唯一&#xff0c;就是建立一个唯一索引。 -- 索引 -- 创建&#xff1a;为tb_emp表的name字段建立一个索引 create index idx_emp_name on tb_emp(name);-- 查询&#xff1a;查…

【智能大数据分析 | 实验四】Spark实验:Spark Streaming

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈智能大数据分析 ⌋ ⌋ ⌋ 智能大数据分析是指利用先进的技术和算法对大规模数据进行深入分析和挖掘&#xff0c;以提取有价值的信息和洞察。它结合了大数据技术、人工智能&#xff08;AI&#xff09;、机器学习&#xff08;ML&a…

基于java的山区环境监督管理系统(源码+定制+开发)环境数据可视化、环境数据监测、 环境保护管理 、污染防治监测系统 大数据分析

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

《Python游戏编程入门》注-第3章3

《Python游戏编程入门》的“3.2.4 Mad Lib”中介绍了一个名为“Mad Lib”游戏的编写方法。 1 游戏玩法 “Mad Lib”游戏由玩家根据提示输入一些信息&#xff0c;例如男人姓名、女人姓名、喜欢的食物以及太空船的名字等。游戏根据玩家输入的信息编写出一个故事&#xff0c;如图…

Postgresql 配置数据库表添加主键自增id

#1024程序员节&#xff5c;征文# 在 PostgreSQL 数据库中&#xff0c;如果你想创建一个自增的 ID 字段&#xff0c;通常会使用序列&#xff08;sequence&#xff09;配合默认值或者使用带有自动递增特性的 SERIAL 类型。以下是两种常见的方法来实现自增 ID&#xff1a; 使用 …

【C++】—— 模板进阶

【C】—— 模板进阶 1 非类型模板参数1.1 什么是非类型模板参数1.2 非类型模板参数对比宏的优势1.3 array 简单了解 2 模板的特化2.1 引子2.2 函数模板特化2.3 函数模板特化的坑2.4 类模板的特化2.4.1 全特化2.4.2 偏特化&#xff08;半特化&#xff09;2.4.3 选择2.4.4 偏特化…

Java最全面试题->Java基础面试题->JavaEE面试题->Web应用服务器面试题

文章目录 Web应用服务器面试题Tomcat是什么?Tomcat缺省端口是多少&#xff0c;如何修改&#xff1f;Tomcat 有那几种Connector 运行模式&#xff1f;什么是Servlet&#xff1f;Servlet请求过程&#xff1f;Tomcat执行流程&#xff1f;Tomcat部署方式?什么是JBoss ?在JBoss 7…

FPGA搭建PCIE3.0通信架构简单读写测试,基于XDMA中断模式,提供3套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案本博客方案的PCIE2.0版本 3、PCIE基础知识4、工程详细设计方案工程设计原理框图XDMA配置及使用XDMA中断模块数据缓存架构用户逻辑Windows版本XDMA驱动安装Linux版本XDMA驱动安装测试应用程序工程源码架构PCIE上板…

实测体验Claude 3.5升级版:AI首次实现直接操控电脑!

前言 就在10月22日晚上&#xff0c;Anthropic发布重大升级&#xff0c;发布Claude 3.5 Sonnet和Claude 3.5 Haiku新版本。 新的 Claude 3.5 Sonnet 在所有指标上都优于其他模型&#xff0c;包括 OpenAI 的 GPT-4 和谷歌的 Gemini 1.5 Pro。 Claude 3.5 Haiku 与之前的顶级 C…

【C++开篇】

首先初阶的数据结构相信大家已经学习的差不多了&#xff0c;关于初阶数据结构排序的相关内容的总结随后我也会给大家分享出来。C语言和C有许多相同的地方&#xff0c;但也有许多不相同的地方。接下来的C部分&#xff0c;我们主要是针对C与C语言不同的地方来与大家进行分享。其中…