zoukankan      html  css  js  c++  java
  • SUSE12SP3-Mycat(3)Server.xml配置详解

    简介

    server.xml 几乎保存了所有 mycat 需要的系统配置信息。其在代码内直接的映射类为 SystemConfig 类。

    user 标签

    <user name="test">
    <property name="password">test</property>
    <property name="schemas">TESTDB</property>
    <property name="readOnly">true</property>
    <property name="benchmark">11111</property>
    <property name="usingDecrypt">1</property>
    <privileges check="false">
    <schema name="TESTDB" dml="0010" showTables="custome/mysql">
    <table name="tbl_user" dml="0110"></table>
    <table name="tbl_dynamic" dml="1111"></table>
    </schema>
    </privileges>
    </user>
    

    server.xml 中的标签本就不多,这个标签主要用于定义登录 mycat 的用户和权限。例如上面的例子中,我定
    义了一个用户,用户名为 test、密码也为 test,可访问的 schema 也只有 TESTDB 一个。
    如果我在 schema.xml 中定义了多个 schema,那么这个用户是无法访问其他的 schema。在 mysql 客户端看来
    则是无法使用 use 切换到这个其他的数据库。

    如果使用了 use 命令,则 mycat 会报出这样的错误提示:

    ERROR 1044 (HY000): Access denied for user 'test' to database 'xxx' 
    

    这个标签嵌套的 property 标签则是具体声明的属性值,正如上面的例子。我们可以修改 user 标签的 name
    属性来指定用户名;修改 password 内的文本来修改密码;修改 readOnly 为 true 或 false 来限制用户是否只是
    可读的;修改 schemas 内的文本来控制用户可放问的 schema;修改 schemas 内的文本来控制用户可访问的
    schema,同时访问多个 schema 的话使用 , 隔开,例如:

    <property name="schemas">TESTDB,db1,db2</property>
    

    Benchmark 属性

    Benchmark:mycat 连接服务降级处理:
    benchmark 基准, 当前端的整体 connection 数达到基准值是, 对来自该账户的请求开始拒绝连接,0 或不设
    表示不限制

    例如

     <property name="benchmark">1000</property>
    

    usingDecrypt 属性

    是否对密码加密默认 0 否 如需要开启配置 1,同时使用加密程序对密码加密,加密命令为:
    执行 mycat jar 程序:
    java -cp Mycat-server-1.4.1-dev.jar io.mycat.util.DecryptUtil 0:user:password
    Mycat-server-1.4.1-dev.jar 为 mycat download 下载目录的 jar
    1:host:user:password 中 0 为前端加密标志

    privileges 子节点

    对用户的 schema 及 下级的 table 进行精细化的 DML 权限控制,privileges 节点中的 check 属性是用
    于标识是否开启 DML 权限检查, 默认 false 标识不检查,当然 privileges 节点不配置,等同 check=false, 由于 Mycat 一个用户的 schemas 属性可配置多个 schema ,所以 privileges 的下级节点 schema 节点同样
    可配置多个,对多库多表进行细粒度的 DML 权限控制Schema/Table 上的 dml 属性描述

    参数 说明 事例(禁止增删改查)
    dml insert,update,select,delete 0000

    注: 设置了 schema , 但只设置了个别 table 或 未设置 table 的 DML,自动继承 schema 的 DML 属性

    <user name="zhuam">
    <property name="password">111111</property>
    <property name="schemas">TESTDB,TESTDB1</property>
    <!-- 表级权限: Table 级的 dml(curd)控制,未设置的 Table 继承 schema 的 dml -->
    <!-- TODO: 非 CURD SQL 语句, 透明传递至后端 -->
    <privileges check="true">
    <schema name="TESTDB" dml="0110" >
    <table name="table01" dml="0111"></table>
    <table name="table02" dml="1111"></table>
    </schema>
    <schema name="TESTDB1" dml="0110">
    <table name="table03" dml="1110"></table>
    <table name="table04" dml="1010"></table>
    </schema>
    </privileges>
    </user>
    

    system 标签

    这个标签内嵌套的所有 property 标签都与系统配置有关,请注意,下面我会省去标签 property 直接使用这
    个标签的 name 属性内的值来介绍这个属性的作用。

    charset 属性

    字符集设置。

    配置属性 charset
    <system> <property name="charset">utf8</property> </system>
    如果需要配置 utf8mb2 等特殊字符集可以在
    index_to_charset.properties 配置中
    配置数据库短的字符集 ID=字符集
    例如:
    224=utf8mb4
    配置字符集的时候一定要坚持 mycat 的字符集与数据库端的字符集是一致的,可以通过变量来查询:
    show variables like 'collation_%';
    show variables like 'character_set_%';
    

    defaultSqlParser 属性

    由于 mycat 最初是时候 Foundation DB 的 sql 解析器,而后才添加的 Druid 的解析器。所以这个属性用来
    指定默认的解析器。目前的可用的取值有:druidparser 和 fdbparser。使用的时候可以选择其中的一种,目前一
    般都使用 druidparser。
    1.3 解析器默认为 fdbparser,1.4 默认为 druidparser,1.4 以后 fdbparser 作废。

    processors 属性

    这个属性主要用于指定系统可用的线程数,默认值为机器 CPU 核心线程数。
    主要影响 processorBufferPool、processorBufferLocalPercent、processorExecutor 属性。
    NIOProcessor 的个数也是由这个属性定义的,所以调优的时候可以适当的调高这个属性。

    processorBufferChunk属性

    这个属性指定每次分配Socket Direct Buffer的大小,默认是4096个字节。这个属性也影响buffer pool的
    长度。如果一次性获取的数过大buffer不够用 经常出现警告,则可以适当调大

    processorBufferPool属性

    这个属性指定bufferPool计算 比例值。由于每次执行NIO读、写操作都需要使用到buffer,系统初始化的
    时候会建立一定长度的buffer池来加快读、写的效率,减少建立buffer的时间。
    Mycat中有两个主要的buffer池:

    • BufferPool
    • ThreadLocalPool

    BufferPool由ThreadLocalPool组合而成,每次从BufferPool中获取buffer都会优先获取
    ThreadLocalPool中的buffer,未命中之后才会去获取BufferPool中的buffer。也就是说ThreadLocalPool是
    作为BufferPool的二级缓存,每个线程内部自己使用的。当然,这其中还有一些限制条件需要线程的名字是由$_
    开头。然而,BufferPool上的buffer则是每个NIOProcessor 都共享的。
    默认这个属性的值为: 默认bufferChunkSize(4096) * processors 属性 * 1000
    BufferPool 的总长度 = bufferPool / bufferChunk。
    若bufferPool不是bufferChunk的整数倍,则总长度为前面计算得出的商 + 1
    假设系统线程数为4,其他都为属性的默认值,则:
    bufferPool = 4096 * 4 * 1000
    BufferPool的总长度 : 4000 = 16384000 / 4096

    processorBufferLocalPercent属性

    前面提到了ThreadLocalPool。这个属性就是用来控制分配这个pool的大小用的,但其也并不是一个准确
    的值,也是一个比例值。这个属性默认值为100。
    线程缓存百分比 = bufferLocalPercent / processors 属性。
    例如,系统可以同时运行4个线程,使用默认值,则根据公式每个线程的百分比为25。最后根据这个百分比
    来计算出具体的ThreadLocalPool的长度公式如下:
    ThreadLocalPool的长度 = 线程缓存百分比 * BufferPool长度 / 100
    假设BufferPool的长度为 4000,其他保持默认值。
    那么最后每个线程建立上的ThreadLocalPool的长度为: 1000 = 25 * 4000 / 100

    processorExecutor属性

    这个属性主要用于指定NIOProcessor上共享的businessExecutor固定线程池大小。mycat在需要处理一
    些异步逻辑的时候会把任务提交到这个线程池中。新版本中这个连接池的使用频率不是很大了,可以设置一个较
    小的值。

    sequnceHandlerType属性

    指定使用Mycat 全局序列的类型。0为本地文件方式,1为数据库方式,2为时间戳序列方式,3为分布式
    ZK ID生成器,4为zk递增id生成。
    从1.6增加 两种ZK的全局ID生成算法。

    TCP连接相关属性

    StandardSocketOptions.SO_RCVBUF

    • StandardSocketOptions.SO_SNDBUF
    • StandardSocketOptions.TCP_NODELAY

    以上这三个属性,分别由:

    frontSocketSoRcvbuf 默认值: 1024 * 1024

    frontSocketSoSndbuf 默认值: 4 * 1024 * 1024

    frontSocketNoDelay 默认值: 1

    backSocketSoRcvbuf 默认值: 4 * 1024 * 1024

    backSocketSoSndbuf 默认值: 1024 * 1024

    backSocketNoDelay 默认值: 1

    各自设置前后端TCP 连接参数。Mycat在每次建立前、后端连接的时候都会使用这些参数初始化连接。可以
    按系统要求适当的调整这些buffer的大小。TCP 连接参数的定义,可以查看Javadoc。

    Mysql连接相关属性

    初始化mysql前后端连接所涉及到的一些属性:
    packetHeaderSize : 指定Mysql协议中的报文头长度。默认 4。
    maxPacketSize : 指定Mysql协议可以携带的数据最大长度。默认16M。
    idleTimeout : 指定连接的空闲超时时间。某连接在发起空闲检查下,发现距离上次使用超过了空闲时间,那
    么这个连接会被回收,就是被直接的关闭掉。默认30分钟,单位毫秒。
    charset : 连接的初始化字符集。默认为utf8。
    txIsolation : 前端连接的初始化事务隔离级别,只在初始化的时候使用,后续会根据客户端传递过来的属性对
    后端数据库连接进行同步。默认为REPEATED_READ,设置值为数字默认3。
    READ_UNCOMMITTED = 1; READ_COMMITTED = 2; REPEATED_READ = 3; SERIALIZABLE = 4;
    sqlExecuteTimeout:SQL执行超时的时间,Mycat会检查连接上最后一次执行 SQL的时间,若超过这个时
    间则会直接关闭这连接。默认时间为300秒,单位秒

    心跳属性

    mycat中有几个周期性的任务来异步的处理一些我需要的工作。这些属性就在系统调优的过程中也是比不可
    少的。

    processorCheckPeriod : 清理NIOProcessor上前后端空闲、超时和关闭连接的间隔时间。默认是1秒,单
    位毫秒。。

    dataNodeIdleCheckPeriod : 对后端连接进行空闲、超时检查的时间间隔,默认是300秒,单位毫秒。

    dataNodeHeartbeatPeriod : 对后端所有读、写库发起心跳的间隔时间,默认是10秒,单位毫秒。

    服务相关属性

    这里介绍一个与服务相关的属性,主要会影响外部系统对mycat的感知。

    bindIp : mycat服务监听的IP地址,默认值为0.0.0.0。

    serverPort : 定义mycat 的使用端口,默认值为8066。

    managerPort : 定义mycat 的管理端口,默认值为9066。

    f a k e M y S Q L V e r s i o n

    mycat模拟的mysql 版本号,默认值为5.6版本,如非特需,不要修改这个值,目前支持设置 5.5,5.6版本,其
    他版本可能会有问题。
    此特性从 1.6 版本开始支持

    全局表一致性检测

    <property name="useGlobleTableCheck">0</property>
    

    < ! - - 1 为 开 启 全 加 班 一 致 性 检 测 、 0 为 关 闭 - - > 原理通过在全局表增加_MYCAT_OP_TIME字段来进行一致性检测,类型为 bigint,create 语句通过mycat 执行会自动加上这个字段,其他情况请自己手工添加。 此特性从 1.6 版本开始支持。

    “增加 mycat 新任务,全局表定义中,需要有一个时间戳字段,每次记录的 update,insert,确保
    时间字段赋值,并且 mycat 增加定时检测逻辑,检测记录总量,以及最新时间戳的匹配,简单
    有效的发现全局表不一致的问题。/ 测试修复类 / 1.5&2.0 /12.9 /leader-us”
    全局表一致性定时检测主要分为两个部分:

    1.SQL 拦截部分

    主要实现对所有全局表中记录进行修改的语句进行拦截,比如:
    ServerParse.INSERT,
    ServerParse.UPDATE,
    ServerParse.REPLACE(mycat-server 不支持)
    对所有对全局表的 insert, update 操作进行拦截,首先判断该全局表是否存在一个记录时间戳
    的内部列_mycat_op_time:
    public class GlobalTableUtil{
    /** 全局表 保存修改时间戳的字段名,用于全局表一致性检查 */

    public static final String GLOBAL_TABLE_MYCAT_COLUMN = "_mycat_op_time";
    

    如果不存在,输出警告,哪个 db 的哪个全局表没有内部列:

    if(innerColumnNotExist.size() > 0){
    for(SQLQueryResult<Map<String, String>> map : innerColumnNotExist){
    if(tableName.equalsIgnoreCase(map.getTableName())){
    StringBuilder warnStr = new StringBuilder();
    if(map != null) warnStr.append(map.getDataNode()).append(".");
    warnStr.append(tableName).append(" inner column: ") .append(GlobalTableUtil.GLOBAL_TABLE_MYCAT_COLUMN)
    .append(" is not exist.");
    LOGGER.warn(warnStr.toString());
    return sql;
    }
    }
    }
    

    然后返回原始 sql. 不需要进行拦截。
    如果存在一个记录时间戳的内部列,那么对该 insert 或者 update 语句进行 SQL 拦截修改:

    if(sqlType == ServerParse.INSERT){
    sql = convertInsertSQL(sql, tableName);
    }
    if(sqlType == ServerParse.UPDATE){
    sql = convertUpdateSQL(sql, tableName);
    }
    

    1.1 insert语句的拦截逻辑

    对所有对全局表进行insert的sql语句,进行改写,比如下面的user是全局表:

    insert into user(id,name)
    valueS(1111,'dig'),
    (1111, 'dig'),
    (1111,'dig') ,
    (1111,'dig');
    

    会被改写成:

    insert into user(id,name, _mycat_op_time)
    valueS(1111,'dig', 1450423751170),
    (1111, 'dig', 1450423751170),
    (1111,'dig', 1450423751170) ,
    (1111,'dig', 1450423751170);
    

    其中_mycat_op_time 是内部列的名称:

    public static final String GLOBAL_TABLE_MYCAT_COLUMN = "_mycat_op_time";
    

    而1450423751170 是在插入时在 mycat-server上生成的一个时间戳对应的long整数(对应到数据库 是bigint)。然后该语句发送给所有db在其全局表中进行插入。
    如果insert语句自带了内部列_mycat_op_time,比如:

    insert into user(id,name, _mycat_op_time)
    valueS(1111,'dig',13545);
    

    那么会输出警告,并且也进行拦截改写成如下形式:

    insert into user(id,name, _mycat_op_time)
    valueS(1111,'dig', 1450423751170);
    

    然后发送给所有db在其全局表中进行插入。
    对mycat-server不支持的sql语句,本拦截器,不进行任何操作,直接返回原始sql。如果在拦截过 程中发生任何异常,也返回原始sql语句,不进行任何修改操作。保证该拦截不会影响系统原 有的健壮性。

    1.2 update语句的拦截逻辑

    Update语句的拦截逻辑和insert语句原理是相似的。也是判断是否有内部列。
    如果没有输出警告信息,如果有则进行拦截。
    对全局表 user 的如下update:

    update user set name='dddd',pwd='aaa'
    where id=2
    

    会被改写成:

    update user set name='dddd',pwd='aaa', _mycat_op_time=1450423751170 where id=2
    

    如果原始sql带有_mycat_op_time 那么进行警告,然后替换它的值,比如:

    update user set name='dddd',pwd='aaa', _mycat_op_time=1111
    where id=2;
    

    会被改写成:

    update user set name='dddd',pwd='aaa', _mycat_op_time=1450423751170 where id=2;
    

    然后将语句发送给所有的全局表进行执行。
    这样的话,如果有哪个表上的insert,update执行失败,那么内部列_mycat_op_time 的最大值,以 及全局表的记录总数就会不一致。Delete语句也一样,只是无需拦截。下面的检查机制就是根 据这个原理来操作的。

    2.一致性的定时检测

    在MycatServer的startup中引入一个定时检查任务:

    timer.schedule(glableTableConsistencyCheck(), 0L, 1000 * 1000L);
    // 全局表一致性检查任务
    private TimerTask glableTableConsistencyCheck() {
    return new TimerTask() {
    @Override
    public void run() {
    timerExecutor.execute(new Runnable() {
    @Override
    public void run() {
    GlobalTableUtil.consistencyCheck();
    }
    });
    }
    };
    

    其实现在GlobalTableUtil 类中:
    该类首先获得所有的全局表:

    static {
    getGlobalTable(); // 初始化 globalTableMap
    }
    

    其实现,参见代码。
    GlobalTableUtil.consistencyCheck() 的实现,主要思路是,首先根据所有的全局表,找到对应的 PhysicalDBNode,然后找到对应的PhysicalDatasource,然后对PhysicalDatasource中的所有 db进行三项检测:

    2.1 检测全局表的内部列是否存在

    checker.checkInnerColumnExist();
    检测的实现是通过一个SQLJob来异步操作的,对应的SQL语句为:

    select count(*) as inner_col_exist from information_schema.columns where column_name=' _mycat_op_time' and table_name='user' and table_schema='db1';
    

    如果返回的inner_col_exist 大于0,那么就表示存在内部列,如果等于0,那么就表示不存在内部 列。
    如果PhysicalDatasource上某个db的全局表没有内部列,那么将这些db记录在一个list中,然后在 SQL 拦截过程中进行判断,如果是全局表,但是没有内部列,那么就输出警告,不对SQL进行 拦截改写,因为该全局表没有内部列,无需改写SQL。在第一项检测完成之后,才能进行第二 项检测。

    2.2 检测全局表的记录总数

    checker.checkRecordCout();
    检查过程是类似的,都是通过SQLjob来完成的,只是对应的语句不一样:
    select count(*) as record_count from user; (假设user表为全局表)

    2.3 检测全局表的时间戳的最大值

    checker.checkMaxTimeStamp();
    检查过程是类似的,都是通过SQLjob来完成的,只是对应的语句不一样:
    select max(_mycat_op_time) as max_timestamp from user (假设user表为全局表)
    三项检查完成之后,就获得了如下所示的结果:
    全局表的记录总数(user表为全局表,并且系统有三个db):

    db1. user.record_count: 43546565
    db2. user.record_count: 43546565
    db3. user.record_count: 43546565
    全局表的最大时间戳:

    db1. user.max_timestamp: 1450578802241
    db2. user.max_timestamp: 1450578802241
    db3. user.max_timestamp: 1450578802241

    然后前端,比如 mycat-eye 就可以将该结果显示出来。目前直接在log中输出,也可以考虑引入像 H2这样的Java实现的嵌入式数据库来记录该结果。H2实现为仅仅一个jar包,十分适合作为 mycat-server层面的一个非文件存储方式。有一些信息如果存在在文件中,查询起来不太方 便,比如上面的检测结果就是如此。
    实际的SQLJob的执行,主要参照了原有的heartbeat的实现,主要在下面两个类中:
    MySQLConsistencyChecker
    MySQLConsistencyHelper
    具体可以参考代码,和heartbeat的实现基本是一样的。
    每一次定时检查,会对所有全局表进行上述三项检测。
    总结成一句:
    SQL的拦截实现记录全局表被修改时的时间戳;定时任务实现对全局表记录总数和时间戳最大值的获 取。

    3.如何使用全局表一致性检测

    1> 在所有全局表中增加一个 bigint 的内部列,列名为 _mycat_op_time,(alter table t add column _mycat_op_time bigint [not null default 0]); 同时建议在该列上建立索引(alter table t add index _op_idx(_mycat_op_time)) 2> 在对全局表进行crud时,最好将内部列当作不存在一样,也就是最好不要对内部列 update,insert等操作,不然会在Log中进行警告:不用操作内部列; 3> 因为全局表多了一个内部列,所以在对全局表进行insert时,必须携带列名,也就是insert into t(id,name) values(xx,xx),不能使用insert into t values(xx,xx); 因为会报错:列数 不对。这是唯一的一个小问题。未来可能会fix掉。
    7.9.15 分 布 式 事 务 开 关
    < ! - - 分 布 式 事 务 开 关 , 0 为 不 过 滤 分 布 式 事 务 , 1 为 过 滤 分 布 式 事 务 ( 如 果 分 布 式 事 务 内 只 涉 及 全 局 表 , 则 不 过 滤 ) , 2 为 不 过 滤 分 布 式 事 务,但 是 记 录 分 布 式 事 务 日 志 - - > 0
    主要应用场景,主要为了控制是否允许跨库事务。
    此特性从 1.6 版本开始支持。

    Off Heap for Mycat

    此特性从 1.6 版本开始支持。
    < ! - o f f h e a p f o r m e r g e / o r d e r / g r o u p / li m it 1 开 启 0 关 闭 - - > 1

    1. 使用非堆内存(Direct Memory)处理跨分片结果集的Merge/order by/group by/limit。

    2. 通过server.xml中的 useOffHeapForMerge参数配置是否启用非堆内存处理跨分片结果集

    3. Mycat内存分层管理:

      a.结果集处理内存;

      b.系统预留内存;

      c.网络处理内存共三块。

    其中网络处理内存部分全部为Direct Memory,结果集内存分为Direct Memory 和 HeapMemory。
    但目前仅使用Direct Memory。系统预留内存为 On Heap Memory。JVM 参数,必须设置
    XX:MaxDirectMemorySize和 -Xmx
    例如:-Xmx1024m -Xmn512m -XX:MaxDirectMemorySize=2048m -Xss256K -XX:+UseParallelGC
    上述分层可以避免OOM问题,以及减少Full GC回收时间,提高mycat响应速度。

    1. 使用TimeSort 和RadixSort,跨分片结果集合并排序使用PriorityQueue,其中经测试RadixSort适合
      LONG,INT,SHORT,Float,Double,String数据类型排序,性能优越。

    2. Java obj连续内存存取,二进制序列化和反序列化,使用缓存友好的数据结构Map和Row。

    3. 支持内存和外存并存的排序方式,结果集排序可以达上亿规模。此时应注意:

      a. 此时前端和后端空闲连接超时检测时间应该设置大些,避免空闲检测关闭front或者backend
      connection,造成Mysqlclient连接丢失时结果集无法正确。
      b. 设置-Xmn值尽可能大些,新生代使用UseParallelGC 垃圾回收器,-Xss设置512K 比较合适,物理内
      存足够时,MaxDirectMemorySize 尽可能设置大些,可以加快结果集处理时间,
      例如:-Xmx1024m -Xmn512m -XX:MaxDirectMemorySize=2048m -Xss256k -XX:+UseParallelGC。

    http://www.mycat.io/document/mycat-definitive-guide.pdf

  • 相关阅读:
    ubuntu配置服务器环境
    discuz安装与学习资料
    前端面试题总结(一)
    css公共样式,初始化
    js的解析--预处理(三)
    sass的安装与基础
    移动开发学习笔记(一) 移动开发的注意事项
    移动前端一些常用的框架
    JavaScript的构造器与对象(二)
    JavaScript 中的Object的使用详解笔记(一)
  • 原文地址:https://www.cnblogs.com/hanfan/p/10725551.html
Copyright © 2011-2022 走看看