美文网首页
2020-04-19 数据库的分表分库

2020-04-19 数据库的分表分库

作者: 奇妙林林 | 来源:发表于2020-04-19 17:49 被阅读0次

    分表分库

    垂直拆分

    垂直拆分就是要把表按模块划分到不同数据库表中(当然原则还是不破坏第三范式),这种拆分在大型网站的演变过程中是很常见的。当一个网站还在很小的时候,只有小量的人来开发和维护,各模块和表都在一起,当网站不断丰富和壮大的时候,也会变成多个子系统来支撑,这时就有按模块和功能把表划分出来的需求。其实,相对于垂直切分更进一步的是服务化改造,说得简单就是要把原来强耦合的系统拆分成多个弱耦合的服务,通过服务间的调用来满足业务需求看,因此表拆出来后要通过服务的形式暴露出去,而不是直接调用不同模块的表,淘宝在架构不断演变过程,最重要的一环就是服务化改造,把用户、交易、店铺、宝贝这些核心的概念抽取成独立的服务,也非常有利于进行局部的优化和治理,保障核心模块的稳定性

    垂直拆分用于分布式场景。

    水平拆分

    上面谈到垂直切分只是把表按模块划分到不同数据库,但没有解决单表大数据量的问题,而水平切分就是要把一个表按照某种规则把数据划分到不同表或数据库里。例如像计费系统,通过按时间来划分表就比较合适,因为系统都是处理某一时间段的数据。而像SaaS应用,通过按用户维度来划分数据比较合适,因为用户与用户之间的隔离的,一般不存在处理多个用户数据的情况,简单的按user_id范围来水平切分

    通俗理解:水平拆分行,行数据拆分到不同表中,垂直拆分列,表数据拆分到不同表中

    水平分割案例

    思路:在大型电商系统中,每天的会员人数不断的增加。达到一定瓶颈后如何优化查询。

    可能大家会想到索引,万一用户量达到上亿级别,如何进行优化呢?

    使用水平分割拆分数据库表。

    如何使用水平拆分数据库

    使用水平分割拆分表,具体根据业务需求,有的按照注册时间、取摸、账号规则、年份等。

    使用取摸方式分表(使用一致性hash算法,对userid取模,来分表)

    首先我创建三张表 user0 / user1 /user2 , 然后我再创建 uuid表,该表的作用就是提供自增的id。

    create table user0(

    id int unsigned primary key ,

    name varchar(32) not null default '',

    pwd  varchar(32) not null default '')

    engine=myisam charset utf8;

    create table user1(

    id int unsigned primary key ,

    name varchar(32) not null default '',

    pwd  varchar(32) not null default '')

    engine=myisam charset utf8;

    create table user2(

    id int unsigned primary key ,

    name varchar(32) not null default '',

    pwd  varchar(32) not null default '')

    engine=myisam charset utf8;

    create table uuid(

    id int unsigned primary key auto_increment)engine=myisam charset utf8;

    创建一个demo项目

    POM文件

    <parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>1.3.3.RELEASE</version>

    </parent>

    <dependencies>

    <dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-jdbc</artifactId>

    </dependency>

    <dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter</artifactId>

    </dependency>

    <dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-test</artifactId>

    <scope>test</scope>

    </dependency>

    <dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    </dependency>

    <dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    </dependencies>

    Service代码

    @Service

    public class UserService {

     

    @Autowired

    private JdbcTemplate jdbcTemplate;

     

    public String regit(String name, String pwd) {

    // 1.先获取到 自定增长ID

    String idInsertSQL = "INSERT INTO uuid VALUES (NULL);";

    jdbcTemplate.update(idInsertSQL);

    Long insertId = jdbcTemplate.queryForObject("select last_insert_id()", Long.class);

    // 2.判断存储表名称

    String tableName = "user" + insertId % 3;

    // 3.注册数据

    String insertUserSql = "INSERT INTO " + tableName + " VALUES ('" + insertId + "','" + name + "','" + pwd

    + "');";

    System.out.println("insertUserSql:" + insertUserSql);

    jdbcTemplate.update(insertUserSql);

    return "success";

    }

     

    public String get(Long id) {

    String tableName = "user" + id % 3;

    String sql = "select name from " + tableName + "  where id="+id;

    System.out.println("SQL:" + sql);

    String name = jdbcTemplate.queryForObject(sql, String.class);

    return name;

    }

     

    }

    Controller

    @RestController

    public class UserController {

    @Autowired

    private UserService userService;

     

    @RequestMapping("/regit")

    public String regit(String name, String pwd) {

    return userService.regit(name, pwd);

    }

     

    @RequestMapping("/get")

    public String get(Long id) {

    String name = userService.get(id);

    return name;

    }

     

    }

    读写分离:

    读写分离是在优化数据库性能的时候,常用的技术,因为在写数据的时候是会造成数据不安全性能问题的,多以比较慢,但是在读数据库的时候是很快的,所以分开数据能提高性能。

    使用数据库中间件来实现分库分表:

    1、什么是MyCat: 

    MyCat是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。

    MyCat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。而在最终用户看来,无论是那种存储方式,在MyCat里,都是一个传统的数据库表,支持标准的SQL语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度

    2、MyCat有哪些作用?

    目前虽然传统关系数据库存在一些列的先天弊端,但NoSQL数据库又将其替代,但是如果传统数据库易于扩展和分拆就可以极大的避免单机单库在数据增删改查方面的缺陷。MyCat就是为了解决数据库的分拆和扩展而生的开源分布式数据库系统。其最终的目标就是低成本地将现有的单机数据库和应用平滑迁移到“云”端,解决数据存储和业务规模迅速增长情况下的数据瓶颈问题。

    举个简单的例子

    如果你只是开一个小卖铺(小项目) ,那么你一个人(数据库)就可以了,但是如果你开一个大型购物中心(大项目),如果不分部门的话,人员(数据)就很难管理,所以按人员不同分了很多部门(数据库),但是光有部门,没有一个统一的管理者(mycat),那么各个部门的配合和协调能力就大大降低了,超市的健康运营就会受到影响。而mycat就是这个管理者,它是对数据库层做一个抽象,来管理这些数据库,而最上面的应用只需要面对一个数据库层的抽象或者说数据库中间件就好了,这就是Mycat的核心作用。 

    所以可以这样理解:数据库是对底层存储文件的抽象,而Mycat是对数据库的抽象。

    2.1.一般数据库的拆表机制

    2.2.MyCat中间件和应用层解决方案对比

    3、MyCa的原理

    MyCat技术原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。

    相关文章

      网友评论

          本文标题:2020-04-19 数据库的分表分库

          本文链接:https://www.haomeiwen.com/subject/lpbvbhtx.html