- 浏览: 68248 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
Alex_Cheung:
对了,第二个没有提取码,请知悉。
一大波视频分享 -
Alex_Cheung:
谢谢分享。
一大波视频分享 -
Jiy:
很详细,谢谢分享
java并发之同步辅助类Phaser -
walle1027:
非常不错,学习了。
java并发之同步辅助类Phaser -
huangjinjin520:
somefuture 写道除了单词写错了 其他挺好的已更正
dubbo注解使用详解
你们团队使用SpringMVC+Spring+JPA框架,快速开发了一个NB的系统,上线后客户订单跟雪花一样纷沓而来。
慢慢地,你的心情开始变差,因为客户和产品的抱怨越来越频繁,抱怨的最多的一个问题就是:系统越来越慢了。
1 常规优化
你组织团队,进行了一系列的优化。
1.1 数据表索引优化
经过初步分析,发现瓶颈在数据库。WEB服务器的CPU闲来无事,但数据库服务器的CPU使用率高居不下。
于是,请来架构组的DBA同事,监控数据库的访问,整理出那些耗时的SQL,并且进行SQL查询分析。根据分析结果,对数据表索引进行重新整理。同时也对数据库本身的参数设置进行了优化。
优化后,页面速度明显提升,客户抱怨减少,又过了一段时间的安逸日子。
1.2 多点部署+负载均衡
慢慢的,访问速度又不行了,这次是WEB服务器压力很大,数据库服务器相对空闲。经过分析,发现是系统并发用户数太多,单WEB服务器不能够支持如此众多的并发请求。
于是,请架构协助进行WEB多点部署,前端使用nginx做负载分发。这时候必须要解决的一个问题就是用户会话保持的问题。这可以有几种不同解决方案:
1、nginx实现sticky分发
因为nginx缺省没有sticky机制,可以使用ip_hash方式来代替。
2、配置Tomcat实现Session复制
3、代码使用SpringSession,利用redis实现session复制。
具体做法就不一一介绍了。其中使用SpringSession的方法,可以参考我的文章《集群环境CAS的问题及解决方案》。
2 试用当当的Sharding JDBC框架
多点部署之后,系统又运行了一段时间,期间增加了更多的WEB节点,基本能应对客户需求。慢慢的,增加WEB服务器也不能解决问题了,因为系统瓶颈又回到了数据库服务器。SQL执行时间越来越长,而且无法优化。原因也很简单,数据量太大。
单表数据已经超过几千万行,通过数据库的优化已经不能满足速度的要求。分库分表提到了日程上,必须解决。
因为使用了JPA,如果分库分表需要对数据访问层做较大的改动,工作量太大,修改的风险也太高。恰好看到当当开源了其Sharding-JDBC组件,摘抄一段介绍:
https://github.com/dangdangdotcom/sharding-jdbc
Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零:
可适用于任何基于java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
可基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid等。
理论上可支持任意实现JDBC规范的数据库。虽然目前仅支持MySQL,但已有支持Oracle,SQLServer,DB2等数据库的计划。
它支持JPA,可以在几乎不修改代码的情况下完成分库分表的实现。因此,选择这个框架做一次分库分表的尝试。
先做一个最简单的试用,不做分库,仅做分表。选择数据表operate_history,这个数据表记录所有的操作历史,是整个系统中数据量最大的一个数据表。
希望将这个表拆分为四个数据表,分别是 operate_history_0operate_history_1 operate_history_2 operate_history_3。数据能够分配保存到四个数据表中,降低单表的数据量。同时,为了尽量减少跨表的查询操作,决定使用字段 entity_key为分表依据,这样同一个entity对象的所有操作,将会记录在同一个数据表中。拆分后的数据表结构为:
3 实现过程
以下是针对JPA项目的修改过程。其他项目请参考官方网站的文档。
3.1 修改pom.xml增加dependency
需要添加两个jar,sharding-jdbc-core和sharding-jdbc-config-spring。
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-config-spring</artifactId>
<version>1.3.0</version>
</dependency>
3.2 修改Spring中Database部分的配置
原Database配置
<bean id="dataSource"class="org.apache.tomcat.jdbc.pool.DataSource"destroy-method="close">
<propertyname="driverClassName"value="com.mysql.jdbc.Driver"></property>
<propertyname="url" value="jdbc:mysql://localhost:3306/sharding"></property>
<propertyname="username" value="root"></property>
<propertyname="password" value="sharding"></property>
</bean>
修改后的配置
<beanid="db-node-0"class="org.apache.tomcat.jdbc.pool.DataSource"destroy-method="close">
<property name="driverClassName"value="com.mysql.jdbc.Driver"></property>
<property name="url"value="jdbc:mysql://localhost:3306/sharding"></property>
<property name="username"value="root"></property>
<property name="password"value="sharding"></property>
</bean>
<rdb:strategyid="historyTableStrategy"
sharding-columns="entity_key"
algorithm-class="cn.codestory.sharding.SingleKeyTableShardingAlgorithm"/>
<rdb:data-sourceid="dataSource">
<rdb:sharding-ruledata-sources="db-node-0"default-data-source="db-node-0">
<rdb:table-rules>
<rdb:table-rulelogic-table="operate_history"
actual-tables="operate_history_0,operate_history_1,operate_history_2,operate_history_3"
table-strategy="historyTableStrategy" />
</rdb:table-rules>
</rdb:sharding-rule>
</rdb:data-source>
3.3 编写类SingleKeyTableShardingAlgorithm
这个类用来根据entity_key值确定使用的分表名。参考sharding提供的示例代码进行修改。核心代码如下
publicCollection<String> doInSharding(
Collection<String>availableTargetNames,
ShardingValue<Long>shardingValue) {
int targetCount = availableTargetNames.size();
Collection<String> result = newLinkedHashSet<>(targetCount);
Collection<Long> values =shardingValue.getValues();
for (Long value : values) {
for (String tableNames :availableTargetNames) {
if (tableNames.endsWith(value % targetCount+ "")) {
result.add(tableNames);
}
}
}
return result;
}
这是一个简单的实现,对entity_key进行求模,用余数确定数据表名。
3.4 修改主键生成方法
因为数据分表保存,不能使用identify方式生成数据表主键。如果主键是String类型,可以考虑使用uuid生成方法,但它查询效率会相对比较低。
如果使用long型主键,可以使用其他方式,一定要确保各个子表中的主键不重复。
3.5 历史数据的处理
根据数据分表的规则,需要对原有数据包的数据进行迁移,分别移动到四个数据表中。如果不做这一步,或者数据迁移到了错误的数据表,后续将会查询不到这些数据。
至此,对项目的修改基本完成,重新启动项目并增加operate_history数据,就会看到新添加的数据,已经根据我们的分表规则,插入到了某一个数据表中。查询的时候,能够同时查询到多个实际数据表中的数据。
4 数据分表规则的一些考虑
前面的例子,演示的是根据entity_key进行分表,也可以使用其他字段如主键进行分表。以下是我想到的一些分表规则:
根据主键进行分配
这种方式能够实现最平均的分配方法,每生成一条新数据,会依次保存到下一个数据表中。
根据用户ID进行分配
这种方式能够确保同一个用户的所有数据保存在同一个数据表中。如果经常按用户id查询数据,这是比较经济的一种做法。
根据某一个外键的值进行分配
前面的例子采用的就是这种方法,因为这个数据可能会经常根据这个外键进行查询。
根据时间进行分配
适用于一些经常按时间段进行查询的数据,将一个时间段内的数据保存在同一个数据表中。比如订单系统,缺省查询一个月之内的数据。
关注公众号可以获取各种学习视频 spring dubbo docker
慢慢地,你的心情开始变差,因为客户和产品的抱怨越来越频繁,抱怨的最多的一个问题就是:系统越来越慢了。
1 常规优化
你组织团队,进行了一系列的优化。
1.1 数据表索引优化
经过初步分析,发现瓶颈在数据库。WEB服务器的CPU闲来无事,但数据库服务器的CPU使用率高居不下。
于是,请来架构组的DBA同事,监控数据库的访问,整理出那些耗时的SQL,并且进行SQL查询分析。根据分析结果,对数据表索引进行重新整理。同时也对数据库本身的参数设置进行了优化。
优化后,页面速度明显提升,客户抱怨减少,又过了一段时间的安逸日子。
1.2 多点部署+负载均衡
慢慢的,访问速度又不行了,这次是WEB服务器压力很大,数据库服务器相对空闲。经过分析,发现是系统并发用户数太多,单WEB服务器不能够支持如此众多的并发请求。
于是,请架构协助进行WEB多点部署,前端使用nginx做负载分发。这时候必须要解决的一个问题就是用户会话保持的问题。这可以有几种不同解决方案:
1、nginx实现sticky分发
因为nginx缺省没有sticky机制,可以使用ip_hash方式来代替。
2、配置Tomcat实现Session复制
3、代码使用SpringSession,利用redis实现session复制。
具体做法就不一一介绍了。其中使用SpringSession的方法,可以参考我的文章《集群环境CAS的问题及解决方案》。
2 试用当当的Sharding JDBC框架
多点部署之后,系统又运行了一段时间,期间增加了更多的WEB节点,基本能应对客户需求。慢慢的,增加WEB服务器也不能解决问题了,因为系统瓶颈又回到了数据库服务器。SQL执行时间越来越长,而且无法优化。原因也很简单,数据量太大。
单表数据已经超过几千万行,通过数据库的优化已经不能满足速度的要求。分库分表提到了日程上,必须解决。
因为使用了JPA,如果分库分表需要对数据访问层做较大的改动,工作量太大,修改的风险也太高。恰好看到当当开源了其Sharding-JDBC组件,摘抄一段介绍:
https://github.com/dangdangdotcom/sharding-jdbc
Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零:
可适用于任何基于java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
可基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid等。
理论上可支持任意实现JDBC规范的数据库。虽然目前仅支持MySQL,但已有支持Oracle,SQLServer,DB2等数据库的计划。
它支持JPA,可以在几乎不修改代码的情况下完成分库分表的实现。因此,选择这个框架做一次分库分表的尝试。
先做一个最简单的试用,不做分库,仅做分表。选择数据表operate_history,这个数据表记录所有的操作历史,是整个系统中数据量最大的一个数据表。
希望将这个表拆分为四个数据表,分别是 operate_history_0operate_history_1 operate_history_2 operate_history_3。数据能够分配保存到四个数据表中,降低单表的数据量。同时,为了尽量减少跨表的查询操作,决定使用字段 entity_key为分表依据,这样同一个entity对象的所有操作,将会记录在同一个数据表中。拆分后的数据表结构为:
3 实现过程
以下是针对JPA项目的修改过程。其他项目请参考官方网站的文档。
3.1 修改pom.xml增加dependency
需要添加两个jar,sharding-jdbc-core和sharding-jdbc-config-spring。
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-config-spring</artifactId>
<version>1.3.0</version>
</dependency>
3.2 修改Spring中Database部分的配置
原Database配置
<bean id="dataSource"class="org.apache.tomcat.jdbc.pool.DataSource"destroy-method="close">
<propertyname="driverClassName"value="com.mysql.jdbc.Driver"></property>
<propertyname="url" value="jdbc:mysql://localhost:3306/sharding"></property>
<propertyname="username" value="root"></property>
<propertyname="password" value="sharding"></property>
</bean>
修改后的配置
<beanid="db-node-0"class="org.apache.tomcat.jdbc.pool.DataSource"destroy-method="close">
<property name="driverClassName"value="com.mysql.jdbc.Driver"></property>
<property name="url"value="jdbc:mysql://localhost:3306/sharding"></property>
<property name="username"value="root"></property>
<property name="password"value="sharding"></property>
</bean>
<rdb:strategyid="historyTableStrategy"
sharding-columns="entity_key"
algorithm-class="cn.codestory.sharding.SingleKeyTableShardingAlgorithm"/>
<rdb:data-sourceid="dataSource">
<rdb:sharding-ruledata-sources="db-node-0"default-data-source="db-node-0">
<rdb:table-rules>
<rdb:table-rulelogic-table="operate_history"
actual-tables="operate_history_0,operate_history_1,operate_history_2,operate_history_3"
table-strategy="historyTableStrategy" />
</rdb:table-rules>
</rdb:sharding-rule>
</rdb:data-source>
3.3 编写类SingleKeyTableShardingAlgorithm
这个类用来根据entity_key值确定使用的分表名。参考sharding提供的示例代码进行修改。核心代码如下
publicCollection<String> doInSharding(
Collection<String>availableTargetNames,
ShardingValue<Long>shardingValue) {
int targetCount = availableTargetNames.size();
Collection<String> result = newLinkedHashSet<>(targetCount);
Collection<Long> values =shardingValue.getValues();
for (Long value : values) {
for (String tableNames :availableTargetNames) {
if (tableNames.endsWith(value % targetCount+ "")) {
result.add(tableNames);
}
}
}
return result;
}
这是一个简单的实现,对entity_key进行求模,用余数确定数据表名。
3.4 修改主键生成方法
因为数据分表保存,不能使用identify方式生成数据表主键。如果主键是String类型,可以考虑使用uuid生成方法,但它查询效率会相对比较低。
如果使用long型主键,可以使用其他方式,一定要确保各个子表中的主键不重复。
3.5 历史数据的处理
根据数据分表的规则,需要对原有数据包的数据进行迁移,分别移动到四个数据表中。如果不做这一步,或者数据迁移到了错误的数据表,后续将会查询不到这些数据。
至此,对项目的修改基本完成,重新启动项目并增加operate_history数据,就会看到新添加的数据,已经根据我们的分表规则,插入到了某一个数据表中。查询的时候,能够同时查询到多个实际数据表中的数据。
4 数据分表规则的一些考虑
前面的例子,演示的是根据entity_key进行分表,也可以使用其他字段如主键进行分表。以下是我想到的一些分表规则:
根据主键进行分配
这种方式能够实现最平均的分配方法,每生成一条新数据,会依次保存到下一个数据表中。
根据用户ID进行分配
这种方式能够确保同一个用户的所有数据保存在同一个数据表中。如果经常按用户id查询数据,这是比较经济的一种做法。
根据某一个外键的值进行分配
前面的例子采用的就是这种方法,因为这个数据可能会经常根据这个外键进行查询。
根据时间进行分配
适用于一些经常按时间段进行查询的数据,将一个时间段内的数据保存在同一个数据表中。比如订单系统,缺省查询一个月之内的数据。
关注公众号可以获取各种学习视频 spring dubbo docker
发表评论
-
一大波视频分享
2018-06-09 09:36 10841.ps 链接: https://pan.baidu ... -
Spring常用工具类
2018-06-03 21:45 1774Spring 的优秀工具类盘点 ( http://www.ib ... -
MINA原理详解
2018-05-19 13:51 14471. 通过SocketConnector同服务器端建立连接 ... -
最近有人说我欺骗消费者,今天来一波视频分享
2018-05-12 21:00 1137最近有人说我欺骗消费者,今天来一波视频分享 dubbo入门 ... -
SVN多版本库环境的搭建
2018-05-02 21:00 1097一、 1、启动SVN sudo svn ... -
前端 Java Python等资源合集大放送
2018-04-21 22:11 650如果需要学习视频,欢 ... -
Nginx会话保持之nginx-sticky-module模块
2018-04-16 20:34 1913在使用负载均衡的时候会遇到会话保持的问题,常用的方法有: 1. ... -
dubbo源码学习(四):暴露服务的过程
2018-04-14 11:38 944dubbo采用的nio异步的通信,通信协议默认为 netty, ... -
dubbo源码学习(四)初始化过程细节:解析服务
2018-04-12 20:32 573今天将真正去看dubbo内部的实现过程,看dubbo的源码前我 ... -
dubbo源码学习(二) : spring 自定义标签
2018-04-09 20:29 588做dubbo的配置时很容易发现,dubbo有一套自己的标签,提 ... -
Dubbo多注册中心和Zookeeper服务的迁移
2018-04-06 08:58 1459一、Dubbo多注册中心 1、 应用场景 例如阿里有些服务 ... -
dubbo源码学习一:基础知识及使用的相关技术
2018-04-05 20:10 644Dubbo是Alibaba开源的分布式服务框架,它最大的特点是 ... -
worker模式
2018-03-29 20:16 594今天来学学,大家也好对线程池有一个更好的理解。 public ... -
线程各种状态转移分析
2018-03-28 22:13 862线程在它的生命周期 ... -
生产者-消费者模式实现
2018-03-26 22:45 1121生产者是指:生产数据的线程 消费者是指:使用数据的线程 生产者 ... -
java并发之同步辅助类Phaser
2018-03-19 21:46 1036Phaser含义: 更加复杂和强大的同步辅助类。它允许并发执 ... -
java并发之同步辅助类CyclicBarrier
2018-03-18 20:13 771CyclicBarrier含义: 栅栏允许两个或者多个线程在 ... -
java并发之同步辅助类semaphore
2018-03-14 21:24 733semaphore(seməˌfôr)含义: 信号量就是可以 ... -
Tomcat 集群 文件上传下载的共享问题 NFS配置
2018-03-12 21:50 616Tomcat 集群时上传文件时如何使得多部tomcat中的文件 ... -
it技术谱图分享
2018-03-10 22:05 4731、程序开发语言综述 2、前端工程师必备技能 3、 ...
相关推荐
集成sharding-jdbc实现分库分表.zip
SpringBoot+Mybatis-Plus整合Sharding-JDBC5.1.1实现单库分表【全网最新】.doc
1、基于yml 配置方式 ,实现springBoot+sharding-jdbc+mybatis-plus 实现分库分表,读写分离,以及全局表,子表的配置。 2、实现mybatis-plus 整合到springboot 详细使用请看 测试用例
sharding-jdbc 分库分表
sharind-jdbc样例,当中包含了按月动态分表,一个比较简单的demo,仅供参考!……………………
sharind-jdbc样例,当中包含了按月动态分表,一个比较简单的demo,仅供参考!
该资源是一个demo,结合mybatis演示sharding-jdbc开源分库分表框架的使用,有创建表SQL,直接导入即可
Sharding-JDBC教程:Spring Boot整合Sharding-JDBC实现分库分表+读写分离
sharding-jdbc之——分库分表实例完整源码,详情请参见博文:http://blog.csdn.net/l1028386804/article/details/79368021
Sharding-JDBC使用案例-分库分表 分库分表
Sharding-JDBC教程:Spring Boot2.0以上整合Sharding-JDBC实现分库分表+读写分离,Mysql数据库主从搭建:https://blog.csdn.net/forezp/article/details/94173427
SpringBoot(49) 整合sharding-jdbc实现自定义分库分表
sharding-jdbc整合boot
mysql分库分表sharding-jdbc-sharding-jdbc-demo
sharding-jdbc 目录结构 sjdbc-read-write-springboot:Spring Boot版 Sharding JDBC 读写分离示列 ...sjdbc-db-sharding-table-springboot:Spring Boot版 Sharding JDBC 分库分表案例 sjdbc-db-sharding-table-rea
Sharding-JDBC集分库分表、读写分离、分布式主键、柔性事务和数据治理与一身,提供一站式的解决分布式关系型数据库的解决方案。
sharding-jdbc 分库分表 + 读写分离 demo演示 可正常运行学习
spring+mybatis+sharding-jdbc实现的一个小demo,仅供参考
当当开源sharding-jdbc-轻量级数据库分库分表中间件,比较成熟的分库分表中间件,值得一看。