第二节:ShardingSphere-Proxy数据分片算法(固定容量、时间区间算法)、分库分表、读写分离

一. 数据分片算法补充

1.  固定容量算法

(1). 配置文件

 

 说明:VOLUME_RANGE为固定容量算法,<2的数据在第1张表中,>=2 且 <2+3 存放在第2张表中(这里sharding-volume=3,表示分片区间的数据间隔)。

查看代码
 # 1. 声明proxy中的代理数据库名称
schemaName: shopDB_Proxy

#2. 连接mysql
dataSources:
  myDBStr_0:
    url: jdbc:mysql://localhost:3306/shopdb?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
    
#3. 分片规则
rules:
- !SHARDING
  tables:
    # 表1
    test1_tb:
      actualDataNodes: myDBStr_0.test1_tb_${0..1}
      tableStrategy:
        standard:
          shardingColumn: classId
          shardingAlgorithmName: my_MOD
     # 表2
    test2_tb:
      actualDataNodes: myDBStr_0.test2_tb_${0..1}
      tableStrategy:
        standard:
          shardingColumn: classId
          shardingAlgorithmName: my_VOLUME_RANGE
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake  
  #定义分片算法        
  shardingAlgorithms:
    #1. int类型取模算法
    my_MOD:
      type: MOD
      props:
        sharding-count: 2   #代表数据分片到两张表,与上述的actualDataNodes中定义的表个数需要对应
    #2.字符串取模算法(hash取模)
    my_HASH_MOD:
      type: HASH_MOD
      props:
        sharding-count: '2'
    #3.范围算法
    my_BOUNDARY_RANGE:
      type: BOUNDARY_RANGE
      props:
        sharding-ranges: 5    # <5的分在0表中, >=5的分在1表中
    #4.固定容量算法(<2的数据在第1张表中,>=2 且 <2+3 存放在第2张表中)
    my_VOLUME_RANGE:
      type: VOLUME_RANGE
      props:
        range-lower: '2'
        range-upper: '8' 
        sharding-volume: '3'   # 分片的区间的数据的间隔
  #定义key的生成规则
  keyGenerators:
    snowflake:
      type: SNOWFLAKE
      props:
        worker-id: 00000000

(2). 操作

   对test2_tb表执行下面的SQL语句

-- 存在第1张表
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf1', 18, 0, '2021-11-01 00:00:00');
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf1', 18, 1, '2021-11-01 00:00:00');
-- 存在第2张表
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf2', 18, 2, '2021-11-01 00:00:00');
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf3', 18, 3, '2021-11-01 00:00:00');
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf4', 18, 4, '2021-11-01 00:00:00');
-- 插入失败
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf5', 18, 5, '2021-11-01 00:00:00');
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf6', 18, 6, '2021-11-01 00:00:00');

剖析:

  classId等于0,1存在第1张表中,classId等于2,3,4存在第2张表中,classId=5,6的超过分片区间间隔,插入失败。

2.  时间区间分片算法

(1). 配置文件

AUTO_INTERVAL为时间分片算法, 如上小于 2022-01-01 在第1张表中, >=2022-01-01 + 365天,在第2张表中

查看代码
 # 1. 声明proxy中的代理数据库名称
schemaName: shopDB_Proxy

#2. 连接mysql
dataSources:
  myDBStr_0:
    url: jdbc:mysql://localhost:3306/shopdb?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
    
#3. 分片规则
rules:
- !SHARDING
  tables:
    # 表1
    test1_tb:
      actualDataNodes: myDBStr_0.test1_tb_${0..1}
      tableStrategy:
        standard:
          shardingColumn: classId
          shardingAlgorithmName: my_MOD
     # 表2
    test2_tb:
      actualDataNodes: myDBStr_0.test2_tb_${0..1}
      tableStrategy:
        standard:
          shardingColumn: addTime
          shardingAlgorithmName: my_AUTO_INTERVAL
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake  
  #定义分片算法        
  shardingAlgorithms:
    #1. int类型取模算法
    my_MOD:
      type: MOD
      props:
        sharding-count: 2   #代表数据分片到两张表,与上述的actualDataNodes中定义的表个数需要对应
    #2.字符串取模算法(hash取模)
    my_HASH_MOD:
      type: HASH_MOD
      props:
        sharding-count: '2'
    #3.范围算法
    my_BOUNDARY_RANGE:
      type: BOUNDARY_RANGE
      props:
        sharding-ranges: 5    # <5的分在0表中, >=5的分在1表中
    #4.固定容量算法2022-01-01
    my_VOLUME_RANGE:
      type: VOLUME_RANGE
      props:
        range-lower: '2'
        range-upper: '8' 
        sharding-volume: '3'   # 分片的区间的数据的间隔
    #5. 时间分片算法(小于 2022-01-01 在第1张表中, >=2022-01-01 + 365天,在第2张表中)
    my_AUTO_INTERVAL:
      type: AUTO_INTERVAL
      props:
        datetime-lower: '2022-01-01 00:00:00'
        datetime-upper: '2028-01-01 00:00:00'
        # 以1年度为单位进行划分
        sharding-seconds: '31536000'  
        # 以1个月为单位进行划分
        #sharding-seconds: '2678400'   
        # 以1天为单位进行划分
        #sharding-seconds: '86400'
    
  #定义key的生成规则
  keyGenerators:
    snowflake:
      type: SNOWFLAKE
      props:
        worker-id: 00000000

(2). 操作

  向代理库中的test2_tb表中插入下面SQL语句,

   addTime= 2021-11-01、2021-12-01,存在test2_tb0表中,小于: datetime-lower: '2022-01-01 00:00:00'

   addTime=2022-02-01、2022-11-01、2022-12-01,存在test2_tb1表中,大于2022-01-01,小于2022-01-01+365天

   addTime=2023-01-03、2023-02-01,插入失败, 大于2022-01-01+365天

-- 存在第1张表
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf1', 18, 0, '2021-11-01 00:00:00');
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf1', 18, 1, '2021-12-01 00:00:00');
-- 存在第2张表
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf2', 18, 2, '2022-02-01 00:00:00');
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf3', 18, 3, '2022-11-01 00:00:00');
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf4', 18, 4, '2022-12-01 00:00:00');
-- 插入失败
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf5', 18, 5, '2023-01-03 00:00:00');
INSERT INTO `test2_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf6', 18, 6, '2023-02-01 00:00:00');

 

 

二. 分库+分表

1. 单纯分库

(1). 目标

    有两个数据库:shopdb1、shopdb2, 二者都有test3_tb表,现在需要根据addTime字段,利用时间分区算法,在数据库层面进行数据分片。

 (2). 核心配置

查看代码
# 1. 声明proxy中的代理数据库名称
schemaName: shopDB_Proxy

#2. 连接mysql
dataSources:
  myDBStr_0:
    url: jdbc:mysql://localhost:3306/shopdb?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  myDBStr_1:
    url: jdbc:mysql://localhost:3306/shopdb1?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  myDBStr_2:
    url: jdbc:mysql://localhost:3306/shopdb2?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
    
#3. 分片规则
rules:
- !SHARDING
  tables:
    #表1
    test1_tb:
      actualDataNodes: myDBStr_0.test1_tb_${0..1}
      tableStrategy:
        standard:
          shardingColumn: classId
          shardingAlgorithmName: my_MOD
    #表2
    test2_tb:
      actualDataNodes: myDBStr_0.test2_tb_${0..1}
      tableStrategy:
        standard:
          shardingColumn: addTime
          shardingAlgorithmName: my_AUTO_INTERVAL
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake  
    #表3
    test3_tb:
      actualDataNodes: myDBStr_${1..2}.test3_tb
      #分表策略(需要关闭)
      # tableStrategy:
        # standard:
          # shardingColumn: classId
          # shardingAlgorithmName: my_MOD
      #分库策略
      databaseStrategy:
        standard:
          shardingColumn: addTime
          shardingAlgorithmName: my_AUTO_INTERVAL  
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake  
  #定义分片算法        
  shardingAlgorithms:
    #1. int类型取模算法
    my_MOD:
      type: MOD
      props:
        sharding-count: 2   #代表数据分片到两张表,与上述的actualDataNodes中定义的表个数需要对应
    #2.字符串取模算法(hash取模)
    my_HASH_MOD:
      type: HASH_MOD
      props:
        sharding-count: '2'
    #3.范围算法
    my_BOUNDARY_RANGE:
      type: BOUNDARY_RANGE
      props:
        sharding-ranges: 5    # <5的分在0表中, >=5的分在1表中
    #4.固定容量算法2022-01-01
    my_VOLUME_RANGE:
      type: VOLUME_RANGE
      props:
        range-lower: '2'
        range-upper: '8' 
        sharding-volume: '3'   # 分片的区间的数据的间隔
    #5. 时间分片算法(小于 2022-01-01 在第1张表中, >=2022-01-01 + 365天,在第2张表中)
    my_AUTO_INTERVAL:
      type: AUTO_INTERVAL
      props:
        datetime-lower: '2022-01-01 00:00:00'
        datetime-upper: '2028-01-01 00:00:00'
        # 以1年度为单位进行划分
        sharding-seconds: '31536000'  
        # 以1个月为单位进行划分
        #sharding-seconds: '2678400'   
        # 以1天为单位进行划分
        #sharding-seconds: '86400'
    
  #定义key的生成规则
  keyGenerators:
    snowflake:
      type: SNOWFLAKE
      props:
        worker-id: 00000000

(3). 操作

  在3307代理库中向test3_tb表中执行下面sql语句

CREATE TABLE `test3_tb`  (
  `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `userName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `userAge` int(255) NULL DEFAULT NULL,
  `classId` int(11) NULL DEFAULT NULL,
  `addTime` datetime(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

-- truncate table test3_tb
-- 插入失败
INSERT INTO `test3_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf1', 18, 0, '2021-11-01 00:00:00');
INSERT INTO `test3_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf1', 18, 1, '2021-12-01 00:00:00');
-- 存在第shopdb1中的test3_tb表
INSERT INTO `test3_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf2', 18, 2, '2022-02-01 00:00:00');
INSERT INTO `test3_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf3', 18, 3, '2022-11-01 00:00:00');
INSERT INTO `test3_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf4', 18, 4, '2022-12-01 00:00:00');
-- 存在第shopdb2中的test3_tb表
INSERT INTO `test3_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf5', 18, 5, '2023-01-03 00:00:00');
INSERT INTO `test3_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf6', 18, 6, '2023-02-01 00:00:00');

 剖析:

   addTime= 2021-11-01、2021-12-01,插入失败

   addTime= 2022-02-01、2022-11-01、2022-12-01,存在第shopdb1中的test3_tb表 

   addTime=2023-01-03、2023-02-01,存在第shopdb2中的test3_tb表中。

 

2. 分库+分表

(1). 目标

    有两个数据库:shopdb1、shopdb2, 二者都对test4_tb表进行分表,分别包含test4_tb_0、test4_tb_1,

    A. 现在需要根据addTime字段,利用时间分区算法,在数据库层面进行数据分片;

    B. 根据classId字段根据取模算法,进行表层次的数据分片。

 (2). 核心配置

查看代码
# 1. 声明proxy中的代理数据库名称
schemaName: shopDB_Proxy

#2. 连接mysql
dataSources:
  myDBStr_0:
    url: jdbc:mysql://localhost:3306/shopdb?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  myDBStr_1:
    url: jdbc:mysql://localhost:3306/shopdb1?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  myDBStr_2:
    url: jdbc:mysql://localhost:3306/shopdb2?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
    
#3. 分片规则
rules:
- !SHARDING
  tables:
    #表1
    test1_tb:
      actualDataNodes: myDBStr_0.test1_tb_${0..1}
      tableStrategy:
        standard:
          shardingColumn: classId
          shardingAlgorithmName: my_MOD
    #表2
    test2_tb:
      actualDataNodes: myDBStr_0.test2_tb_${0..1}
      tableStrategy:
        standard:
          shardingColumn: addTime
          shardingAlgorithmName: my_AUTO_INTERVAL
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake  
    #表3(单纯分库)
    test3_tb:
      actualDataNodes: myDBStr_${1..2}.test3_tb
      #分表策略(需要关闭)
      # tableStrategy:
        # standard:
          # shardingColumn: classId
          # shardingAlgorithmName: my_MOD
      #分库策略
      databaseStrategy:
        standard:
          shardingColumn: addTime
          shardingAlgorithmName: my_AUTO_INTERVAL  
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake  
    #表4(分库+分表)
    test4_tb:
      actualDataNodes: myDBStr_${1..2}.test4_tb_${0..1}
      #分表策略
      tableStrategy:
        standard:
          shardingColumn: classId
          shardingAlgorithmName: my_MOD
      #分库策略
      databaseStrategy:
        standard:
          shardingColumn: addTime
          shardingAlgorithmName: my_AUTO_INTERVAL  
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake  
  #定义分片算法        
  shardingAlgorithms:
    #1. int类型取模算法
    my_MOD:
      type: MOD
      props:
        sharding-count: 2   #代表数据分片到两张表,与上述的actualDataNodes中定义的表个数需要对应
    #2.字符串取模算法(hash取模)
    my_HASH_MOD:
      type: HASH_MOD
      props:
        sharding-count: '2'
    #3.范围算法
    my_BOUNDARY_RANGE:
      type: BOUNDARY_RANGE
      props:
        sharding-ranges: 5    # <5的分在0表中, >=5的分在1表中
    #4.固定容量算法2022-01-01
    my_VOLUME_RANGE:
      type: VOLUME_RANGE
      props:
        range-lower: '2'
        range-upper: '8' 
        sharding-volume: '3'   # 分片的区间的数据的间隔
    #5. 时间分片算法(小于 2022-01-01 在第1张表中, >=2022-01-01 + 365天,在第2张表中)
    my_AUTO_INTERVAL:
      type: AUTO_INTERVAL
      props:
        datetime-lower: '2022-01-01 00:00:00'
        datetime-upper: '2028-01-01 00:00:00'
        # 以1年度为单位进行划分
        sharding-seconds: '31536000'  
        # 以1个月为单位进行划分
        #sharding-seconds: '2678400'   
        # 以1天为单位进行划分
        #sharding-seconds: '86400'
    
  #定义key的生成规则
  keyGenerators:
    snowflake:
      type: SNOWFLAKE
      props:
        worker-id: 00000000

(3). 操作

  在3307代理库中向test4_tb表中执行下面sql语句

CREATE TABLE `test4_tb`  (
  `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `userName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `userAge` int(255) NULL DEFAULT NULL,
  `classId` int(11) NULL DEFAULT NULL,
  `addTime` datetime(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;


-- truncate table test4_tb
-- 插入失败
INSERT INTO `test4_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf1', 18, 0, '2021-11-01 00:00:00');
INSERT INTO `test4_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf1', 18, 1, '2021-12-01 00:00:00');
-- 在shopdb1中
-- 其中classId=2,4 存在表test4_tb_0中,classId=3 存在表test4_tb_1中 
INSERT INTO `test4_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf2', 18, 2, '2022-02-01 00:00:00');
INSERT INTO `test4_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf3', 18, 3, '2022-11-01 00:00:00');
INSERT INTO `test4_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf4', 18, 4, '2022-12-01 00:00:00');
-- 在shopdb2中
-- 其中classId=6 存在表test4_tb_0中,classId=5 存在表test4_tb_1中 
INSERT INTO `test4_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf5', 18, 5, '2023-01-03 00:00:00');
INSERT INTO `test4_tb`(`userName`, `userAge`, `classId`, `addTime`) VALUES ('ypf6', 18, 6, '2023-02-01 00:00:00');

 剖析:

   addTime= 2021-11-01、2021-12-01,插入失败

   addTime= 2022-02-01、2022-11-01、2022-12-01,存在第shopdb1中, 其中classId=2,4 存在表test4_tb_0中,classId=3 存在表test4_tb_1中 

   addTime=2023-01-03、2023-02-01,存在第shopdb2中,其中classId=6 存在表test4_tb_0中,classId=5 存在表test4_tb_1中 

 

三. 读写分离+分库+分表

1. 前提

   三个MySQL实例,一主两从,3006端口为写库,3008、3009端口为读库。

   对test1_tb表进行分表,数据分片。

2. 核心配置如下

查看代码
# 1. 声明proxy中的代理数据库名称
schemaName: shopDB_Proxy

#2. 连接mysql(一主两从)
dataSources:
  #写连接
  myDBStr_0:
    url: jdbc:mysql://localhost:3306/shopdb?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  #读连接1
  myDBStr_1_read1:
    url: jdbc:mysql://localhost:3308/shopdb?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  #读连接2
  myDBStr_1_read2:
    url: jdbc:mysql://localhost:3309/shopdb?serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
    
#3. 分片规则
rules:
- !READWRITE_SPLITTING
  #读写分离配置
  dataSources:
    pr_ds0:
      writeDataSourceName: myDBStr_0
      readDataSourceNames:
        - myDBStr_1_read1
        - myDBStr_1_read2
      loadBalancerName: My_ROUND_ROBIN
  # 负载均衡算法配置
  loadBalancers:
    My_ROUND_ROBIN: # 负载均衡算法别名
      type: ROUND_ROBIN
- !SHARDING
  tables:
    #表1
    test1_tb:
      actualDataNodes: myDBStr_0.test1_tb_${0..1}
      tableStrategy:
        standard:
          shardingColumn: classId
          shardingAlgorithmName: my_MOD
      keyGenerateStrategy:
        column: id
        keyGeneratorName: snowflake  
  #定义分片算法        
  shardingAlgorithms:
    #1. int类型取模算法
    my_MOD:
      type: MOD
      props:
        sharding-count: 2   #代表数据分片到两张表,与上述的actualDataNodes中定义的表个数需要对应 
  #定义key的生成规则
  keyGenerators:
    snowflake:
      type: SNOWFLAKE
      props:
        worker-id: 00000000

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2022-08-22 11:59  Yaopengfei  阅读(1308)  评论(1编辑  收藏  举报