zoukankan      html  css  js  c++  java
  • 分库分表之-sharding-jdbc 中间件使用

    一、分库分表的方式

    1、垂直分表:

    将一个表拆分为多个表,按照字段使用频率,热度进行拆分,拆分后的表仍然在同一个库中

    带来的提升:

    • 减少IO争抢导致锁表的几率,查询看商品详情与商品信息浏览互不影响。

    • 提供热门数据操作效率

    拆分原则:

    • 把访问频率比较低字段单独放一张表中

    • 把txt,blob等大字段拆分出来放到附表中;

    • 把组合查询的列都放到一张表中;

    垂直分库

    把同一个库中的表拆分放到不同的数据库【不同服务器上面的数据库】

    带来提升:

    • 业务层面降低了耦合

    • 不同业务数据可以很方便的进行分类管理,维护,扩展。

    • 高并发场景下,一定程度的提升了IO,降低了单机资源瓶颈,并且减少了数据库连接数

    拆分原则

    • 根据业务层面对表进行分类

    • 数据是允许部署在不同的服务器上。

    水平分库

    水平分库,把同一个表的数据按照一定路由规则拆分到不同数据库库中,每一个库都可以放在不同服务器上。

    提升性能:

    • 解决了单库数量量大,高并发性能瓶颈

    • 提高了系统稳定性,可用性

    拆分原则:

    • 切分后数据行数巨大,存在单库读写,存储性能瓶颈

    水平分表

    将一个表通过一定的路由规则拆分到相同表结构的不同表中存储,水平分表是在同一个库中拆分

    性能提升:

    • 提高数据库查询性能

    • 减少IO和锁表几率

    拆分原则

    • 单表数据量过大

    二、ShardingSphere简介

    定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

    • 适用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
    • 基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
    • 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer和PostgreSQL。

    2、sharding-jdbc核心概念

    • 逻辑表(LogicTable):进行水平拆分的时候同一类型(逻辑、数据结构相同)的表的总称。例:订单数据根据主键尾数拆分为10张表,分别是t_order_0t_order_9,他们的逻辑表名为t_order
    • 真实表(ActualTable):在分片的数据库中真实存在的物理表。即上个示例中的t_order_0t_order_9
    • 数据节点(DataNode):数据分片的最小单元。由数据源名称和数据表组成,例:ds_0.t_order_0
    • 动态表(DynamicTable):逻辑表和物理表不一定需要在配置规则中静态配置。如,按照日期分片的场景,物理表的名称随着时间的推移会产生变化。
    • 绑定表(BindingTable):指分片规则一致的主表和子表。例如:t_order表和t_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升
    SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

    水平分表为例:

    注:下面用到的sharding-jdbc名词解释

    • 分片键(ShardingColumn):分片字段用于将数据库(表)水平拆分的字段,支持单字段及多字段分片。例如上例中的order_id。
    • 分片算法(ShardingAlgorithm):进行水平拆分时采用的算法,分片算法需要应用方开发者自行实现,可实现的灵活度非常高。目前提供4种分片算法。由于分片算法和业务实现紧密相关,因此并未提供内置分片算法,而是通过分片策略将各种场景提炼出来,提供更高层级的抽象,并提供接口让应用开发者自行实现分片算法。

    项目为springboot 。

    application.properties

    #server.port=43210
    #spring.application.name = sharding-jdbc-quickstart-demo
    #server.servlet.context-path = /sharding-jdbc-quickstart-demo
    spring.http.encoding.enabled = true
    spring.http.encoding.charset = UTF-8
    spring.http.encoding.force = true
    mybatis.configuration.map-underscore-to-camel-case = true
    #spring.profiles.active=masterslave
    
    # 自定义数据源
    spring.shardingsphere.datasource.names = m1
    spring.shardingsphere.datasource.m1.type = com.alibaba.druid.pool.DruidDataSource
    spring.shardingsphere.datasource.m1.driver-class-name = com.mysql.jdbc.Driver
    spring.shardingsphere.datasource.m1.url = jdbc:mysql://localhost:3306/order_db?useUnicode=true&useSSL=false
    spring.shardingsphere.datasource.m1.username = root
    spring.shardingsphere.datasource.m1.password = 123456
    
    # 以下是分片规则配置
    # 指定t_order表的数据分布情况,配置数据节点
    # t_order 逻辑表名
    # insert into t_order () values ()
    # $->{1..2} => 1, 2 => t_order_1,t_order_2
    spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m1.t_order_$->{1..2}
    
    # 指定t_order表的主键生成策略为SNOWFLAKE
    spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
    spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
    
    # 指定t_order表的分片策略,分片策略包括分片键和分片算法
    spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column = order_id
    spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression = t_order_$->{order_id % 2 + 1}
    
    # 打开sql输出日志
    spring.shardingsphere.props.sql.show = true
    logging.level.root = info
    logging.level.org.springframework.web=info
    logging.level.druid.sql=debug
    logging.level.com.itheima.dbsharding=debug
    OrderMapper
    @Component
    @Mapper
    public interface OrderMapper {
        /**
         * 新增订单
         * @param price
         * @param userId
         * @param status
         * @return
         */
        @Insert("insert into t_order(price,user_id,status)values(#{price},#{userId},#{status})")
        int insertOrderInfo(@Param("price") BigDecimal price, @Param("userId")Long userId, @Param("status")String status);
    }
    ShardingJdbcTests 测试方法
       @Autowired
        public OrderMapper orderMapper;
    
        @Test
        public void testInsertOrder(){
            for (int i = 0 ; i<10; i++){
                orderMapper.insertOrderInfo(new BigDecimal((i+1)*4),1L,"Success");
            }
        }
     
  • 相关阅读:
    什么是 bean 的自动装配?
    什么是 Spring 的内部 bean?
    什么是 Spring 的 MVC 框架?
    Spring AOP and AspectJ AOP 有什么区别?
    解释 JDBC 抽象和 DAO 模块?
    volatile 类型变量提供什么保证?
    一个 Spring Bean 定义 包含什么?
    什么是 Spring MVC 框架的控制器?
    使用 Spring 访问 Hibernate 的方法有哪些?
    什么是 Callable 和 Future?
  • 原文地址:https://www.cnblogs.com/alomsc/p/13392431.html
Copyright © 2011-2022 走看看