应用层针对数据切片的实现方法

Posted wuqiqing_1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了应用层针对数据切片的实现方法相关的知识,希望对你有一定的参考价值。

为了满足业务增长和服务能力的增长,我们需要必要的sharding操作,通过水平或者垂直的切割将系统分别放置于不同的物理机器上,从而达到很好的扩展性,也为业务的发展提供技术保证,那么看似简单的sharding,在应用层次需要做那些工作呢?
   在详细描述之前,我们需要定义以下两件事:
    (1)定义sharding的方式,设定我们需要shading模式是通过SQL方式访问数据库。
    (2)定义SQL访问时sharding的精细度,即需要SQL解析的模式还是简单的数据源绑定模式,不同的实现方式其实现复杂度也完全不一样。
  接下来我们开始详细讲解数据源绑定模式和SQL解析模式的具体实现方法。
  假设我们有用户信息2000万或者更多,随着业务的增长我们需要根据userid将此sharding, 数据源绑定的模式是如何实现的?
    第一步,定义数据库的sharding方式,将数据库通过schema方式切分开来,简单SQL代码如下。
     SQL代码如下:
     create database user00;
     create database user01;
      ...
     create database user09;
   第二步,将10个schema分布到不通的物理机器上,并创建相同的表,表的个数一定为10份。
     machine1:
      user00~user02:
      create table user 
      (
        userid    bi gint (12),
        email    varchar(256),
        ........
       )  

   machine2:

     user03~user05:
      create table user 
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  

machine3:

     user06~user09:
      create table user 
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
第三步,定义数据源与具体逻辑数据库的关系,简单的XML配置代码如下:

<datasource-config>
<datasource name="user00" value="0">
  <property name="driver" value="com. mysql .jdbc.Driver"/>
  <property name="url" value="jdbc: mysql ://10.224.57.116:3306/user00"/>
  <property name="user" value="test"/>
  <property name="password" value="pass"/>
</datasource>
...
<datasource name="user03" value="3">
  <property name="driver" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://10.224.57.117:3306/user03"/>
  <property name="user" value="test"/>
  <property name="password" value="pass"/>
</datasource>
...
<datasource name="user06" value="6">
  <property name="driver" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://10.224.57.118:3306/user06"/>
  <property name="user" value="test"/>
  <property name="password" value="pass"/>
</datasource>
...
</datasource-config>

第四步,根据传入的USERID,进行数据源的选择,代码逻辑如下:
(1)插入数据:
         SQL语句为: insert into user(userid,email) values(1,'aa@sina.com');
         插入逻辑:根据userid的value=1进行取模10的值=1,知道此时插入的数据源为user01,根据数据源打开数据库,插入数据。

(2)查询数据:
           SQL语句为: select * from    user where  userid=12;
           查询逻辑:根据userid的value=1进行取模10的值=2,知道此时查询的数据源为user02,根据数据源打开数据库,获取查询数据。

总结:数据源绑定模式相对比较粗犷,实现方式非常简单,拆分的数量与数据源的配置数量成正比,将数据源与传入的值进行绑定, sharding的精细度只能到schema级别,使用的SQL语句一定是固定的,可改造ibatis的数据源注入情况,达到ibatis的下应用的sharding。

依然假设我们有用户信息2000万或者更多,随着业务的增长我们需要根据userid将此sharding, SQL解析的模式是如何实现的?
第一步,定义数据库的sharding方式,将数据库通过schema和表的方式切分开来,将4个schema分布到不通的物理机器上,并创建不同命名的表,表的个数是4*10=40。
machine1:
      user00:
      create table user00
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
      ......
     create table user09
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
    
user01:
      create table user10
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
      .....
      create table user19
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  

   machine2:

     user02:
      create table user20
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
      .....
      create table user29
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  

   user03:
      create table user30
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
      .....
      create table user39
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  

machine3:

      user04:
      create table user40
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
      .....
      create table user49
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
    user05:
      create table user50
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
      .....
      create table user59
      (
        userid   bigint (12),
        email    varchar(256),
        ........
       )  
第二步,定义数据源与具体逻辑数据库的关系,简单的XML代码如下:

<datasource-config>
<datasource name="user00" value="0">
  <property name="driver" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://10.224.57.116:3306/user00"/>
  <property name="user" value="test"/>
  <property name="password" value="pass"/>
</datasource>
...
<datasource name="user02" value="2">
  <property name="driver" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://10.224.57.117:3306/user03"/>
  <property name="user" value="test"/>
  <property name="password" value="pass"/>
</datasource>
...
<datasource name="user04" value="4">
  <property name="driver" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://10.224.57.118:3306/user06"/>
  <property name="user" value="test"/>
  <property name="password" value="pass"/>
</datasource>
...
</datasource-config>

第三步,根据传入的USERID,进行数据源和表选择,代码逻辑如下:
(1)插入数据:
         SQL语句为: insert into user(userid,email) values(1,'aa@sina.com');
         插入逻辑:根据userid的value=1进行取模10的值=1,知道此时插入的数据源为user01,在根据userid末尾两位数据知道表名为user01,此时的SQL语句中表名已经更改,如果使用ibtais书写SQL,那么静态的SQL无法替换成动态的SQL语句,此时有两种做法,一种方法是在ibtais上层实现一套解析层,将SQL解析后并替换再传递给ibatis去执行,另一种方法是改写ibtais的代码,加入SQL解析程序,将SQL解析后并替换再传递给ibatis去执行插入操作,此时的难点在于SQL的语法解析,目前比较著名的淘宝TDDL就是采取第一种的方法,使用 java cc去解析SQL语句。本人尝试了下第二种方法即ibatis的改写模式,在此将实现代码分享给大家。
为啥通过切片分配到列表末尾之后不会引发 IndexError? [复制]

如何从末尾到开头切片数据帧?

Python/Numpy - 在数组末尾环绕切片

在 python 中创建切片对象

Database数据库切片模式

如何截断数据表中的字段数据并在末尾添加 <更多选项> 以查看整个字段数据?