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 切換到這個其餘的數據庫。java

若是使用了 use 命令,則 mycat 會報出這樣的錯誤提示:mysql

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 或不設
表示不限制sql

例如數據庫

<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

相關文章
相關標籤/搜索