千家信息网

Mycat 连接池模型源码

发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,PhysicalDBNode 是Mycat集群(Datanode)的对应,引用一个连接池对象 PhysicalDBPool,PhysicalDBPool 里面引用了真正的连接池对象 PhysicalD
千家信息网最后更新 2025年01月20日Mycat 连接池模型源码

PhysicalDBNode 是Mycat集群(Datanode)的对应,引用一个连接池对象 PhysicalDBPool,
PhysicalDBPool 里面引用了真正的连接池对象 PhysicalDatasource,PhysicalDBPool 里面把该
集群的读节点,写节点写入各自的 PhysicalDatasource 数组,通过负载均衡决定走哪个节点
负载均衡策略:随机选择,按权重设置随机概率
代码:randomSelect
节点权重计算公式String weightStr = node.getAttribute("weight");
int weight = "".equals(weightStr) ? PhysicalDBPool.WEIGHT : Integer.parseInt(weightStr) ;
负载均衡:offset -= okSources.get(i).getConfig().getWeight();
没明白为什么这么分配,难道可用达到权重越大,分配可能性越小???

public PhysicalDatasource randomSelect(ArrayList okSources) {   if (okSources.isEmpty()) {      return this.getSource();   } else {            int length = okSources.size();     // 总个数        int totalWeight = 0;         // 总权重        boolean sameWeight = true;        // 权重是否都一样        for (int i = 0; i < length; i++) {                        int weight = okSources.get(i).getConfig().getWeight();            totalWeight += weight;        // 累计总权重                           if (sameWeight && i > 0                   && weight != okSources.get(i-1).getConfig().getWeight() ) {      // 计算所有权重是否一样                                              sameWeight = false;                }        }        if (totalWeight > 0 && !sameWeight ) {           // 如果权重不相同且权重大于0则按总权重数随机            int offset = random.nextInt(totalWeight);            // 并确定随机值落在哪个片断上            for (int i = 0; i < length; i++) {                offset -= okSources.get(i).getConfig().getWeight();                if (offset < 0) {                    return okSources.get(i);                }            }        }        // 如果权重相同或权重为0则均等随机        return okSources.get( random.nextInt(length) );          //int index = Math.abs(random.nextInt()) % okSources.size();      //return okSources.get(index);   }}

PhysicalDatasource 连接池对象保存该连接的可用连接使用的数据结构是,ConMap,主要功能是获取当前节点的可用连接,首先从当前database上获取可用连接,如果没有,则从其他 database 上获取可用连接

public BackendConnection tryTakeCon(final String schema, boolean autoCommit) {   final ConQueue queue = items.get(schema);   BackendConnection con = tryTakeCon(queue, autoCommit);   if (con != null) {      return con;   } else {      for (ConQueue queue2 : items.values()) {         if (queue != queue2) {            con = tryTakeCon(queue2, autoCommit);            if (con != null) {               return con;            }         }      }   }   return null;}
private BackendConnection tryTakeCon(ConQueue queue, boolean autoCommit) {   BackendConnection con = null;   if (queue != null && ((con = queue.takeIdleCon(autoCommit)) != null)) {      return con;   } else {      return null;   }}

database的可用连接是存放在数据结构ConQueue中的,可用连接分为自动提交,手动提交,所以ConQueue由2个ConcurrentLinkedQueue组成,autoCommitCons 自动提交队列,manCommitCons 手动提交队列
分配可用连接:先从提交方式队列队首分配,分配失败,从另一个队列分配,分配失败,从其他databse 分配。猜想:此处分配完成应该不是最种的可用连接,还需要做事务隔离级别、事务模式、字符集、Database 等等处理和校验,才能执行具体的 sql 指令,这些应该是在MySQLConnection 类中进行的

public BackendConnection takeIdleCon(boolean autoCommit) {   ConcurrentLinkedQueue f1 = autoCommitCons;   ConcurrentLinkedQueue f2 = manCommitCons;   if (!autoCommit) {      f1 = manCommitCons;      f2 = autoCommitCons;   }   BackendConnection con = f1.poll();   if (con == null || con.isClosedOrQuit()) {      con = f2.poll();   }   if (con == null || con.isClosedOrQuit()) {      return null;   } else {      return con;   }}
0