基于Vue+SpringCloudAlibaba微服务电商项目实战-024:基于shardingjdbc实现分表分库(完结撒花)

1 数据库分表分库规则

今日课程任务

  1. 订单表与会员表如何实现分表分库
  2. 分表分库实现算法有哪些
  3. sharding-jdbc与MyCat实现分表分库的区别
  4. sharding-jdbc实现分表分库的源码分析
  5. 分表分库后,如何实现联合查询
  6. 微服务电商项目如何整合Zipkin实现服务追踪
  7. 微服务服务追踪实现原理与存在缺陷

分表分库:最好是在千万级别数据开始分表分库。

分库概念:根据业务实现分库 订单数据库、会员数据库、支付数据库
会员数据库中分为多个不同的数据库
member_db1—member_table
member_db2—member_table
同样的表不建议在多个数据库中存放,最好在单个数据库中将一个大表拆分成多个子表
member_db.member_table1 member_db.member_table2

2 mycat实现分表分库原理

拆分子表能有效提高查询效率
举例:1000w数据量表查询效率10s,拆分成2个子表查询时间为5s左右

分片算法:

  1. 计算hash(常见) 根据唯一id取模 存在表扩容的问题
  2. 按照时间划分
  3. 按照范围划分

基于mycat实现分片,可以隐藏数据库db真实的联接地址,虚拟一个数据库类似nginx反向代理。分表分库后查询所有数据效率也不会很低,因为采用多线程查询数据。
在这里插入图片描述

3 shadingjdbc实现的原理

Sharding-jdbc实现原理:
本地采用aop拦截jdbc语句,在发送sql之前改写sql语句,效率比mycat要高。
在这里插入图片描述
Sharding-jdbc与mycat区别:

  1. mycat是基于服务器虚拟数据库的方式实现分表分库;
  2. sharding-jdbc基于本地aop拦截改写sql语句

4 项目如何整合shadingjdbc

数据库表

CREATE TABLE `t_order_0` (
  `order_id` bigint(20) NOT NULL,
  `user_id` bigint(20) NOT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
 
CREATE TABLE `t_order_1` (
  `order_id` bigint(20) NOT NULL,
  `user_id` bigint(20) NOT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Maven依赖

<dependencies>
    <dependency>
        <groupId>com.mayikt</groupId>
        <artifactId>mt-shop-service-api-order</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>io.shardingsphere</groupId>
        <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
        <version>3.0.0.M3</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.9</version>
    </dependency>
</dependencies>

bootstrap.yml

###服务启动端口号
server:
  port: 3030

spring:
  cloud:
    nacos:
      discovery:
        ##服务的注册
        server-addr: 127.0.0.1:8848
      config:
        server-addr: 127.0.0.1:8848
  application:
    name:  app-mayikt-order

sharding:
  jdbc:
    ####ds1
    datasource:
      names: ds1
      ds1:
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/meite_order?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
        username: root
    ####  分片配置
    config:
      sharding:
        tables:
          ####t_order
          t_order:
            table-strategy:
              inline:
                #### 根据order_id 进行分片
                sharding-column: order_id
                ####  ds_1.t_order_0 ds_1.t_order_1
                algorithm-expression: t_order_$->{order_id % 2}
              ###分表的总数 0到1   t_order_0 t_order_1
            actual-data-nodes: ds1.t_order_$->{0..1}
        props:
          sql:
            ### 开启分片日志
            show: true

核心代码

public interface OrderService {

    /**
     * 新增order
     *
     * @return
     */
    @GetMapping("/addOrder")
    BaseResponse<String> addOrder();

    /**
     * 根据订单号码查询
     *
     * @param orderId
     * @return
     */
    @GetMapping("/findByOrderId")
    BaseResponse<OrderRspDto> findByOrderId(Long orderId);

    /**
     * 查询所有的订单
     *
     * @return
     */
    @GetMapping("/listOrderId")
    List<String> listOrderId();
}
@RestController
public class OrderServiceImpl extends BaseApiService implements OrderService {
    @Autowired
    private OrderMapper orderMapper;

    @Override
    public BaseResponse<String> addOrder() {
        for (int i = 0; i < 100; i++) {
            Long userId = 1L;
            orderMapper.addOrder(i + "", userId);
        }
        return setResultSuccess();
    }

    @Override
    public  BaseResponse<OrderRspDto> findByOrderId(Long orderId) {
        OrderEntity orderEntity = orderMapper.findByOrderId(orderId);
        OrderRspDto orderRspDto = dtoToDo(orderEntity,OrderRspDto.class);
        return setResultSuccess(orderRspDto);
    }

    @Override
    public List<String> listOrderId() {
        return orderMapper.findListOrders();
    }
}
public interface OrderMapper {

    @Insert("INSERT INTO `t_order` VALUES (${orderId},#{userId});")
    int addOrder(String orderId, Long userId);


    @Select("SELECT order_id as orderId  FROM t_order limit  0,5; ")
    List<String> findListOrders();

    @Select("SELECT order_id as orderId,user_id as userId  FROM t_order  where order_id=#{orderId} ")
    OrderEntity findByOrderId(@Param("orderId") Long orderId);
}

测试效果:
在这里插入图片描述

5 微服务如何实现服务追踪

生成环境中,遇到问题是怎么解决的

  1. 查询日志(服务器上直接看)
  2. Elk+kafka+aop异步采集日志
  3. 搭建微信公众号报警系统 微信公众号模板推送
  4. 构建服务追踪系统

以上234种方案选一种即可,没必要全部都搭建一遍。
微服务中依赖关系比较大,定位问题找到错误原因非常复杂,可以搭建服务追踪系统解决。

6 微服务服务追踪实现原理分析

ZipkinServer环境搭建
在 Spring Boot 2.0 版本之后,官方已不推荐自己搭建定制了,而是直接提供了编译好的 jar 包。详情可以查看官网:https://zipkin.io/pages/quickstart.html
注意:zipkin官网已经提供定制了,使用官方jar运行即可。
默认端口号启动zipkin服务
java –jar zipkin.jar 默认端口号; 9411
http://127.0.0.1:9411
指定端口号启动9411
java -jar zipkin.jar --server.port=8080

ZipkinClient集成
Maven依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

application.yml

spring:
  application:
    name: app-itmayiedu-member
  zipkin: 
    base-url: http://127.0.0.1:9411/
  ###全部采集  
  sleuth:
    sampler:
      probability: 1.0

Sleuth简单的介绍
Sleuth 每一次RPC远程调用请求都会生成一个spanid记录每一次rpc请求的信息,还有一个traceid 全局唯一id;

实现原理:

  1. 开始方调用接口的时候会生成一个全局的id ,放入到请求中
  2. 每次调用rpc接口的时候会产生一个新的spanid,放入到请求中

在这里插入图片描述
Sleuth可以结合Zipkin可以实现界面化的形式管理我们接口依赖信息。

效果测试:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值