我们在做数据库 sharding 的时候不需要参考这一原则,这一原则主要是为了程序内部 hash 表使用,外部我们本来就是要 hash mod 确定 sharding node 。
通过 mod 取模的方式会出现不均匀问题,在此基础上可以做个 自定义奇偶路由,这样可以均匀两边的数据。
一些注意事项1.在现有项目中集成 sharding-JDBC 有一些小问题,sharding-jdbc 不支持批量插入,如果项目中已经使用了大量的批量插入语句就需要改造,或者使用 辅助hash计算物理表名,在批量插入。
2.原有项目数据层使用 Druid + MyBatis,集成了 sharding-JDBC 之后 sharding-JDBC包装了 Druid ,所以一些 sharding-JDBC 不支持的sql语句基本就过不去了。
3.使用 springboot 集成 sharding-JDBC 的时候,在bean加载的时候我需要设置 IncrementIdGenerator ,但是出现classloader问题。
IncrementIdGenerator incrementIdGenerator = this.getIncrementIdGenerator(dataSource); ShardingRule shardingRule = shardingRuleConfiguration.build(dataSourceMap); ((IdGenerator) shardingRule.getDefaultKeyGenerator()).setIncrementIdGenerator(incrementIdGenerator); private IncrementIdGenerator getIncrementIdGenerator(DataSource druidDataSource) { ... }后来发现 springboot的类加载器使用的是 restartclassloader,所以导致转换一直失败。只要去掉 spring-boot-devtools package即可,restartclassloader 是为了热启动。
4.dao.xml 逆向工程问题,我们使用的很多数据库表mybatis生成工具生成的时候都是物理表名,一旦我们使用了sharding-JDCB之后都是用的逻辑表名,所以生成工具需要提供选项来设置逻辑表名。
5.为 mybatis 提供的 SqlSessionFactory 需要在Druid的基础上用shading-JDCB包装下。
6.sharding-JDBC DefaultkeyGenerator 默认采用是 snowflake 算法,但是我们不能直接用我们需要根据 datacenterid-workerid 自己配合zookeeper来设置 workerId 段。
(snowflake workId 10 bit 十进制 1023,dataCenterId 5 bit 十进制 31 、WorkId 5 bit 十进制 31)
7.由于我们使用的是 mysql com.mysql.jdbc.ReplicationDriver 自带的实现读写分离,所以处理读写分离会方便很多。如果不是使用的这种就需要手动设置 Datasource Hint 来处理。
8.在使用 mybatis dao mapper 的时候需要多份逻辑表,因为有些数据源数据表是不需要走sharding的,自定义shardingStragety 来处理分支逻辑。
9 全局id几种方法
9.1 如果使用 zookeeper 来做分布式ID,就要注意 session expired 可能会存在重复 workid 问题,加锁或者接受一定程度的并行(有序列号保证一段时间空间)。
9.2.采用集中发号器服务,在主DB中采用预生成表+incrment 插件(经典取号器实现,innodb 存储引擎中的 TRX_SYS_TRX_ID_STORE 事务号也是这种方式)
9.3.定长发号器、业务规则发号器,这种需要业务上下文的发号器实现都需要预先配置,然后每次请求带上获取上下文来说明获取业务类型
10.在项目中有些地方使用了自增id排序,数据表拆分之后就需要进行改造,因为ID大小顺序已经不存在了。根据数据的最新排序时使用了id排序需要改造成用时间字段排序。