All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.javaclub.cdl.client.matrix.rule.DynamicRouterStrategy Maven / Gradle / Ivy

The newest version!
package com.github.javaclub.cdl.client.matrix.rule;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.github.javaclub.cdl.client.config.DbConfigManager;

/**
 *  库表动态路由
 */
public class DynamicRouterStrategy implements RouterStrategy {
	private DbConfigManager dbConfigManager;
	private volatile DynamicRouterInfo routerInfo;
	private HashFunction hashFunction;
	private AtomicBoolean inited = new AtomicBoolean(false);

	public void init() {
		if(inited.compareAndSet(false,true)){
			updateRouter(dbConfigManager.getShardDynamicRouter(this));
		}
	}
	
	public void setDbConfigManager(DbConfigManager dbConfigManager) {
		this.dbConfigManager = dbConfigManager;
	}

	public void updateRouter(String newCfg) {
		if (StringUtils.isNotBlank(newCfg)) {
			DynamicRouterCfg dynamicRouterCfg = JSONObject.parseObject(newCfg, DynamicRouterCfg.class);
			DynamicRouterInfo dynamicRouterInfo = new DynamicRouterInfo();
			dynamicRouterInfo.setDefaultDbGroup(dynamicRouterCfg.getDefaultDbGroup());
			dynamicRouterInfo.setShardingColumn(dynamicRouterCfg.getShardingColumn());

			for (String table : dynamicRouterCfg.getShardRouterMap().keySet()) {
				Map map = new HashMap<>();
				Map shards = dynamicRouterCfg.getShardRouterMap().get(table);
				for (String group : shards.keySet()) {
					String[] ss = shards.get(group).split(",");
					for (String s : ss) {
						String[] aa = s.split("-");
						int startIndex = Integer.parseInt(aa[0]);
						int endIndex = Integer.parseInt(aa[1]);
						for (int i = startIndex; i <= endIndex; i++) {
							String actualTable = dynamicRouterCfg.getTablePrefix().get(table)
									+ SuffixParse.getTableSuffix(i, aa[0].length());
							map.put(actualTable, group);
						}
					}
				}
				List sortedActualTable = new ArrayList<>();
				sortedActualTable.addAll(map.keySet());
				Collections.sort(sortedActualTable);
				dynamicRouterInfo.getRouterMap().put(table, new HashMap());
				for (int i = 0; i < sortedActualTable.size(); i++) {
					RouterNode routerNode = new RouterNode();
					routerNode.setActualTable(sortedActualTable.get(i));
					routerNode.setGroupName(map.get(sortedActualTable.get(i)));
					dynamicRouterInfo.getRouterMap().get(table).put(i, routerNode);
				}
			}
			this.routerInfo = dynamicRouterInfo;
		}
	}

	@Override
	public Map getShardingColumn() {
		if(!inited.get()){
			throw new RuntimeException("init method not be invoked at first, check your spring bean");
		}
		return routerInfo.getShardingColumn();
	}

	@Override
	public Map getActualTable(String table, Object shardColumnValue) {
		if(!inited.get()){
			throw new RuntimeException("init method not be invoked at first, check your spring bean");
		}
		if (routerInfo.getRouterMap().get(table) == null) {
			throw new RuntimeException("not found route map for table:" + table);
		}

		int tableIndex = -1;
		
		if(hashFunction != null){
			tableIndex = hashFunction.doHash(table, shardColumnValue);
		}	
		
		if(tableIndex == -1){
			if (shardColumnValue instanceof Number) {
				Number number = (Number) shardColumnValue;
				long value = number.longValue();
				long mod = value % routerInfo.getRouterMap().get(table).size();
				tableIndex = (int) mod;
			} else {
				tableIndex = shardColumnValue.hashCode() % routerInfo.getRouterMap().get(table).size();
			}
		}
		
		RouterNode routerNode = routerInfo.getRouterMap().get(table).get(tableIndex);
		Map map = new HashMap<>();
		map.put(routerNode.getGroupName(), routerNode.getActualTable());
		return map;
	}

	@Override
	public Map> getAllActualTable(String table) {
		if(!inited.get()){
			throw new RuntimeException("init method not be invoked at first, check your spring bean");
		}
		Map> map = new HashMap<>();
		if (routerInfo.getShardingColumn().get(table) == null) {
			map.put(routerInfo.getDefaultDbGroup(), Arrays.asList(new String[] { table }));
			return map;
		}

		Map routerMap = routerInfo.getRouterMap().get(table);
		if (routerMap == null) {
			throw new RuntimeException("not found route map for table:" + table);
		}
		for (RouterNode routerNode : routerMap.values()) {
			String groupName = routerNode.getGroupName();
			if (map.get(groupName) == null) {
				map.put(groupName, new ArrayList());
			}
			if (!map.get(groupName).contains(routerNode.getActualTable())) {
				map.get(groupName).add(routerNode.getActualTable());
			}
		}
		return map;
	}

	@Override
	public void setHashFunction(HashFunction hashFunction) {
		this.hashFunction = hashFunction;
	}
	
	class DynamicRouterInfo {
		private String defaultDbGroup; // 非sharding表走默认库
		private Map> routerMap = new HashMap<>();
		private Map shardingColumn = new HashMap<>();

		public String getDefaultDbGroup() {
			return defaultDbGroup;
		}

		public void setDefaultDbGroup(String defaultDbGroup) {
			this.defaultDbGroup = defaultDbGroup;
		}

		public Map> getRouterMap() {
			return routerMap;
		}

		public void setRouterMap(Map> routerMap) {
			this.routerMap = routerMap;
		}

		public Map getShardingColumn() {
			return shardingColumn;
		}

		public void setShardingColumn(Map shardingColumn) {
			this.shardingColumn = shardingColumn;
		}
	}

	@Override
	public String getDefaultGroup() {
		return routerInfo.getDefaultDbGroup();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy