海量数据的存储问题

如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB。对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求。这个时候NoSQL的出现暂时解决了这一危机。它通过降低数据的安全性,减少对事务的支持,减少对复杂查询的支持,来获取性能上的提升。

但是,在有些场合NoSQL一些折衷是无法满足使用场景的,就比如有些使用场景是绝对要有事务与安全指标的。这个时候NoSQL肯定是无法满足的,所以还是需要使用关系性数据库。如果使用关系型数据库解决海量存储的问题呢?此时就需要做数据库集群,为了提高查询性能将一个数据库的数据分散到不同的数据库中存储。

转自http://blog.csdn.net/jaysonhu/article/details/52858535

1. 学习计划

1、订单系统实现

2、订单生成

3、Mycat数据库分片

 

写在前面

  Mycat作为独立的数据库中间件,我们只需要进行相关的配置,就可以非常方便的帮我们实现水平切分、垂直切分、读写分离等功能,但Mysql的主从复制需要我们通过其它方式实现。这里假设我们已经搭建好相关的环境,下面就开始我们的实践吧!

试验环境
系统window
mysql:
使用的是phpstudy自带数据库

1.1 什么是数据库分片

简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。

数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式。

(1)一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直(纵向)切分

图片 1

 

 

 

(2)另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。

 图片 2

 

mysql安装

  1. 下载mysql

  2. 解压
    tar -zxvf mysql-5.6.32-linux-glibc2.5-x86_64.tar.gz

  3. 把mysql文件夹移动到 /usr/local/ 下
    mv mysql-5.6.32-linux-glibc2.5-x86_64 /usr/local/mysql

  4. 创建mysql用户和组

    groupadd mysql
    adduser -r -g mysql mysql
    chown -R mysql.mysql /usr/local/mysql  //修改mysql目录所属mysql用户
    
  5. 安装

    /usr/local/mysql/scripts/mysql_install_db

  6. 修改配置文件my.cnf,必须要修改才能使用mycat

    最后一行添加

    lower_case_table_names = 1

  7. 设置mysql服务

    cp -f /usr/local/mysql/support-files/mysql.server  /etc/init.d/mysqld
    
  8. 启动mysql

    service mysqld start

  9. 把mysql命令加入环境变量

    修改/etc/profile文件,最后行添加
    export PATH=$PATH:/usr/local/mysql/bin

    然后执行

    source /etc/profile

    使配置立即生效

  10. 登陆mysql如果提示错误
    Can't connect to local MySQL server through socket '/tmp/mysql.sock'
    执行命令
    ln /var/lib/mysql/mysql.sock /tmp/mysql.sock
    后再登陆

  11. root用户初始密码为空,修改密码使用mysqladmin命令
    mysqladmin -uroot -p password

  12. 登陆客户端

    mysql -uroot -p

  13. 创建测试数据库

 CREATE database db1;
 CREATE database db2;
 CREATE database db3;

至此mysql已经安装完成了

2. 订单系统

准备环境

  • Mysql(Version : 5.7)主从环境搭建
  • 对应数据库建立(以下例子中要建的数据库是:master1mycat 和
    master2mycat)

主库 定义为 123.207.43.xx

1.2 如何实现数据库分片

当数据库分片后,数据由一个数据库分散到多个数据库中。此时系统要查询时需要切换不同的数据库进行查询,那么系统如何知道要查询的数据在哪个数据库中?当添加一条记录时要向哪个数据库中插入呢?这些问题处理起来都是非常的麻烦。

这种情况下可以使用一个数据库中间件mycat来解决相关的问题。接下来了解一下什么是mycat。

安装java

2.1. 功能分析

1、在购物车页面点击“去结算”按钮,跳转到订单确认页面

a) 必须要求用户登录

b) 使用拦截器实现。

c) 如果用户未登录跳转到登录页面。

d) 如果用户已经登录,放行。展示确认页面。

e) 判断cookie中是否有购物车数据

f) 如果有同步到服务端。

2、订单确认页面中选择收货地址,选择支付方式,确认商品列表。

a) 根据用户id查询收货地址列表

b) 展示支付方式列表。

c) 从购物车中取商品列表,从服务端取购物车列表。

3、订单确认页面点击“提交”,生成订单。

4、展示订单生成完成,或者跳转到支付页面。

 

配置server.xml

        <user name="mysqlmycat">
                <property name="password">mysqlmycat</property>
                <property name="schemas">mysqlmycats</property>
        </user>
#  power by php中文网 2017  www.php.cn  官网下载最新版

[client]
port=3306
[mysql]
default-character-set=utf8

[mysqld]
port=3306

log-error = C:/phpStudy/PHPTutorial/MySQL/mylog/error.log
basedir="C:/phpStudy/PHPTutorial/MySQL/"
datadir="C:/phpStudy/PHPTutorial/MySQL/data/"
character-set-server=utf8
default-storage-engine=MyISAM
#支持 INNODB 引擎模式。修改为 default-storage-engine=INNODB 即可。
#如果 INNODB 模式如果不能启动,删除data目录下ib开头的日志文件重新启动
sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=512

query_cache_size=0
table_cache=256
tmp_table_size=18M

thread_cache_size=8
myisam_max_sort_file_size=64G
myisam_sort_buffer_size=35M
key_buffer_size=25M
read_buffer_size=64K
read_rnd_buffer_size=256K
sort_buffer_size=256K

innodb_additional_mem_pool_size=2M

innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=1M

innodb_buffer_pool_size=47M
innodb_log_file_size=24M
innodb_thread_concurrency=8
innodb_thread_concurrency=8
innodb_thread_concurrency=8


#主从复制
server-id=1

log_bin

sync_binlog=1


binlog_format=MIXED

Mycat介绍

mycat安装

  1. 下载mycat

  2. 解压

    tar -zxvf Mycat-server-1.6-RELEASE-20161012170031-linux.tar.gz

  3. 把mycat文件夹移动到 /usr/local/ 下
    mv Mycat-server-1.6-RELEASE-20161012170031-linux /usr/local/mycat

  4. 新建用户和组

    groupadd mycat
    adduser -r -g mycat mycat
    chown -R mycat.mycat /usr/local/mycat  //修改mycat目录所属mycat用户
    
  5. 修改配置文件 /usr/local/mycat/conf/schema.xml

    这里配置mysql的地址、用户名和密码

    <writeHost host="hostM1" url="localhost:3306" user="root" password="root">
        <readHost host="hostS1" url="localhost:3306" user="root" password="root" />
    </writeHost>
    

    server.xml

    这里配置mycat的用户名密码

    <user name="root">
       <property name="password">digdeep</property>
       <property name="schemas">TESTDB</property>
    </user>
    
  6. 启动mycat

    /usr/local/mycat/bin/mycat start

  7. 连接mycat

    mysql -uroot -pdigdeep -h127.0.0.1 -P8066 -DTESTDB

    注意这里 -h 后面必须是ip,使用localhost会出错

  8. 创建测试数据

use TESTDB;
create table company(id int not null primary key,name varchar(50),addr varchar(255));
insert into company values(1,"facebook","usa");
  1. 结果:查看mysql上的数据库db1,db2,db3上都创建了表company

2.2. 工程搭建

E3-order

  |–E3-order-interface(jar)

  |–E3-order-service(war)

E3-order-web(war)

 

配置schema.xml

        <schema name="mysqlmycats" checkSQLschema="false" sqlMaxLimit="100">
                <table name="tb_user" dataNode="mydn1,mydn2" rule="user-mod-long" />
                <table name="tb_student" dataNode="mydn1,mydn2" rule="student-mod-long" />
        </schema>

        <dataNode name="mydn1" dataHost="myhost1" database="master1mycat" />
        <dataNode name="mydn2" dataHost="myhost2" database="master2mycat" />

        <dataHost name="myhost1" maxCon="100" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native">
                <heartbeat>select user()</heartbeat>
                <writeHost host="hostM1" url="localhost:3306" user="root" password="xxx">
                        <readHost host="hostS1" url="localhost:3307" user="root" password="xxx"/>
                </writeHost>
        </dataHost>

        <dataHost name="myhost2" maxCon="100" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native">
                <heartbeat>select user()</heartbeat>
                <writeHost host="hostM2" url="localhost:3308" user="root" password="xxx" >
                        <readHost host="hostS2" url="localhost:3309" user="root" password="xxx"/>
                </writeHost>
        </dataHost>

这里日志采用混合模式

2.1 什么是Mycat?

 

Mycat 背后是阿里曾经开源的知名产品——Cobar。Cobar 的核心功能和优势是 MySQL 数据库分片,此产品曾经广为流传,据说最早的发起者对
Mysql 很精通,后来从阿里跳槽了,阿里随后开源的
Cobar,并维持到 2013 年年初,然后,就没有然后了。

Cobar 的思路和实现路径的确不错。基于
Java 开发的,实现了 MySQL 公开的二进制传输协议,巧妙地将自己伪装成一个
MySQL Server,目前市面上绝大多数 MySQL 客户端工具和应用都能兼容。比自己实现一个新的数据库协议要明智的多,因为生态环境在哪里摆着。

 

Mycat 是基于 cobar 演变而来,对 cobar 的代码进行了彻底的重构,使用 NIO 重构了网络模块,并且优化了 Buffer 内核,增强了聚合,Join 等基本特性,同时兼容绝大多数数据库成为通用的数据库中间件。

简单的说,MyCAT就是:

·一个新颖的数据库中间件产品支持mysql集群,或者mariadb cluster,提供高可用性数据分片集群。你可以像使用mysql一样使用mycat。对于开发人员来说根本感觉不到mycat的存在。

 图片 3

mysql主从服务器配置

  1. 修改主mysql配置文件my.cnf

    [mysqld]
    log_bin = mysql-bin  #记录操作日志
    binlog_ignore_db =  mysql  #不同步mysql系统数据库
    server_id = 1
    
  2. 启动主mysql,在主mysql创建一个用户user让从mysql连接,执行sql

    grant replication slave on *.* to 'user'@'%' identified by 'password'
    
  3. 修改从mysql配置文件my.cnf

    log_bin = mysql-bin  #记录操作日志
    replicate_ignore_db = mysql #不同步mysql系统数据库
    slave_skip_errors = all 
    server_id = 2
    
  4. 主mysql执行sql

    show master status;\G

    图片 4

    1.jpg

  5. 从mysql连接主mysql

    根据第2步配创建的user,password 和 第4步获取的file,position
    连接主mysql

//如果是mysql5.5
change master to master_host='node1',master_user='user',master_password='password',master_log_file='mysql-bin.000004',master_log_pos=120;
//如果是mysql5.6即以上可以不需要master_log_file和master_log_pos,mysql会自动识别
change master to master_host='node1',master_user='user',master_password='password';
  1. 开启从mysql,从mysql中执行

    start slave;

  2. 查看从mysql状态,从mysql执行

    show slave status\G;

    图片 5

    2.png

`红色下划线部分为yes则开启成功`
  1. 测试成果

    首先在主从mysql上都新建数据库testdb

    主mysql:use testdb;create table user(id int not null primary key,name varchar(50));

    从mysql上也会产生user表,主从mysql配置成功!

2.3. 展示订单确认页面

配置rule.xml

       <tableRule name="user-mod-long">
                <rule>
                        <columns>id</columns>
                        <algorithm>mod-long</algorithm>
                </rule>
        </tableRule>
       <tableRule name="student-mod-long">
                <rule>
                        <columns>user_id</columns>
                        <algorithm>mod-long</algorithm>
                </rule>
        </tableRule>

        <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
            <property name="count">2</property>
        </function>

  修改了配置文件后,别忘了重启Mycat,如果有异常出现,请通过查看logs目录下的日志文件进行排查。

然后主库配置就到这里

2.2 Mycat支持的数据库

 图片 6

 

读写分离配置

  1. 注意事项

    远程 mysql 必须允许 mycat主机
    远程连接,修改mysql.user表中的用户数据,执行sql

    update mysql.user set host = '%' where user = 'root'
    
  2. schema.xml配置

    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
    writeType="0" dbType="mysql" dbDriver="native" switchType="2"  slaveThreshold="100">
        <heartbeat>show slave status</heartbeat>
        <writeHost host="hostM1" url="node1:3306" user="root" password="root">
            <readHost host="hostS1" url="node2:3306" user="root" password="root" />
        </writeHost>
    </dataHost>
    

    dbDriver

    属性

    指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。使用
    native 的话,因为这个值执行的是二进制的 mysql 协议,所以可以使用
    mysql 和 maridb。其他类型的数据库则需要使用 JDBC 驱动来支持。

    从 1.6 版本开始支持 postgresql 的 native 原始协议。

    如果使用 JDBC 的话需要将符合 JDBC 4 标准的驱动 JAR 包放到 MYCAT\lib
    目录下,并检查驱动 JAR
    包中包括如下目录结构的文件:META-INF\services\java.sql.Driver。在这个文件内写上具体的
    Driver 类名,例如:com.mysql.jdbc.Driver。

    balance

    属性

    负载均衡类型,目前的取值有 3 种:

    1. balance=”0”, 不开启读写分离机制,所有读操作都发送到当前可用的
      writeHost 上。

    2. balance=”1”,全部的 readHost 与 stand by writeHost 参与 select
      语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且
      M1 与 M2 互为主备),正常情况下,M2,S1,S2 都参与 select
      语句的负载均衡。

    3. balance=”2”,所有读操作都随机的在 writeHost、readhost 上分发。

    4. balance=”3”,所有读请求随机的分发到 wiriterHost 对应的 readhost
      执行,writerHost 不负担读压

      力,注意 balance=3 只在 1.4 及其以后版本有,1.3 没有。

    writeType

    属性

    负载均衡类型,目前的取值有 3 种:

    1. writeType=”0”, 所有写操作发送到配置的第一个
      writeHost,第一个挂了切到还生存的第二个

      writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties
      .

    2. writeType=”1”,所有写操作都随机的发送到配置的 writeHost,1.5
      以后废弃不推荐。

    switchType

    属性

    • -1 表示不自动切换

    • 1 默认值,自动切换

    • 2 基于 MySQL 主从同步的状态决定是否切换

      心跳语句为 show slave status

  3. 根据主从延时切换技术

    Mycat1.4开始支持
    MySQL主从复制状态绑定的读写分离机制,让读更加安全可靠,配置如下:
    MyCAT心跳检查语句配置为 show slave status ,dataHost
    上定义两个新属性: switchType=”2”
    与slaveThreshold=”100”,此时意味着开启MySQL主从复制状态绑定的读写分离与切换机制,Mycat心跳机制通过检测
    show slave status 中的 “Seconds_Behind_Master”,
    “Slave_IO_Running”, “Slave_SQL_Running”
    三个字段来确定当前主从同步的状态以及Seconds_Behind_Master
    主从复制时延, 当Seconds_Behind_Master>slaveThreshold
    时,读写分离筛选器会过滤掉此Slave机器,防止读到很久之前的旧数据,而当主节点宕机后,切换逻辑会检查Slave上的Seconds_Behind_Master是否为0,为0时则表示主从同步,可以安全切换,否则不会切换。

  4. 重启mycat,连接创建测试数据

    use TESTDB;
    create table company(id int not null primary key,name varchar(50),addr varchar(255));
    insert into company values(1,"facebook","usa");
    
  5. 结果:查看主从mysql上的db1,db2,db3上都创建了表company

  6. 如果你的mysql的复制模式为STATEMENT(可以在my.cnf中配置binlog_format="STATEMENT"),还可以这样测试。

    mycat执行sql :

    insert into company values(1,@@hostname,"usa");`
    select * from company ;
    

图片 7

3.jpg

 可以看出,读取数据是从从mysql读出的

2.3.1. 功能分析

1、根据id查询用户的收货地址列表(使用静态数据)

2、从购物车中取商品列表,展示到页面。调用购物车服务查询。

 

项目搭建(SpringBoot + JPA)

  • 准备:首次建表,设置application.yml中的spring.jpa.hibernate.ddl-auto属性为:create(JPA自动建表解决方案,使用update的话在连接mycat的时候会报找不到表的错误)。为保证数据不被丢失,在建表之后可以更改为:update

  • 添加application.yml:

spring:
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
      naming:
        strategy: org.hibernate.cfg.ImprovedNamingStrategy
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
  datasource:
    url: jdbc:mysql://localhost:8066/mysqlmycats?characterEncoding=UTF-8&useSSL=false&autoReconnect=true&rewriteBatchedStatements=true
    username: mysqlmycat
    password: mysqlmycat
  • 添加User Entity

@Entity
@Table(name = "tb_user")
@Data
public class User {

    @Id
    private Long id;

    private String name;

    private Integer gender;

}
  • 添加Student Entity

@Entity
@Table(name = "tb_student")
@Data
public class Student {

    @Id
    private Long id;

    private String name;

    @Column(unique = true)
    private Long userId;

}
  • 添加UserDao

public interface UserDao extends JpaRepository<User, Long> {

    Page<User> findByNameLike(String name, Pageable pageable);

}
  • 添加StudentDao

public interface StudentDao extends JpaRepository<Student, Long> {

    Page<User> findByNameLike(String name, Pageable pageable);

}

接下来我们需要开设来宾访问权限

2.3 Mycat的分片策略

 图片 8

 

 

 

2.3.2. Dao层

直接从redis中取购车商品列表。

 

项目测试

  1. 测试添加

@Test
public void testAdd() {
        for (long i = 0; i < 30; i++) {
            User user = new User();
            user.setId(i);
            user.setName("张三" + i);
            user.setGender(i % 2 == 0 ? 0 : 1);
            userDao.save(user);

            Student student = new Student();
            student.setId(System.currentTimeMillis() + i);
            student.setName("张三学生" + i);
            student.setUserId(i);
            studentDao.save(student);
        }
}

测试结果:数据按id取模的方式划分到了两个数据库中,同时从库同步了主库的数据

图片 9

水平切分(id取模)

  1. 测试模糊查询+分页

@Test
public void testFind() {
        Pageable pageable = new PageRequest(0, 10, Sort.Direction.DESC, "id");
        List<User> userList = userDao.findByNameLike("%张三2%", pageable).getContent();
        userList.forEach(System.out::println);

        Pageable pageable2 = new PageRequest(0, 10, Sort.Direction.DESC, "userId");
        List<Student> studentList = studentDao.findByNameLike("%张三学生1%", pageable2).getContent();
        studentList.forEach(System.out::println);
}

测试结果:按照模糊匹配及id降序的方式输出结果

图片 10

测试模糊查询+分页

测试结果:读操作都走了从库

图片 11

读写分离,读都走了从库

  1. 删除及修改请自行测试

GRANT ALL PRIVILEGES ON . TO ‘myuser’@’%’IDENTIFIED BY ‘mypassword’
WITH GRANT OPTION;

2.4 概念说明

2.3.3. Service层

收货地址静态数据,没有server。

调用购物车的service查询购物车商品列表。

 

参考链接

Mycat官网
Mycat从零开始
Mycat权威指南

GitHub:Mycat-Server
Wiki:Mycat-Server
Issues:Mycat-Server
mysql中间件研究(Atlas,Cobar,TDDL)
mysql中间件研究(Atlas,Cobar,TDDL,Mycat,Heisenberg,Oceanus,Vitess,OneProxy)

myuser mypassword随便起 但是要记住这个是你从库登录凭证

2.4.1 逻辑库(schema) :

前面一节讲了数据库中间件,通常对实际应用来说,并不需要知道中间件的存在,业务开发人员只需要知道数据库的概念,所以数据库中间件可以被看做是一个或多个数据库集群构成的逻辑库。

2.3.4. Controller

引用购物车服务

 图片 12

图片 13

 

 

 

请求的url:/order/order-cart

参数:没有参数

返回值:逻辑视图

 

Controller

@Controller
public class OrderCartController {

    @Autowired
    private CartService cartService;

    @RequestMapping("/order/order-cart")
    public String showOrderCart(HttpServletRequest request) {
        //取用户信息
        TbUser user = (TbUser) request.getAttribute("user");
        //取购物车商品列表
        List<TbItem> cartList = cartService.getCartList(user.getId());
        //把商品列表传递给jsp
        request.setAttribute("cartList", cartList);
        //返回逻辑视图
        return "order-cart";
    }
}

 

2.4. 登录拦截器 

我们还需要查询一下log的位置与名字
showmaster status;
记录一下 之后会用到

2.4.2 逻辑表(table):

既然有逻辑库,那么就会有逻辑表,分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表,可以是数据切分后,分布在一个或多个分片库中,也可以不做数据切分,不分片,只有一个表构成。

分片表:是指那些原有的很大数据的表,需要切分到多个数据库的表,这样,每个分片都有一部分数据,所有分片构成了完整的数据。
总而言之就是需要进行分片的表。

非分片表:一个数据库中并不是所有的表都很大,某些表是可以不用进行切分的,非分片是相对分片表来说的,就是那些不需要进行数据切分的表。

2.4.1. 功能分析

1、从cookie中取token

2、如果没有取到,没有登录,跳转到sso系统的登录页面。拦截

3、如果取到token。判断登录是否过期,需要调用sso系统的服务,根据token取用户信息

4、如果没有取到用户信息,登录已经过期,重新登录。跳转到登录页面。拦截

5、如果取到用户信息,用户已经是登录状态,把用户信息保存到request中。放行

6、判断cookie中是否有购物车信息,如果有合并购物车

 

从库
my.ini配置

2.4.3 分片节点(dataNode)

数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点(dataNode)。

2.4.2. 拦截器实现

 

/**
 * 用户登录判断拦截器
 * <p>Title: LoginInterceptor</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
public class LoginInterceptor implements HandlerInterceptor {

    @Value("${COOKIE_TOKEN_KEY}")
    private String COOKIE_TOKEN_KEY;
    @Value("${COOKIE_CART_KEY}")
    private String COOKIE_CART_KEY;
    @Value("${SSO_URL}")
    private String SSO_URL;
    @Autowired
    private UserService userService;
    @Autowired
    private CartService cartService;

    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1、从cookie中取token
        String token = CookieUtils.getCookieValue(request, COOKIE_TOKEN_KEY);
        // 2、如果没有取到,没有登录,跳转到sso系统的登录页面。拦截
        if (StringUtils.isBlank(token)) {
            //跳转到登录页面
            response.sendRedirect(SSO_URL + "/page/login?redirect=" + request.getRequestURL());
            return false;
        }
        // 3、如果取到token。判断登录是否过期,需要调用sso系统的服务,根据token取用户信息
        E3Result e3Result = userService.getUserByToken(token);
        // 4、如果没有取到用户信息,登录已经过期,重新登录。跳转到登录页面。拦截
        if (e3Result.getStatus() != 200) {
            response.sendRedirect(SSO_URL + "/page/login?redirect=" + request.getRequestURL());
            return false;
        }
        // 5、如果取到用户信息,用户已经是登录状态,把用户信息保存到request中。放行
        TbUser user = (TbUser) e3Result.getData();
        request.setAttribute("user", user);
        // 6、判断cookie中是否有购物车信息,如果有合并购物车
        String json = CookieUtils.getCookieValue(request, COOKIE_CART_KEY, true);
        if (StringUtils.isNotBlank(json)) {
            cartService.mergeCart(user.getId(), JsonUtils.jsonToList(json, TbItem.class));
            //删除cookie中的购物车数据
            CookieUtils.setCookie(request, response, COOKIE_CART_KEY, "");
        }
        //放行
        return true;
    }

}

 

2.4.3. Springmvc配置 

<!-- 拦截器配置 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="cn.e3mall.order.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

  

主从复制

server-id = 2

只需加入这句话

然后设置连接

mysql>grantreplication slave on . to ‘testcreate’@’192.168.1.61’
identified by ‘123456’;

说明:’testcreate’:同步的数据库;

  ‘192.168.1.61’:同步的数据库地址;

    ‘123456’ :同步的数据库密码,在从库配置时需要设置。

mysql>showslave status\G;

执行上述命令显示:

两个yes那么成功

图片 14

image.png

如果遇到关于position相关的错误,就需要再手动设置以下File/Postion的信息

mysql>Changemaster to master_host = ‘192.168.1.60’

master_user= ‘test’

master_password=’123456’

master_log_file=’mysql-bin.000001’, 主库的文件信息

master_log_pos=’106’;主库的Position信息

把之前查到的名字 和pos填进去
然后slave start

2.4.4 节点主机(dataHost)

数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost),为了规避单节点主机并发数限制,尽量将读写压力高的分片节点(dataNode)均衡的放在不同的节点主机(dataHost)。

2.4.4. 实现sso系统的回调

 图片 15

 

2.4.5 分片规则(rule)

前面讲了数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。

2.5. 提交订单

Mycat的下载及安装

2.5.1. 功能分析

1、在订单确认页面点击“提交订单”按钮生成订单。

2、请求的url:/order/create

3、参数:提交的是表单的数据。保存的数据:订单、订单明细、配送地址。

a) 向tb_order中插入记录。

  1. 订单号需要手动生成。

要求订单号不能重复。

订单号可读性号。

可以使用redis的incr命令生成订单号。订单号需要一个初始值。

  1. Payment:表单数据
  2. payment_type:表单数据
  3. user_id:用户信息
  4. buyer_nick:用户名
  5. 其他字段null

b) 向tb_order_item订单明细表插入数据。

  1. Id:使用incr生成
  2. order_id:生成的订单号
  3. 其他的都是表单中的数据。

c) tb_order_shipping,订单配送信息

  1. order_id:生成的订单号
  2. 其他字段都是表单中的数据。

d) 使用pojo接收表单的数据。

可以扩展TbOrder,在子类中添加两个属性一个是商品明细列表,一个是配送信息。

把pojo放到e3-order-interface工程中。

public class OrderInfo extends TbOrder implements Serializable{
    private List<TbOrderItem> orderItems;
    private TbOrderShipping orderShipping;
    public List<TbOrderItem> getOrderItems() {
        return orderItems;
    }
    public void setOrderItems(List<TbOrderItem> orderItems) {
        this.orderItems = orderItems;
    }
    public TbOrderShipping getOrderShipping() {
        return orderShipping;
    }
    public void setOrderShipping(TbOrderShipping orderShipping) {
        this.orderShipping = orderShipping;
    }

}

 

业务逻辑: 

1、接收表单的数据

2、生成订单id

3、向订单表插入数据。

4、向订单明细表插入数据

5、向订单物流表插入数据。

6、返回e3Result。

 

返回值:e3Result

 

3.1 安装环境

1、jdk:要求jdk必须是1.7及以上版本

2、Mysql:推荐mysql是5.5以上版本

3、Mycat:

Mycat的官方网站:

http://www.mycat.org.cn/

下载地址:

https://github.com/MyCATApache/Mycat-download

 

2.5.2. Dao层

可以使用逆向工程。

 

3.2 安装步骤

Mycat有windows、linux多种版本。本教程为linux安装步骤,windows基本相同。

第一步:下载Mycat-server-xxxx-linux.tar.gz

第二步:将压缩包解压缩。建议将mycat放到/usr/local/mycat目录下。

第三步:进入mycat目录,启动mycat

./mycat start

停止:

./mycat stop

mycat 支持的命令{ console | start | stop | restart | status
| dump }

Mycat的默认端口号为:8066

2.5.3. Service层

参数:OrderInfo

返回值:e3Result

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private TbOrderMapper orderMapper;
    @Autowired
    private TbOrderItemMapper orderItemMapper;
    @Autowired
    private TbOrderShippingMapper orderShippingMapper;
    @Autowired
    private JedisClient jedisClient;

    @Value("${ORDER_GEN_KEY}")
    private String ORDER_GEN_KEY;
    @Value("${ORDER_ID_BEGIN}")
    private String ORDER_ID_BEGIN;
    @Value("${ORDER_ITEM_ID_GEN_KEY}")
    private String ORDER_ITEM_ID_GEN_KEY;

    @Override
    public e3Result createOrder(OrderInfo orderInfo) {
        // 1、接收表单的数据
        // 2、生成订单id
        if (!jedisClient.exists(ORDER_GEN_KEY)) {
            //设置初始值
            jedisClient.set(ORDER_GEN_KEY, ORDER_ID_BEGIN);
        }
        String orderId = jedisClient.incr(ORDER_GEN_KEY).toString();
        orderInfo.setOrderId(orderId);
        orderInfo.setPostFee("0");
        //1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭
        orderInfo.setStatus(1);
        Date date = new Date();
        orderInfo.setCreateTime(date);
        orderInfo.setUpdateTime(date);
        // 3、向订单表插入数据。
        orderMapper.insert(orderInfo);
        // 4、向订单明细表插入数据
        List<TbOrderItem> orderItems = orderInfo.getOrderItems();
        for (TbOrderItem tbOrderItem : orderItems) {
            //生成明细id
            Long orderItemId = jedisClient.incr(ORDER_ITEM_ID_GEN_KEY);
            tbOrderItem.setId(orderItemId.toString());
            tbOrderItem.setOrderId(orderId);
            //插入数据
            orderItemMapper.insert(tbOrderItem);
        }
        // 5、向订单物流表插入数据。
        TbOrderShipping orderShipping = orderInfo.getOrderShipping();
        orderShipping.setOrderId(orderId);
        orderShipping.setCreated(date);
        orderShipping.setUpdated(date);
        orderShippingMapper.insert(orderShipping);
        // 6、返回e3Result。
        return e3Result.ok(orderId);
    }

}

 

  

Mycat的分片

2.5.4. Controller

请求的url:/order/create

参数:使用OrderInfo接收

返回值:逻辑视图。

业务逻辑:

1、接收表单提交的数据OrderInfo。

2、补全用户信息。

3、调用Service创建订单。

4、返回逻辑视图展示成功页面

a) 需要Service返回订单号

b) 当前日期加三天。

 

在拦截器中添加用户处理逻辑:

 图片 16

@RequestMapping(value="/order/create", method=RequestMethod.POST)
    public String createOrder(OrderInfo orderInfo, HttpServletRequest request) {
        // 1、接收表单提交的数据OrderInfo。
        // 2、补全用户信息。
        TbUser user = (TbUser) request.getAttribute("user");
        orderInfo.setUserId(user.getId());
        orderInfo.setBuyerNick(user.getUsername());
        // 3、调用Service创建订单。
        e3Result result = orderService.createOrder(orderInfo);
        //取订单号
        String orderId = result.getData().toString();
        // a)需要Service返回订单号
        request.setAttribute("orderId", orderId);
        request.setAttribute("payment", orderInfo.getPayment());
        // b)当前日期加三天。
        DateTime dateTime = new DateTime();
        dateTime = dateTime.plusDays(3);
        request.setAttribute("date", dateTime.toString("yyyy-MM-dd"));
        // 4、返回逻辑视图展示成功页面
        return "success";
    }

 

3. Mycat数据库分片

 

4.1 需求

把商品表分片存储到三个数据节点上。

 

海量数据的存储问题

如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB。对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求。这个时候NoSQL的出现暂时解决了这一危机。它通过降低数据的安全性,减少对事务的支持,减少对复杂查询的支持,来获取性能上的提升。

但是,在有些场合NoSQL一些折衷是无法满足使用场景的,就比如有些使用场景是绝对要有事务与安全指标的。这个时候NoSQL肯定是无法满足的,所以还是需要使用关系性数据库。如果使用关系型数据库解决海量存储的问题呢?此时就需要做数据库集群,为了提高查询性能将一个数据库的数据分散到不同的数据库中存储。

4.2 安装环境分析

两台mysql数据库服务器:

Host1:192.168.25.134

Host2:192.168.25.166

 

host1环境

操作系统版本 : centos6.4

数据库版本 : mysql-5.6

mycat版本 :1.4 release

数据库名 : db1、db3

 

 

mysql节点2环境

操作系统版本 : centos6.4

数据库版本 : mysql-5.6

mycat版本 :1.4 release

数据库名 : db2

 

MyCat安装到节点1上(需要安装jdk)

 

1.1 什么是数据库分片

简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。

数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式。

(1)一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直(纵向)切分

图片 17

 

 

 

(2)另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。

 图片 18

 

4.3 配置schema.xml

1.2 如何实现数据库分片

当数据库分片后,数据由一个数据库分散到多个数据库中。此时系统要查询时需要切换不同的数据库进行查询,那么系统如何知道要查询的数据在哪个数据库中?当添加一条记录时要向哪个数据库中插入呢?这些问题处理起来都是非常的麻烦。

这种情况下可以使用一个数据库中间件mycat来解决相关的问题。接下来了解一下什么是mycat。

4.3.1 Schema.xml介绍

Schema.xml作为MyCat中重要的配置文件之一,管理着MyCat的逻辑库、表、分片规则、DataNode以及DataSource。弄懂这些配置,是正确使用MyCat的前提。这里就一层层对该文件进行解析。

 

schema 标签用于定义MyCat实例中的逻辑库

Table 标签定义了MyCat中的逻辑表

dataNode 标签定义了MyCat中的数据节点,也就是我们通常说所的数据分片。

dataHost标签在mycat逻辑库中也是作为最底层的标签存在,直接定义了具体的数据库实例、读写分离配置和心跳语句。

 

注意:若是LINUX版本的MYSQL,则需要设置为Mysql大小写不敏感,否则可能会发生表找不到的问题。

在MySQL的配置文件中/etc/my.cnf [mysqld] 中增加一行

  lower_case_table_names=1

 

Mycat介绍

4.3.2 Schema.xml配置

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/">

        <schema name="e3mall" checkSQLschema="false" sqlMaxLimit="100">
                <!-- auto sharding by id (long) -->
                <table name="tb_item" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
        </schema>
        <dataNode name="dn1" dataHost="localhost1" database="db1" />
        <dataNode name="dn2" dataHost="localhost2" database="db2" />
        <dataNode name="dn3" dataHost="localhost1" database="db3" />
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
                writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.25.134:3306" user="root"
                        password="root">
                        <!-- can have multi read hosts -->

                </writeHost>
        </dataHost>
        <dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"
                writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.25.166:3306" user="root"
                        password="root">
                        <!-- can have multi read hosts -->

                </writeHost>
        </dataHost>
</mycat:schema>

 

4.4 配置server.xml 

 

2.1 什么是Mycat?

 

Mycat 背后是阿里曾经开源的知名产品——Cobar。Cobar 的核心功能和优势是 MySQL 数据库分片,此产品曾经广为流传,据说最早的发起者对
Mysql 很精通,后来从阿里跳槽了,阿里随后开源的
Cobar,并维持到 2013 年年初,然后,就没有然后了。

Cobar 的思路和实现路径的确不错。基于
Java 开发的,实现了 MySQL 公开的二进制传输协议,巧妙地将自己伪装成一个
MySQL Server,目前市面上绝大多数 MySQL 客户端工具和应用都能兼容。比自己实现一个新的数据库协议要明智的多,因为生态环境在哪里摆着。

 

Mycat 是基于 cobar 演变而来,对 cobar 的代码进行了彻底的重构,使用 NIO 重构了网络模块,并且优化了 Buffer 内核,增强了聚合,Join 等基本特性,同时兼容绝大多数数据库成为通用的数据库中间件。

简单的说,MyCAT就是:

·一个新颖的数据库中间件产品支持mysql集群,或者mariadb cluster,提供高可用性数据分片集群。你可以像使用mysql一样使用mycat。对于开发人员来说根本感觉不到mycat的存在。

 图片 19

4.4.1 Server.xml介绍

server.xml几乎保存了所有mycat需要的系统配置信息。最常用的是在此配置用户名、密码及权限。

 

2.2 Mycat支持的数据库

 图片 20

4.4.2 Server.xml配置

<user name="test">
    <property name="password">test</property>
    <property name="schemas">e3mall</property>
    <property name="readOnly">false</property>
</user>

 

4.5 配置rule.xml 

rule.xml里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。这个文件里面主要有tableRule和function这两个标签。在具体使用过程中可以按照需求添加tableRule

和function。

此配置文件可以不用修改,使用默认即可。

2.3 Mycat的分片策略

 图片 21

 

 

 

4.6 测试分片

2.4 概念说明

4.6.1 创建表

配置完毕后,重新启动mycat。使用mysql客户端连接mycat,创建表。

-- ----------------------------
-- Table structure for tb_item
-- ----------------------------
DROP TABLE IF EXISTS `tb_item`;
CREATE TABLE `tb_item` (
  `id` bigint(20) NOT NULL COMMENT '商品id,同时也是商品编号',
  `title` varchar(100) NOT NULL COMMENT '商品标题',
  `sell_point` varchar(500) DEFAULT NULL COMMENT '商品卖点',
  `price` bigint(20) NOT NULL COMMENT '商品价格,单位为:分',
  `num` int(10) NOT NULL COMMENT '库存数量',
  `barcode` varchar(30) DEFAULT NULL COMMENT '商品条形码',
  `image` varchar(500) DEFAULT NULL COMMENT '商品图片',
  `cid` bigint(10) NOT NULL COMMENT '所属类目,叶子类目',
  `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '商品状态,1-正常,2-下架,3-删除',
  `created` datetime NOT NULL COMMENT '创建时间',
  `updated` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `cid` (`cid`),
  KEY `status` (`status`),
  KEY `updated` (`updated`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';

 

4.6.2 插入数据 

 

将此文件中的数据插入到数据库:

 图片 22

 

 

2.4.1 逻辑库(schema) :

前面一节讲了数据库中间件,通常对实际应用来说,并不需要知道中间件的存在,业务开发人员只需要知道数据库的概念,所以数据库中间件可以被看做是一个或多个数据库集群构成的逻辑库。

4.6.3 分片测试

由于配置的分片规则为“auto-sharding-long”,所以mycat会根据此规则自动分片。

每个datanode中保存一定数量的数据。根据id进行分片

经测试id范围为:

Datanode1:1~5000000

Datanode2:5000000~10000000

Datanode3:10000001~15000000

 

当15000000以上的id插入时报错:

[Err] 1064 – can’t find any valid datanode :TB_ITEM -> ID ->
15000001

此时需要添加节点了。

 

2.4.2 逻辑表(table):

既然有逻辑库,那么就会有逻辑表,分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表,可以是数据切分后,分布在一个或多个分片库中,也可以不做数据切分,不分片,只有一个表构成。

分片表:是指那些原有的很大数据的表,需要切分到多个数据库的表,这样,每个分片都有一部分数据,所有分片构成了完整的数据。
总而言之就是需要进行分片的表。

非分片表:一个数据库中并不是所有的表都很大,某些表是可以不用进行切分的,非分片是相对分片表来说的,就是那些不需要进行数据切分的表。

Mycat读写分离

数据库读写分离对于大型系统或者访问量很高的互联网应用来说,是必不可少的一个重要功能。对于MySQL来说,标准的读写分离是主从模式,一个写节点Master后面跟着多个读节点,读节点的数量取决于系统的压力,通常是1-3个读节点的配置

 图片 23

 

Mycat读写分离和自动切换机制,需要mysql的主从复制机制配合。

 图片 24

 

2.4.3 分片节点(dataNode)

数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点(dataNode)。

5.1 Mysql的主从复制

 

主从配置需要注意的地方

1、主DB server和从DB server数据库的版本一致

2、主DB server和从DB server数据库数据名称一致

3、主DB server开启二进制日志,主DB
server和从DB server的server_id都必须唯一

 

2.4.4 节点主机(dataHost)

数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost),为了规避单节点主机并发数限制,尽量将读写压力高的分片节点(dataNode)均衡的放在不同的节点主机(dataHost)。

5.2 Mysql主服务器配置

第一步:修改my.cnf文件:

在[mysqld]段下添加:

binlog-do-db=db1

binlog-ignore-db=mysql

#启用二进制日志

log-bin=mysql-bin

#服务器唯一ID,一般取IP最后一段

server-id=134

第二步:重启mysql服务

service mysqld restart

第三步:建立帐户并授权slave

mysql>GRANT FILE ON *.* TO ‘backup’@’%’ IDENTIFIED BY ‘123456’;

mysql>GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* to
‘backup’@’%’ identified by ‘123456’;

#一般不用root帐号,“%”表示所有客户端都可能连,只要帐号,密码正确,此处可用具体客户端IP代替,如192.168.145.226,加强安全。

 

刷新权限

mysql> FLUSH PRIVILEGES;

  

查看mysql现在有哪些用户

mysql>select user,host from mysql.user;

 

第四步:查询master的状态

mysql> show master status;

+——————+———-+————–+——————+——————-+

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
Executed_Gtid_Set |

+——————+———-+————–+——————+——————-+

| mysql-bin.000001 |      120 | db1          | mysql            |
                  |

+——————+———-+————–+——————+——————-+

1 row in set

 

 

 

2.4.5 分片规则(rule)

前面讲了数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。

5.3 Mysql从服务器配置

第一步:修改my.cnf文件

[mysqld]

server-id=166

 

第二步:配置从服务器

mysql>change master to
master_host=’192.168.25.128′,master_port=3306,master_user=’backup’,master_password=’123456′,master_log_file=’mysql-bin.000001′,master_log_pos=120

 

注意语句中间不要断开,master_port为mysql服务器端口号(无引号),master_user为执行同步操作的数据库账户,“120”无单引号(此处的120就是show master status 中看到的position的值,这里的mysql-bin.000001就是file对应的值)。

 

第二步:启动从服务器复制功能

Mysql>start slave;

 

第三步:检查从服务器复制功能状态:

mysql> show slave status

 

……………………(省略部分)

Slave_IO_Running: Yes //此状态必须YES

Slave_SQL_Running: Yes //此状态必须YES

……………………(省略部分)

 

注:Slave_IO及Slave_SQL进程必须正常运行,即YES状态,否则都是错误的状态(如:其中一个NO均属错误)。

 

错误处理:

如果出现此错误:

Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.

因为是mysql是克隆的系统所以mysql的uuid是一样的,所以需要修改。

解决方法:

删除/var/lib/mysql/auto.cnf文件,重新启动服务。

 

 图片 25

 

以上操作过程,从服务器配置完成。

 

Mycat的下载及安装

5.4 Mycat配置

Mycat 1.4 支持MySQL主从复制状态绑定的读写分离机制,让读更加安全可靠,配置如下:

 

<dataNode name="dn1" dataHost="localhost1" database="db1" />

<dataNode name="dn2" dataHost="localhost1" database="db2" />

<dataNode name="dn3" dataHost="localhost1" database="db3" />

<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"

writeType="0" dbType="mysql" dbDriver="native" switchType="2"  slaveThreshold="100">

<heartbeat>show slave status</heartbeat>

<writeHost host="hostM" url="192.168.25.134:3306" user="root"

    password="root">

    <readHost host="hostS" url="192.168.25.166:3306" user="root"

    password="root" />

  </writeHost>

</dataHost>

 

 

 

(1) 设置
balance=”1″与writeType=”0″

Balance参数设置:

  1. balance=“0”, 所有读操作都发送到当前可用的writeHost上。

2.
balance=“1”,所有读操作都随机的发送到readHost。

  1. balance=“2”,所有读操作都随机的在writeHost、readhost上分发

WriteType参数设置:

  1. writeType=“0”,
    所有写操作都发送到可用的writeHost上。

  2. writeType=“1”,所有写操作都随机的发送到readHost。

  3. writeType=“2”,所有写操作都随机的在writeHost、readhost分上发。

 “readHost是从属于writeHost的,即意味着它从那个writeHost获取同步数据,因此,当它所属的writeHost宕机了,则它也不会再参与到读写分离中来,即“不工作了”,这是因为此时,它的数据已经“不可靠”了。基于这个考虑,目前mycat
1.3和1.4版本中,若想支持MySQL一主一从的标准配置,并且在主节点宕机的情况下,从节点还能读取数据,则需要在Mycat里配置为两个writeHost并设置banlance=1。”

(2) 设置 switchType=”2″
与slaveThreshold=”100″

switchType 目前有三种选择:

-1:表示不自动切换

1 :默认值,自动切换

2 :基于MySQL主从同步的状态决定是否切换

“Mycat心跳检查语句配置为 show slave status ,dataHost 上定义两个新属性:
switchType=”2″
与slaveThreshold=”100″,此时意味着开启MySQL主从复制状态绑定的读写分离与切换机制。Mycat心跳机制通过检测
show slave status 中的 “Seconds_Behind_Master”, “Slave_IO_Running”,
“Slave_SQL_Running”
三个字段来确定当前主从同步的状态以及Seconds_Behind_Master主从复制时延。“

 

 

3.1 安装环境

1、jdk:要求jdk必须是1.7及以上版本

2、Mysql:推荐mysql是5.5以上版本

3、Mycat:

Mycat的官方网站:

http://www.mycat.org.cn/

下载地址:

https://github.com/MyCATApache/Mycat-download

 

附:Centos6.5下安装mysql

第一步:查看mysql是否安装。

rpm -qa|grep mysql

第二步:如果mysql的版本不是想要的版本。需要把mysql卸载。

yum remove mysql mysql-server mysql-libs mysql-common

rm -rf /var/lib/mysql

rm /etc/my.cnf

第三步:安装mysql。需要使用yum命令安装。在安装mysql之前需要安装mysql的下载源。需要从oracle的官方网站下载。

1)下载mysql的源包。

我们是centos6.4对应的rpm包为:mysql-community-release-el6-5.noarch.rpm

2)安装mysql下载源:

yum localinstall mysql-community-release-el6-5.noarch.rpm

(图片 26)此附件可保存

 图片 27

 

3)在线安装mysql:

yum install mysql-community-server

第四步:启动mysql

service mysqld start

第五步:需要给root用户设置密码。

/usr/bin/mysqladmin -u root password ‘new-password’  //
为root账号设置密码

第六步:远程连接授权。

GRANT ALL PRIVILEGES ON *.* TO ‘myuser’@’%’ IDENTIFIED BY
‘mypassword’ WITH GRANT
OPTION;

注意:’myuser’、’mypassword’ 需要替换成实际的用户名和密码。

 

3.2 安装步骤

Mycat有windows、linux多种版本。本教程为linux安装步骤,windows基本相同。

第一步:下载Mycat-server-xxxx-linux.tar.gz

第二步:将压缩包解压缩。建议将mycat放到/usr/local/mycat目录下。

第三步:进入mycat目录,启动mycat

./mycat start

停止:

./mycat stop

mycat 支持的命令{ console | start | stop | restart | status
| dump }

Mycat的默认端口号为:8066

Mycat的分片

4.1 需求

把商品表分片存储到三个数据节点上。

 

4.2 安装环境分析

两台mysql数据库服务器:

Host1:192.168.25.134

Host2:192.168.25.166

 

host1环境

操作系统版本 : centos6.4

数据库版本 : mysql-5.6

mycat版本 :1.4 release

数据库名 : db1、db3

 

 

mysql节点2环境

操作系统版本 : centos6.4

数据库版本 : mysql-5.6

mycat版本 :1.4 release

数据库名 : db2

 

MyCat安装到节点1上(需要安装jdk)

 

4.3 配置schema.xml

4.3.1 Schema.xml介绍

Schema.xml作为MyCat中重要的配置文件之一,管理着MyCat的逻辑库、表、分片规则、DataNode以及DataSource。弄懂这些配置,是正确使用MyCat的前提。这里就一层层对该文件进行解析。

 

schema 标签用于定义MyCat实例中的逻辑库

Table 标签定义了MyCat中的逻辑表

dataNode 标签定义了MyCat中的数据节点,也就是我们通常说所的数据分片。

dataHost标签在mycat逻辑库中也是作为最底层的标签存在,直接定义了具体的数据库实例、读写分离配置和心跳语句。

 

注意:若是LINUX版本的MYSQL,则需要设置为Mysql大小写不敏感,否则可能会发生表找不到的问题。

在MySQL的配置文件中/etc/my.cnf [mysqld] 中增加一行

  lower_case_table_names=1

 

4.3.2 Schema.xml配置

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/">

        <schema name="e3mall" checkSQLschema="false" sqlMaxLimit="100">
                <!-- auto sharding by id (long) -->
                <table name="tb_item" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
        </schema>
        <dataNode name="dn1" dataHost="localhost1" database="db1" />
        <dataNode name="dn2" dataHost="localhost2" database="db2" />
        <dataNode name="dn3" dataHost="localhost1" database="db3" />
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
                writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.25.134:3306" user="root"
                        password="root">
                        <!-- can have multi read hosts -->

                </writeHost>
        </dataHost>
        <dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"
                writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.25.166:3306" user="root"
                        password="root">
                        <!-- can have multi read hosts -->

                </writeHost>
        </dataHost>
</mycat:schema>

 

4.4 配置server.xml 

 

4.4.1 Server.xml介绍

server.xml几乎保存了所有mycat需要的系统配置信息。最常用的是在此配置用户名、密码及权限。

 

4.4.2 Server.xml配置

<user name="test">
    <property name="password">test</property>
    <property name="schemas">e3mall</property>
    <property name="readOnly">false</property>
</user>

 

4.5 配置rule.xml 

rule.xml里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。这个文件里面主要有tableRule和function这两个标签。在具体使用过程中可以按照需求添加tableRule

和function。

此配置文件可以不用修改,使用默认即可。

4.6 测试分片

4.6.1 创建表

配置完毕后,重新启动mycat。使用mysql客户端连接mycat,创建表。

-- ----------------------------
-- Table structure for tb_item
-- ----------------------------
DROP TABLE IF EXISTS `tb_item`;
CREATE TABLE `tb_item` (
  `id` bigint(20) NOT NULL COMMENT '商品id,同时也是商品编号',
  `title` varchar(100) NOT NULL COMMENT '商品标题',
  `sell_point` varchar(500) DEFAULT NULL COMMENT '商品卖点',
  `price` bigint(20) NOT NULL COMMENT '商品价格,单位为:分',
  `num` int(10) NOT NULL COMMENT '库存数量',
  `barcode` varchar(30) DEFAULT NULL COMMENT '商品条形码',
  `image` varchar(500) DEFAULT NULL COMMENT '商品图片',
  `cid` bigint(10) NOT NULL COMMENT '所属类目,叶子类目',
  `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '商品状态,1-正常,2-下架,3-删除',
  `created` datetime NOT NULL COMMENT '创建时间',
  `updated` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `cid` (`cid`),
  KEY `status` (`status`),
  KEY `updated` (`updated`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';

 

4.6.2 插入数据 

 

将此文件中的数据插入到数据库:

 图片 28

 

 

4.6.3 分片测试

由于配置的分片规则为“auto-sharding-long”,所以mycat会根据此规则自动分片。

每个datanode中保存一定数量的数据。根据id进行分片

经测试id范围为:

Datanode1:1~5000000

Datanode2:5000000~10000000

Datanode3:10000001~15000000

 

当15000000以上的id插入时报错:

[Err] 1064 – can’t find any valid datanode :TB_ITEM -> ID ->
15000001

此时需要添加节点了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图