sharding-jdbc分片策略(二)

一、在最开始提到了GroupIDAndCollectTimeDBShardingAlgorithm分库策略和CollectTimeYYYYMMDDTBShardingAlgorithm分表策略

这两个分别实现的是MultipleKeysDatabaseShardingAlgorithm实现了dosharding方法

CollectTimeYYYYMMDDTBShardingAlgorithm实现了SingleKeyTableShardingAlgorithm中的

 doEqualSharding ,doInSharding , doBetweenSharding三个方法分别匹配sql语句中的 = , in , between

具体的实现就不写了,因为分片策略不同的场景有着不同的策略,理解了自然就通了。

 

综合以上讲解:实现sharding-jdbc数据源可以分为以下流程

一、写好配置文件

    ①包括制定数据源的类,有可能是自己实现的数据源

public class SwitchableDruidDataSource extends DruidDataSource {

	private static final Logger log = LoggerFactory.getLogger(SwitchableDruidDataSource.class);
    private static int maxRetryTimes = 20;
    private static int retryInterval = 10 * 1000;

    @Override
    public Connection createPhysicalConnection() throws SQLException {
        if (!Boolean.valueOf(EmpfLocalConfigure.getValue("jdbc.ssl.switchable"))) {
            return super.createPhysicalConnection();
        }
        int retryCounter = 0;
        while (retryCounter < maxRetryTimes) {
            try {
                return super.createPhysicalConnection();
            } catch (Exception ex) {
            	log.error("createPhysicalConnection error, ", ex);
                try {
                    Thread.sleep(retryInterval);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                    LoggerFactory.getLogger(DruidDataSource.class).info("retry with url[{}] => ", retryCounter, this.getUrl());
                }
                retryCounter++;
                switchSSL();
                if (retryCounter >= maxRetryTimes) {
                    return super.createPhysicalConnection();
                }
            }
        }
        return null;
    }

    private void switchSSL() {
        if (StringUtils.indexOf(getUrl(), "useSSL=true") != -1) {
            this.setUrl(StringUtils.replace(getUrl(), "useSSL=true", "useSSL=false"));
            this.setUrl(StringUtils.replace(getUrl(), "verifyServerCertificate=true", "verifyServerCertificate=false"));
        } else if (StringUtils.indexOf(getUrl(), "useSSL=false") != -1) {
            this.setUrl(StringUtils.replace(getUrl(), "useSSL=false", "useSSL=true"));
            this.setUrl(StringUtils.replace(getUrl(), "verifyServerCertificate=false", "verifyServerCertificate=true"));
        }
    }

}

     ②写好数据源和逻辑表的分库分表策略:这个可参考前两篇文章

     二,写sharding 数据源,这个数据源要继承dangdang的shardingdatasource

public class YamlShardingDataSource extends com.dangdang.ddframe.rdb.sharding.jdbc.ShardingDataSource {

	private YamlConfig yamlConfig = null;

	public YamlShardingDataSource(final File yamlFile) throws IOException {
		// C_387386 NULL_RETURNS

		super(new ShardingRuleBuilder(yamlFile.getName(), unmarshal(yamlFile)).build(), null != unmarshal(yamlFile) ? unmarshal(yamlFile).getProps() : null);
		yamlConfig = unmarshal(yamlFile);
		LoggerFactory.getLogger(YamlShardingDataSource.class).debug("debug ==> " + yamlFile.getCanonicalPath());
	}

	private static YamlConfig unmarshal(final File yamlFile) throws IOException {
		try (FileInputStream fileInputStream = new FileInputStream(yamlFile);
				InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8")) {
			return new Yaml(new YamlShardingConstructor()).loadAs(inputStreamReader, YamlConfig.class);
		}
	}

	public YamlConfig getYamlConfig() {
		return yamlConfig;
	}
}

 其中YamlShardingConstructor:

package com.pinnet.sharding.datasource;

import com.pinnet.platform.common.configure.EmpfLocalConfigure;
import org.apache.commons.lang.StringUtils;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.ScalarNode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class YamlShardingConstructor extends Constructor {

    //yaml规范已有${},此处使用${{}}做标记
    private static final Pattern placeHolderPattern = Pattern.compile("\\$\\{\\{([^}}]+)\\}\\}");

    public YamlShardingConstructor() {
        super(YamlConfig.class);
        yamlClassConstructors.put(NodeId.scalar, new EncryptedConstructScalar());
    }

    /**
     * YAML解析插入自定义逻辑
     */
    private class EncryptedConstructScalar extends ConstructScalar {
        public Object construct(Node node) {
            if (node instanceof ScalarNode) {
                String val = (String) constructScalar((ScalarNode) node);
                //【安全特性简述】如果yaml中有${{}},则用EmpfLocalConfigure中的值替换
                Matcher matcher = placeHolderPattern.matcher(val);
                boolean replace = false;
                while (matcher.find()) {
                    replace = true;
                    val = StringUtils.replace(val, matcher.group(0), EmpfLocalConfigure.getValue(matcher.group(1)));
                }
                if (replace) {
                    return val;
                }
            }
            return super.construct(node);
        }
    }

}

 yamlconifg

            

public class YamlConfig extends ShardingRuleConfig {

    private Properties props = new Properties();

    public Properties getProps() {
        return props;
    }

    public void setProps(Properties props) {
        this.props = props;
    }
}

 

 

分片策略详解可以查看:https://blog.csdn.net/wuliusir/article/details/51090189

                                        http://lalahei.iteye.com/blog/2326061

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值