精华内容
下载资源
问答
  • sharding源码
    千次阅读
    2022-02-04 11:49:35

    使用sharding时,有些语句可能被分发到多个数据库节点执行,之后将这些结果汇总加工返回到客户端。归并引擎的作用便是完成对结果的汇总加工,也叫作结果归并。
    sharding结果归并从功能上分为遍历、排序、分组、分页和聚合5种类型,从结构划分可分为流式归并、内存归并和装饰者归并,流式归并和内存归并是互斥的,装饰者归并可以在流式归并和内存归并之上做进一步的处理。

    流式归并是指每一次从结果集中获取到的数据,都能够通过逐条获取的方式返回正确的单条数据,它与数据库原生的返回结果集的方式最为契合。遍历、排序以及流式分组都属于流式归并的一种。
    内存归并则是需要将结果集的所有数据都遍历并存储在内存中,再通过统一的分组、排序以及聚合等计算之后,再将其封装成为逐条访问的数据结果集返回。
    装饰者归并是对所有的结果集归并进行统一的功能增强,目前装饰者归并有分页归并和聚合归并这2种类型。

    本文接下来介绍select语句的结果归并,对于其他语句不再本文介绍范围内。

    1、归并引擎

    归并引擎根据select语句特点,查找合适的归并处理策略,将数据库执行结果封装到MergedResult对象中。sharding对MergedResult使用ShardingResultSet封装,ShardingResultSet实现了ResultSet,应用程序获得便是ShardingResultSet对象,ShardingResultSet将对其方法的调用都委托给了MergedResult。所以应用程序中调用ShardingResultSet,其实就是调用MergedResult。
    从上面的介绍中,可以看到MergedResult的作用:持有多个数据库的结果集对象(ResultSet),当应用程序获取数据库结果时,可以在多个结果集之间自动切换,使得应用程序就像使用一个结果集对象而不是多个。
    sharding提供了12个功能各不相同的MergedResult实现类,归并引擎的作用便是查找合适的MergedResult实现类,并创建MergedResult对象,将该对象返回给上层调用。
    sharding提供了两种归并引擎实现类:ShardingResultMergerEngine和EncryptResultDecoratorEngine,后者在加密场景中使用,一般情况下使用的是ShardingResultMergerEngine。

    2、MergedResult

    先来看一下MergedResult接口:

    public interface MergedResult {
        
        /**
         * Iterate next data.
         */
        boolean next() throws SQLException;
        
        /**
         * Get data value.
         *
         * @param columnIndex column index
         * @param type class type of data value
         * @return data value
         */
        Object getValue(int columnIndex, Class<?> type) throws SQLException;
        
        /**
         * Get calendar value.
         *
         * @param columnIndex column index
         * @param type class type of data value
         * @param calendar calendar
         * @return calendar value
         */
        Object getCalendarValue(int columnIndex, Class<?> type, Calendar calendar) throws SQLException;
        
        /**
         * Get InputStream.
         *
         * @param columnIndex column index
         * @param type class type of data value
         */
        InputStream getInputStream(int columnIndex, String type) throws SQLException;
        
        /**
         * Judge ResultSet is null or not.
         * 
         * @return ResultSet is null or not
         */
        boolean wasNull() throws SQLException;
    }
    

    MergedResult提供了next方法和getValue方法,next方法用于判断是否已经完成对结果集的遍历,getValue方法可以获得数据库的执行结果。
    MergedResult将结果集封装,调用方调用next方法和getValue方法便可以完成对所有结果的遍历,大大简化了调用方的操作。
    sharding提供了12种MergedResult实现类:

    实现类作用
    LimitDecoratorMergedResultmysql使用,用于分页查询
    IteratorStreamMergedResult对结果集执行简单遍历
    GroupByStreamMergedResult用于分组查询
    OrderByStreamMergedResult排序
    GroupByMemoryMergedResult分组,与上面分组不同的是,该类需要在内存中完成分组
    SingleLocalDataMergedResultDAL语句使用,DAL表示数据库管理类的语句,比如show create table语句
    MultipleLocalDataMergedResult暂没有使用场景
    LogicTablesMergedResultDAL语句使用
    ShowCreateTableMergedResultDAL语句使用
    TransparentMergedResult用于update/insert/delete等语句
    TopAndRowNumberDecoratorMergedResultSQL Server使用,用于分页查询
    RowNumberDecoratorMergedResultOracle使用,用于分页查询

    下面对部分MergedResult实现类详细介绍。

    2.1、IteratorStreamMergedResult

    该实现类是遍历归并,是最简单的归并方式。sharding将多个结果集对象组织成一个链表,顺次遍历链表中的每个结果集。下面看一下它的源码。

    	//入参queryResults是结果集对象组成的链表
        public IteratorStreamMergedResult(final List<QueryResult> queryResults) {
            this.queryResults = queryResults.iterator();
            setCurrentQueryResult(this.queryResults.next());
        }
        //next方法遍历完当前的结果集对象,便切换到链表中下一个结果集对象
        @Override
        public boolean next() throws SQLException {
            if (getCurrentQueryResult().next()) {
                return true;
            }
            if (!queryResults.hasNext()) {
                return false;
            }
            //设置当前正在访问的结果集对象
            setCurrentQueryResult(queryResults.next());
            boolean hasNext = getCurrentQueryResult().next();
            if (hasNext) {
                return true;
            }
            while (!hasNext && queryResults.hasNext()) {
                setCurrentQueryResult(queryResults.next());
                hasNext = getCurrentQueryResult().next();
            }
            return hasNext;
        }
    

    2.2、OrderByStreamMergedResult

    当SQL语句中有order by子句,且需要归并多个数据库节点返回的结果集时,sharding使用该类处理结果集。
    因为每个数据库节点执行的SQL都有order by子句,都是已经排序过的数据,那么将每个结果集的当前数据值进行比较(通过实现Java的Comparable接口完成),并将其放入优先级队列。 每次获取下一条数据时,只需将队列顶端结果集的游标下移,并根据新游标重新进入优先级排序队列找到自己的位置即可。
    该类使用的是流式归并的方式,每次next仅获取唯一正确的一条数据,极大的节省了内存的消耗。
    下面我们看一下源码:

    	//queryResults:多个结果集对象组成的链表
        public OrderByStreamMergedResult(final List<QueryResult> queryResults, final SelectStatementContext selectStatementContext, final SchemaMetaData schemaMetaData) throws SQLException {
        	//获得排序字段,也就是order by子句里面的字段名
            this.orderByItems = selectStatementContext.getOrderByContext().getItems();
            //orderByValuesQueue就是上文提到的优先级队列,结果集放入该队列中
            this.orderByValuesQueue = new PriorityQueue<>(queryResults.size());
            orderResultSetsToQueue(queryResults, selectStatementContext, schemaMetaData);
            isFirstNext = true;
        }
        
        private void orderResultSetsToQueue(final List<QueryResult> queryResults, final SelectStatementContext selectStatementContext, final SchemaMetaData schemaMetaData) throws SQLException {
        	//获得各个结果集对象的第一个结果,并将它们放入到优先级队列中
            for (QueryResult each : queryResults) {
                OrderByValue orderByValue = new OrderByValue(each, orderByItems, selectStatementContext, schemaMetaData);
                if (orderByValue.next()) {
                    orderByValuesQueue.offer(orderByValue);
                }
            }
            setCurrentQueryResult(orderByValuesQueue.isEmpty() ? queryResults.get(0) : orderByValuesQueue.peek().getQueryResult());
        }
        
        @Override
        public boolean next() throws SQLException {
            if (orderByValuesQueue.isEmpty()) {
                return false;
            }
            if (isFirstNext) {
                isFirstNext = false;
                return true;
            }
            OrderByValue firstOrderByValue = orderByValuesQueue.poll();
            if (firstOrderByValue.next()) {
                orderByValuesQueue.offer(firstOrderByValue);
            }
            if (orderByValuesQueue.isEmpty()) {
                return false;
            }
            setCurrentQueryResult(orderByValuesQueue.peek().getQueryResult());
            return true;
        }
    

    优先级队列里面的排序方式是:

        public int compareTo(final OrderByValue o) {
            int i = 0;
            //遍历各个排序字段
            for (OrderByItem each : orderByItems) {
            	//调用java的Comparable接口完成排序,也对排序方向进行了判断
                int result = CompareUtil.compareTo(orderValues.get(i), o.orderValues.get(i), each.getSegment().getOrderDirection(),
                    each.getSegment().getNullOrderDirection(), orderValuesCaseSensitive.get(i));
                if (0 != result) {
                    return result;
                }
                i++;
            }
            return 0;
        }
    

    2.3、GroupByStreamMergedResult

    处理group by子句,sharding提供了两种处理方式,一种是流式处理,一种是内存中再分组加工处理。两者的区别是,如果order by子句的字段与group by子句的字段一样,则使用流水处理,如果不一样,则使用内存再加工处理。本小节先介绍流式处理,下一小节介绍内存处理方式。
    GroupByStreamMergedResult是OrderByStreamMergedResult的子类,因此GroupByStreamMergedResult使用优先级队列对每个结果集排序。每次调用next方法时,从优先级队列里面获取下一个结果作为当前结果,然后再从优先级队列里面获得下一个结果,将该结果与第一个结果比较,如果相同,则两个结果合并然后遍历下一个,如果不同,则next方法返回。
    GroupByStreamMergedResult对结果合并时,也会对sum、max、min等聚合方法进行处理。

    2.4、GroupByMemoryMergedResult

    因为排序字段与分组字段不同,无法使用流式方式处理结果集。GroupByMemoryMergedResult的处理方式是遍历每条数据库执行结果记录,将它们放入到一个HashMap对象中,该HashMap对象的key是group by字段的值,value是对应的数据库执行结果记录,不过如果有多个记录具有相同的group by字段值,则value是一个聚合后的记录。
    遍历完所有的结果后,将HashMap的value转换为一个List对象,然后对List按照order by子句进行排序。这样每次调用next方法获得下一个记录时,就从List中返回。

    2.5、LimitDecoratorMergedResult

    LimitDecoratorMergedResult是一个装饰器,它会对其他的MergedResult对象进行装饰。

    	//mergedResult是被装饰的MergedResult对象
    	//pagination用于表示分页,记录了分页数据
        public LimitDecoratorMergedResult(final MergedResult mergedResult, final PaginationContext pagination) throws SQLException {
            super(mergedResult);
            this.pagination = pagination;
            skipAll = skipOffset();
        }
        //skipOffset方法调用mergedResult的next方法,跳过指定的分页记录
        private boolean skipOffset() throws SQLException {
            for (int i = 0; i < pagination.getActualOffset(); i++) {
                if (!getMergedResult().next()) {
                    return true;
                }
            }
            rowNumber = 0;
            return false;
        }
        
        @Override
        public boolean next() throws SQLException {
            if (skipAll) {
                return false;
            }
            if (!pagination.getActualRowCount().isPresent()) {
                return getMergedResult().next();
            }
            return ++rowNumber <= pagination.getActualRowCount().get() && getMergedResult().next();
        }
    

    3、引用

    https://shardingsphere.apache.org/document/legacy/4.x/document/cn/features/sharding/principle/merge/

    更多相关内容
  • sharding源码包结构寻找线索2)shrding-jdbc-core 提供的对于jdbc规范的重写3)sql路由3)sql路由3)sql路由3)sql路由2.debug关键节点验证执行流程 本文主旨 本文尝试,以自上而下的方式,从整体脉络、从大方向上...

    一、本文主旨

    本系列源于对sharding多表路由情况下,性能问题的跟踪、解析,借这次机会,进行一次sharding源码的全面学习和总结。
    本篇尝试总结从0到1探索源码的过程,从主体脉络上理清sharding执行流程。

    二、一条sql 引起的反思

      @Override
      <select id="list" resultMap="baseResultMap">
         SELECT * FROM user where id in (397768528364568576, 397768518222741505, 397768536589598720)
      </select>
    

    当我们使用sharding-jdbc、执行这样一条sql时,user称为虚拟表名,并不真实存在。那么,sharding执行时,内部具体都做了哪些事情呢?

    //分表配置
    spring.shardingsphere.sharding.tables.user.actual-data-nodes=ds$->{0..1}.user_$->{0..2}
    spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
    spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id % 3}
    spring.shardingsphere.sharding.tables.user.key-generator.column=id
    spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE
    
    //分库配置
    spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=id
    spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{id % 2}
    spring.shardingsphere.props.sql.show=true
    

    我的实际配置如上:2个库,3张表

    三、 寻找Sharding-JDBC 主脉络

    1.从sharding源码包结构寻找线索

    核心原则:抓主放次,抓大放小
    本篇目的:理清sharding主脉络,掌握主要执行过程。

    浏览源码包后,对几个主要模块功能定位有了解、筛选出了关键入口类。便于进一步代码跟踪验证。

    1)shrding-jdbc-core 对jdbc重写

    sharding-jdbc基于适配器模式、实现了jdbc规范,我们可以简单认为,它是一种支持分片的数据库驱动(类似,事实并不是)。

    ShardingPreparedStatement#execute
    

    2)sharding-core-parse 对sql解析

    sql 解析过程分为词法解析和语法解析。

    SQLParsingEngine#parse
    

    3)sharding-core-rewrite 对sql重写

    面向逻辑库与逻辑表书写的SQL,不能够直接在真实的数据库执行,SQL改写用于将逻辑SQL改写为在真实数据库中可以正确执行的SQL。

    SQLRewriteEngine#rewrite
    

    4)sharding-core-route 对sql路由

    根据上下文匹配数据库和表的分片策略,生成路由路径。 对于携带分片键的SQL,根据分片键进行分片路由,不携带分片键的SQL则采用广播路由。

    ShardingRouterFactory#newInstance
    

    5)sharding-core-optimize 对sql优化

    优化包只是根据上下文和参数对sharding数据模型做了处理,便于后续处理。

    OptimizeEngineFactory#newInstance //只是对内部数据模型的优化,不重点关注
    

    6)sharding-core-execute 执行sql

    负责将路由和改写完成之后的真实SQL发送到底层数据源执行

    SQLExecuteCallback#execute
    

    7)sharding-core-merge 结果归并

    将从各个数据节点获取的多个结果集,组合为一个返回给请求客户端。

    MergeEngineFactory#newInstance
    

    2.debug关键节点验证执行流

    对之前选出来的各个子模块的入口类,断点调试,验证执行流程。

    1)ShardingRouterFactory

    在这里插入图片描述
    很显然,我们没有指定强制路由,因次走new ParsingSQLRouter逻辑。
    我们在ParsingSQLRouter#parse和ParsingSQLRouter#route方法打上断点、大胆放行。

    2)ShardingPreparedStatement#execute

    在这里插入图片描述
    看到这个很高兴、这是sharding对JDBC规范的实现,是我们的老朋友。

     @Override
        public boolean execute() throws SQLException {
            try {
                clearPrevious();
                //执行sql路由
                shard(); 
                initPreparedStatementExecutor();
                //调用preparedStatementExecutor执行sql
                return preparedStatementExecutor.execute();
            } finally {
                clearBatch();
            }
        }
    

    见面知意,我们发现其中有两个处理:shard(), preparedStatementExecutor.execute();
    我们不妨点进去看下:

    private void shard() {
          routeResult = shardingEngine.shard(sql, getParameters());
    }
    

    继续跟进 shardingEngine.shard(sql, getParameters());

     /**
       * Shard.
       *
       * @param sql SQL
       * @param parameters parameters of SQL
       * @return SQL route result
       */
      public SQLRouteResult shard(final String sql, final List<Object> parameters) {
          List<Object> clonedParameters = cloneParameters(parameters);
          //执行路由、获取sqlRouteResult
          SQLRouteResult result = route(sql, clonedParameters);
          //对路由结果进行转换和重写
          result.getRouteUnits().addAll(HintManager.isDatabaseShardingOnly() ? convert(sql, clonedParameters, result) : rewriteAndConvert(sql, clonedParameters, result));
          if (shardingProperties.getValue(ShardingPropertiesConstant.SQL_SHOW)) {
              boolean showSimple = shardingProperties.getValue(ShardingPropertiesConstant.SQL_SIMPLE);
              SQLLogger.logSQL(sql, showSimple, result.getSqlStatement(), result.getRouteUnits());
          }
          return result;
      }
    

    了解到这里,我们不再继续看其中细节,回到我们的主线。通用粗略的看一眼preparedStatementExecutor.execute();

    /**
       * Execute SQL.
       *
       * @return return true if is DQL, false if is DML
       * @throws SQLException SQL exception
       */
      public boolean execute() throws SQLException {
          boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
          //这里跟我浏览源码圈的重点不谋而合了
          SQLExecuteCallback<Boolean> executeCallback = SQLExecuteCallbackFactory.getPreparedSQLExecuteCallback(getDatabaseType(), isExceptionThrown);
          //通过executeCallback 执行sql
          List<Boolean> result = executeCallback(executeCallback);
          if (null == result || result.isEmpty() || null == result.get(0)) {
              return false;
          }
          return result.get(0);
      }
    

    其中用到了SQLExecuteCallbac执行sql,sql路由等等,和之前浏览源码圈定的重点不谋而合。略欣慰,不用高兴太早,继续放行看下一个断点。

    3)ParsingSQLRouter#parse sql路由

    在这里插入图片描述
    返回了SelectStatement类型的 SQLStatement,这目前与我们主线无关,不去关心直接放行。

    4)ParsingSQLRouter#route

    @Override
    public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) {
       Optional<GeneratedKey> generatedKey = sqlStatement instanceof InsertStatement
               ? GeneratedKey.getGenerateKey(shardingRule, parameters, (InsertStatement) sqlStatement) : Optional.<GeneratedKey>absent();
       //sql路由
       SQLRouteResult result = new SQLRouteResult(sqlStatement, generatedKey.orNull());
       //调用了sql优化,不是这部分优化是针对便于sharding的数据模型处理,无关主线,细节忽略。
       OptimizeResult optimizeResult = OptimizeEngineFactory.newInstance(shardingRule, sqlStatement, parameters, generatedKey.orNull()).optimize();
       if (generatedKey.isPresent()) {
           setGeneratedKeys(result, generatedKey.get());
       }
       boolean needMerge = false;
       if (sqlStatement instanceof SelectStatement) {
           needMerge = isNeedMergeShardingValues((SelectStatement) sqlStatement);
       }
       if (needMerge) {
           checkSubqueryShardingValues(sqlStatement, optimizeResult.getShardingConditions());
           mergeShardingValues(optimizeResult.getShardingConditions());
       }
       //数据路由,觉得我们这条数据到哪些节点执行
       RoutingResult routingResult = RoutingEngineFactory.newInstance(shardingRule, shardingMetaData.getDataSource(), sqlStatement, optimizeResult).route();
       if (sqlStatement instanceof SelectStatement && null != ((SelectStatement) sqlStatement).getLimit() && !routingResult.isSingleRouting()) {
           result.setLimit(getProcessedLimit(parameters, (SelectStatement) sqlStatement));
       }
       if (needMerge) {
           Preconditions.checkState(1 == routingResult.getTableUnits().getTableUnits().size(), "Must have one sharding with subquery.");
       }
       result.setRoutingResult(routingResult);
       result.setOptimizeResult(optimizeResult);
       return result;
    }
    

    最终返回路由结果如下:
    在这里插入图片描述
    此处已经获取到了这条sql所有最小单元。放行(其实这里是存在性能问题的,后续系列再讲)

    5)SQLRewriteEngine#rewrite Sql改写

    在这里插入图片描述
    对sql参数,SqlToken做了处理,主要是数据结构上的,不去关心、继续放行。

    6)SQLExecuteCallback#execute 执行sql

    在这里插入图片描述
    迭代statementExecuteUnits,循环调用execute0执行每个sql(即之前看到的 routingResult)。

    7)MergeEngineFactory 结果归并

    在这里插入图片描述
    最终:DefaultResultSetHandler#collapseSingleResultList得到期望数据,继续返回。
    在这里插入图片描述

    四、本篇总结

    Shardng-Jdbc实现是基于JDBC规范实现的,因此遵循我们所熟悉的开发流程的: 获取数据库链接-》创建statement -> 执行sql语句 -> 处理结果集 -> 释放资源等等。

    不同的是,sharding内部进行了一系列封装和处理:
    1、封装用户配置的多个数据源统一为一个ShardingDataSource。
    2、封装了分库分表策略供用户配置使用。
    3、内部执行的sql解析、路由、改写、执行、归并都是在JDBC主脉络下的一种实现。

    封装后的sharding 对用户的功能表现,非常类似于数据库驱动。

    本篇并未涉及过多细节、后续具体分析

    五、欢迎评论、指正。

    独学而无友,则孤陋而寡闻 。
    个人理解,如有偏颇,欢迎评论、讨论、指正。
    
    展开全文
  • 其实,我自己写了一个increament-jdbc组件的,当我读了sharding-jdbc的源码之后,发现思路和原理差不多,sharding这个各方面要比我的强,毕竟我是一天之内赶出来的东东。 示例代码地址: demo没有写日志,也没有各种...
  • sharding-jdbc之——分库分表实例完整源码,详情请参见博文:http://blog.csdn.net/l1028386804/article/details/79368021
  • shardingjdbc源码解析

    2021-08-24 10:21:58
    org.apache.shardingsphere.shardingjdbc.jdbc.core.statement.ShardingPreparedStatement#execute org.apache.shardingsphere.core.BaseShardingEngine#shard 3. org.apache.shardingsphere.core....

    入口分析:

    1. org.apache.shardingsphere.shardingjdbc.jdbc.core.statement.ShardingPreparedStatement#execute
      这里是分库分表的切入口
      在这里插入图片描述

    2. org.apache.shardingsphere.core.BaseShardingEngine#shard

    在这里插入图片描述
    3. org.apache.shardingsphere.core.PreparedQueryShardingEngine#route
    4. org.apache.shardingsphere.core.route.PreparedStatementRoutingEngine#route
    这里开始对逻辑sql进行解析
    在这里插入图片描述

    4.1. org.apache.shardingsphere.core.route.router.sharding.ParsingSQLRouter#parse
    在这里插入图片描述

    4.2 org.apache.shardingsphere.core.parse.SQLParsingEngine#parse

    • 首先判断缓存中是否存在解析结果
    • 解析逻辑sql到SQLStatement
      在这里插入图片描述
    1. org.apache.shardingsphere.core.route.router.sharding.ParsingSQLRouter#route
      在这里插入图片描述
      6.1 org.apache.shardingsphere.core.route.type.standard.StandardRoutingEngine#route()
      6.2 org.apache.shardingsphere.core.route.type.standard.StandardRoutingEngine#getDataNodes
      6.3 org.apache.shardingsphere.core.route.type.standard.StandardRoutingEngine#routeByShardingConditions
      6.4 org.apache.shardingsphere.core.route.type.standard.StandardRoutingEngine#routeByShardingConditionsWithCondition
      6.5 org.apache.shardingsphere.core.route.type.standard.StandardRoutingEngine#routeTables
      这里会根据是否含有分片键来判断是直接查询所有表还是根据分片键查询对应的实际表。
      在这里插入图片描述
      6.6 org.apache.shardingsphere.core.strategy.route.standard.StandardShardingStrategy#doSharding

    这里最终会进入到你定义的分表规则,去获取到最终真实要查询的表名称
    6.7 com.cxytiandi.sharding.algorithm.MyPreciseShardingAlgorithm#doSharding
    在这里插入图片描述
    7. org.apache.shardingsphere.core.BaseShardingEngine#rewriteAndConvert
    重写sql语句
    在这里插入图片描述
    7.1 org.apache.shardingsphere.core.rewrite.SQLRewriteEngine#rewrite
    在这里将表名进行改写:
    insert int user(id,name) values(1, ‘xly’);
    改写为
    insert into user_1(id,name) values(1, ‘xly’);

    在这里插入图片描述
    到这里就结束了源码的解析。

    展开全文
  • 昨天发出的上篇配置解析的文章,没有介绍sharding-jdbc提供的分片的api和与spring集成的配置文件,可能直接看配置源码解析不太直观,今天把这两块补上,这个也是收到了芋头小钝的建议,感谢芋头小钝。   ...

    说在前面

    本文转自“天河聊技术”微信公众号

     

    昨天发出的上篇配置解析的文章,没有介绍sharding-jdbc提供的分片的api和与spring集成的配置文件,可能直接看配置源码解析不太直观,今天把这两块补上,这个也是收到了芋头小钝的建议,感谢芋头小钝。

     

    sharding的分片api介绍

    sharding-jdbc提供的分片有两种方式,一种就是inline表达式,底层是groovy通过解析你配置的闭包实现的,一种是指定分片策略的实现类,分片算法支持三种,=、in、between。

     

    inline分片方式

    sharding-jdbc集成spring的配置文件中这样配置

    18141434_sWwp.jpg

    上图中的配置是指定了一种表的分片策略,这种表的逻辑表名是demo,可以看到demo_${create_time.toString(&quot;yyyyMM&quot;)}这里是用demo_作为物理表的前缀和具体的后缀拼接起来就成了具体的物理表,toString() 方法就是sharding-jdbc的提供的inline表达式支持的其中一个闭包,${create_time.toString(&quot;yyyyMM&quot;)}这个部分就是inline表达式,这个inline表达式的意思就是把分片字段值按照这个时间格式格式化成字符串拼接到demo_的后面,sharding-columns="create_time"这里制定了按照分片字段,整体解释下,逻辑表是demo,create_time分片字段值是“20170801 00:00:00“,这里的时间是Date类型,那么具体路由到的表就是demo_201708 这张物理表,一句话概括就是demo这张表是按月分表的。

     

    inline分片表达式内部实现

     

    18141435_Avj1.jpg

    具体实现是上图标注的几个类,还有InlineParser inline表达式解析器类,底层是通过groovy解析闭包的方式进行实现的,值得介绍的是下面的这个类

    com.dangdang.ddframe.rdb.sharding.config.common.internal.algorithm.ShardingValueWrapper 这个类是sharding-jdbc默认提供的哪些inline表达式,如果需要可以对其进行扩展。

     

    普通的分片实现方式

     

    分片策略接口和默认实现整体类图

    18141435_Q4OU.jpg

     

    ShardingAlgorithm 顶层分片策略接口

    TableShardingAlgorithm 表分片策略接口

    MultipleKeysShardingAlgorithm 多个key分片策略接口,这个接口只有一个分片抽象方法,doSharding() 方法

    DatabaseShardingAlgorithm 数据库分片策略接口

    SingleKeyShardingAlgorithm 单个key分片策略接口,支持三种运算符的分片策略,如下图

    18141435_yS6k.jpg

    这种分片策略也是用的最多的,我们的项目美利财务平台中分片策略也是用的这种分片策略。

    NoneKeyShardingAlgorithm 无分片值策略接口,数据量小的表不考虑分片就会走这个分片策略。

    18141435_RFle.jpg

    上图中这一层接口是第二层接口的组合实现,开发中只需要实现这层接口实现自己具体的分片策略即可,也可以实现第二层接口,那就需要实现多个接口,建议实现第三层接口。

     

    这些是sharding-jdbc的默认分片实现

    18141435_LVV9.jpg

    可以参考这些实现实现自己个性化分片实现

     

    这里是分片的引擎实现,在sql路由的时候会详细介绍

    18141435_Sx04.jpg

     

    sharding-jdbc集成spring的xml配置文件

    18141435_YE6b.jpg

     

    说到最后

    本篇文章主要介绍了sharding-jdbc提供了inline表达式分片方式,配置方便,还有提供了实现分片接口的方式,可以灵活扩展,和spring集成的配置可以参考最后一张图或者参考sharding-jdbc官方网站的文档,相信大家对这些了解之后,再看上篇文章sharding-jdbc集成spring配置文件解析的内容应该会容易一些,以上内容仅供参考,下篇文章将接着对上篇文章集成spring配置文件解析的剩余部分进行讲解。

    转载于:https://my.oschina.net/u/3775437/blog/1641860

    展开全文
  • 分片JDBC-分片数据库和表的JDBC驱动程序 概述 分片JDBC是JDBC的扩展,提供了诸如分片,读/写拆分和BASE事务之类的分布式功能。 特征 1.分片 分布式数据库中支持的聚合功能,分组依据,排序依据和限制SQL。...
  • 快速掌握使用shardingjdbc框架,shardingjdbc是目前国内最热门的分库分表框架,更是大型高并发网络公司的技术架构?
  • 文章目录系列文章目录前言一、下载源码以及编译1 下载源码2 导入并编译源码二、深入源码解析1.源码入口2.创建数据源源码解析2.1 创建数据源源码入库2.2 初始化路由规则2.2.1 创建表路由规则2.2.1.1构建分表策略总结 ...
  • 下载源码(选择自己喜欢的版本即可) https://github.com/apache/incubator-shardingsphere/archive/4.0.0-RC2.zip 2、导入工程到IDEA 3、sharding-core-parse编译 注意先编译此工程是因为:工程内的部分类...
  • ShardingPreparedStatement#executeQuery(): public ResultSet executeQuery() throws SQLException { ResultSet result; try { clearPrevious(); shard(); // 路由并重写好真实sql ...
  • 使用sharding-jdbc快速实现自动读写分离-demo源码
  • 如何快速阅读ShardingSphere源码 ShardingSphere的目录结构 如何快速把握 ShardingSphere 的代码结构呢?这是我们剖析源码时需要回答的第一个问题,为此我们需要梳理剖析 ShardingSphere 框架代码结构的系统方法。...
  • 工作闲暇之余,把自己学到的东西记录一下,感兴趣的朋友可以去了解下Sharding

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,433
精华内容 5,373
关键字:

sharding源码

友情链接: altera_ps2.rar