最近刚好项目要改成读写分离,使用的是mycat 但是mycat的稳定新不是很好,所以如果只是简单的读写分离还可以,如果要进行分库和分表那就有不兼容的问题存在,我们项目没有进行分库分表只是简单的读写分离,所以在这里我说一下简单的读写分离.
环境;
Mycat-server-1.4-release-20151019230038-linux.tar.gz
jdk-7u75-linux-x64.tar.gz
注:因为mycat 是Java开发的,所以必须在Java环境下运行,依赖jdk1.7及以上
- 先安装jdk1.7 配置环境变量
- 解压mycat压缩包
jdk的安装在这里就不说,之前已经说过了,
下面说mycat配置,mycat 有两个重要的配置文件 schema.xml 和 server.xml
schema.xml文件的配置:
datahost 节点中参数配置:
balance: 负载均衡类型目前有四个取值,这是源码中的给出的,其实并不是很清晰,并没有说 和writeType , switchType 之间的组合会有怎样的效果
读取负载均衡配置
1. balance="0", 不开启分离机制,所有读操作都发送到当前可用的 writeHost 上。
2. balance="1",全部的 readHost 和 stand by writeHost 参不 select 的负载均衡
3. balance="2",所有读操作都随机的在 writeHost、readhost 上分发。
4. balance="3",所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力
在这里我就直接上源码了,其实有时候看源码还是挺不错的
这是解析DataHosts 的一段源码
private void loadDataHosts(Element root) {
NodeList list = root.getElementsByTagName("dataHost");
for (int i = 0, n = list.getLength(); i < n; ++i) {
Element element = (Element) list.item(i);
String name = element.getAttribute("name");
//判断是否重复
if (dataHosts.containsKey(name)) {
throw new ConfigException("dataHost name " + name + "duplicated!");
}
//读取最大连接数
int maxCon = Integer.parseInt(element.getAttribute("maxCon"));
//读取最小连接数
int minCon = Integer.parseInt(element.getAttribute("minCon"));
/**
* 读取负载均衡配置
* 1. balance="0", 不开启分离机制,所有读操作都发送到当前可用的 writeHost 上。
* 2. balance="1",全部的 readHost 和 stand by writeHost 参不 select 的负载均衡
* 3. balance="2",所有读操作都随机的在 writeHost、readhost 上分发。
* 4. balance="3",所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力
*/
int balance = Integer.parseInt(element.getAttribute("balance"));
/**
* 读取切换类型
* -1 表示不自动切换
* 1 默认值,自动切换
* 2 基于MySQL主从同步的状态决定是否切换
* 心跳询句为 show slave status
* 3 基于 MySQL galary cluster 的切换机制
*/
String switchTypeStr = element.getAttribute("switchType");
int switchType = switchTypeStr.equals("") ? -1 : Integer.parseInt(switchTypeStr);
//读取从延迟界限
String slaveThresholdStr = element.getAttribute("slaveThreshold");
int slaveThreshold = slaveThresholdStr.equals("") ? -1 : Integer.parseInt(slaveThresholdStr);
//如果 tempReadHostAvailable 设置大于 0 则表示写主机如果挂掉, 临时的读服务依然可用
String tempReadHostAvailableStr = element.getAttribute("tempReadHostAvailable");
boolean tempReadHostAvailable = !tempReadHostAvailableStr.equals("") && Integer.parseInt(tempReadHostAvailableStr) > 0;
/**
* 读取 写类型
* 这里只支持 0 - 所有写操作仅配置的第一个 writeHost
*/
String writeTypStr = element.getAttribute("writeType");
int writeType = "".equals(writeTypStr) ? PhysicalDBPool.WRITE_ONLYONE_NODE : Integer.parseInt(writeTypStr);
String dbDriver = element.getAttribute("dbDriver");
String dbType = element.getAttribute("dbType");
String filters = element.getAttribute("filters");
String logTimeStr = element.getAttribute("logTime");
String slaveIDs = element.getAttribute("slaveIDs");
long logTime = "".equals(logTimeStr) ? PhysicalDBPool.LONG_TIME : Long.parseLong(logTimeStr) ;
//读取心跳语句
String heartbeatSQL = element.getElementsByTagName("heartbeat").item(0).getTextContent();
//读取 初始化sql配置,用于oracle
NodeList connectionInitSqlList = element.getElementsByTagName("connectionInitSql");
String initConSQL = null;
if (connectionInitSqlList.getLength() > 0) {
initConSQL = connectionInitSqlList.item(0).getTextContent();
}
//读取writeHost
NodeList writeNodes = element.getElementsByTagName("writeHost");
DBHostConfig[] writeDbConfs = new DBHostConfig[writeNodes.getLength()];
Map<Integer, DBHostConfig[]> readHostsMap = new HashMap<Integer, DBHostConfig[]>(2);
Set<String> writeHostNameSet = new HashSet<String>(writeNodes.getLength());
for (int w = 0; w < writeDbConfs.length; w++) {
Element writeNode = (Element) writeNodes.item(w);
writeDbConfs[w] = createDBHostConf(name, writeNode, dbType, dbDriver, maxCon, minCon,filters,logTime);
if(writeHostNameSet.contains(writeDbConfs[w].getHostName())) {
throw new ConfigException("writeHost " + writeDbConfs[w].getHostName() + " duplicated!");
} else {
writeHostNameSet.add(writeDbConfs[w].getHostName());
}
NodeList readNodes = writeNode.getElementsByTagName("readHost");
//读取对应的每一个readHost
if (readNodes.getLength() != 0) {
DBHostConfig[] readDbConfs = new DBHostConfig[readNodes.getLength()];
Set<String> readHostNameSet = new HashSet<String>(readNodes.getLength());
for (int r = 0; r < readDbConfs.length; r++) {
Element readNode = (Element) readNodes.item(r);
readDbConfs[r] = createDBHostConf(name, readNode, dbType, dbDriver, maxCon, minCon,filters, logTime);
if(readHostNameSet.contains(readDbConfs[r].getHostName())) {
throw new ConfigException("readHost " + readDbConfs[r].getHostName() + " duplicated!");
} else {
readHostNameSet.add(readDbConfs[r].getHostName());
}
}
readHostsMap.put(w, readDbConfs);
}
}
DataHostConfig hostConf = new DataHostConfig(name, dbType, dbDriver,
writeDbConfs, readHostsMap, switchType, slaveThreshold, tempReadHostAvailable);
hostConf.setMaxCon(maxCon);
hostConf.setMinCon(minCon);
hostConf.setBalance(balance);
hostConf.setWriteType(writeType);
hostConf.setHearbeatSQL(heartbeatSQL);
hostConf.setConnectionInitSql(initConSQL);
hostConf.setFilters(filters);
hostConf.setLogTime(logTime);
hostConf.setSlaveIDs(slaveIDs);
dataHosts.put(hostConf.getName(), hostConf);
}
}