├── .gitignore ├── README.md ├── discover-server ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── pbteach │ │ └── dtx │ │ └── discoverserver │ │ └── DiscoveryServer.java │ └── resources │ ├── application.yml │ └── log4j2-dev.xml ├── dtx-notifymsg-demo ├── dtx-notifymsg-demo-bank1 │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── pbteach │ │ │ └── dtx │ │ │ └── notifydemo │ │ │ └── bank1 │ │ │ ├── NotifyBank1Service.java │ │ │ ├── controller │ │ │ └── AccountInfoController.java │ │ │ ├── dao │ │ │ └── AccountInfoDao.java │ │ │ ├── entity │ │ │ ├── AccountInfo.java │ │ │ └── AccountPay.java │ │ │ ├── message │ │ │ └── NotifyMsgListener.java │ │ │ ├── model │ │ │ └── AccountChangeEvent.java │ │ │ ├── service │ │ │ ├── AccountInfoService.java │ │ │ └── impl │ │ │ │ └── AccountInfoServiceImpl.java │ │ │ └── spring │ │ │ ├── PayClient.java │ │ │ └── PayFallback.java │ │ └── resources │ │ ├── application-local.properties │ │ └── application.properties ├── dtx-notifymsg-demo-pay │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── pbteach │ │ │ └── dtx │ │ │ └── notifymsg │ │ │ └── pay │ │ │ ├── NotifyPayService.java │ │ │ ├── controller │ │ │ └── AccountPayController.java │ │ │ ├── dao │ │ │ └── AccountPayDao.java │ │ │ ├── entity │ │ │ └── AccountPay.java │ │ │ └── service │ │ │ ├── AccountPayService.java │ │ │ └── impl │ │ │ └── AccountPayServiceImpl.java │ │ └── resources │ │ ├── application-local.properties │ │ └── application.properties └── pom.xml ├── dtx-seata-demo ├── dtx-seata-demo-bank1 │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── pbteach │ │ │ └── dtx │ │ │ └── seatademo │ │ │ └── bank1 │ │ │ ├── Bank1Server.java │ │ │ ├── config │ │ │ └── DatabaseConfiguration.java │ │ │ ├── controller │ │ │ └── Bank1Controller.java │ │ │ ├── dao │ │ │ └── AccountInfoDao.java │ │ │ ├── entity │ │ │ └── AccountInfo.java │ │ │ ├── service │ │ │ ├── AccountInfoService.java │ │ │ └── impl │ │ │ │ └── AccountInfoServiceImpl.java │ │ │ └── spring │ │ │ ├── Bank2Client.java │ │ │ └── Bank2ClientFallback.java │ │ └── resources │ │ ├── application-local.yml │ │ ├── application.yml │ │ ├── file.conf │ │ └── registry.conf ├── dtx-seata-demo-bank2 │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── pbteach │ │ │ └── seatademo │ │ │ └── bank2 │ │ │ ├── Bank2Server.java │ │ │ ├── config │ │ │ └── DatabaseConfiguration.java │ │ │ ├── controller │ │ │ └── Bank2Controller.java │ │ │ ├── dao │ │ │ └── AccountInfoDao.java │ │ │ ├── entity │ │ │ └── AccountInfo.java │ │ │ └── service │ │ │ ├── AccountInfoService.java │ │ │ └── impl │ │ │ └── AccountInfoServiceImpl.java │ │ └── resources │ │ ├── application-local.yml │ │ ├── application.yml │ │ ├── file.conf │ │ └── registry.conf └── pom.xml ├── dtx-tcc-demo ├── dtx-tcc-demo-bank1 │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── pbteach │ │ │ └── dtx │ │ │ └── tccdemo │ │ │ └── bank1 │ │ │ ├── Bank1TccServer.java │ │ │ ├── config │ │ │ └── DatabaseConfiguration.java │ │ │ ├── controller │ │ │ └── Bank1Controller.java │ │ │ ├── dao │ │ │ └── AccountInfoDao.java │ │ │ ├── entity │ │ │ └── AccountInfo.java │ │ │ ├── service │ │ │ ├── AccountInfoService.java │ │ │ └── impl │ │ │ │ └── AccountInfoServiceImpl.java │ │ │ └── spring │ │ │ ├── Bank2Client.java │ │ │ └── Bank2ClientFallback.java │ │ └── resources │ │ ├── application-local.yml │ │ └── application.yml ├── dtx-tcc-demo-bank2 │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── pbteach │ │ │ └── dtx │ │ │ └── tccdemo │ │ │ └── bank2 │ │ │ ├── Bank2TccServer.java │ │ │ ├── config │ │ │ └── DatabaseConfiguration.java │ │ │ ├── controller │ │ │ └── Bank2Controller.java │ │ │ ├── dao │ │ │ └── AccountInfoDao.java │ │ │ ├── entity │ │ │ └── AccountInfo.java │ │ │ └── service │ │ │ ├── AccountInfoService.java │ │ │ └── impl │ │ │ └── AccountInfoServiceImpl.java │ │ └── resources │ │ ├── application-local.yml │ │ └── application.yml └── pom.xml ├── dtx-txmsg-demo ├── dtx-txmsg-demo-bank1 │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── pbteach │ │ │ └── dtx │ │ │ └── txmsgdemo │ │ │ └── bank1 │ │ │ ├── TxMsgBank1Service.java │ │ │ ├── controller │ │ │ └── AccountInfoController.java │ │ │ ├── dao │ │ │ └── AccountInfoDao.java │ │ │ ├── entity │ │ │ └── AccountInfo.java │ │ │ ├── message │ │ │ └── ProducerTxmsgListener.java │ │ │ ├── model │ │ │ └── AccountChangeEvent.java │ │ │ └── service │ │ │ ├── AccountInfoService.java │ │ │ └── impl │ │ │ └── AccountInfoServiceImpl.java │ │ └── resources │ │ ├── application-local.properties │ │ └── application.properties ├── dtx-txmsg-demo-bank2 │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── pbteach │ │ │ └── dtx │ │ │ └── txmsgdemo │ │ │ └── bank2 │ │ │ ├── TxMsgBank2Service.java │ │ │ ├── dao │ │ │ └── AccountInfoDao.java │ │ │ ├── entity │ │ │ └── AccountInfo.java │ │ │ ├── message │ │ │ └── TxmsgConsumer.java │ │ │ ├── model │ │ │ └── AccountChangeEvent.java │ │ │ └── service │ │ │ ├── AccountInfoService.java │ │ │ └── impl │ │ │ └── AccountInfoServiceImpl.java │ │ └── resources │ │ ├── application-local.properties │ │ └── application.properties └── pom.xml ├── pom.xml └── sql ├── ban1_pay.sql ├── bank1.sql └── bank2.sql /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | target/ 3 | *.iml 4 | pom.xml.tag 5 | pom.xml.releaseBackup 6 | pom.xml.versionsBackup 7 | pom.xml.next 8 | release.properties 9 | dependency-reduced-pom.xml 10 | buildNumber.properties 11 | .mvn/timing.properties 12 | 13 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 14 | !/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pbdtx 2 | 用于研究测试SpringCloud分布式事务控制解决方案,包括2PC、TCC、可靠消息最终一致性,最大努力通知,所用技术包括:Seata,Hmily,RocketMQ等 3 | 4 | # 1 基础概念 5 | 什么是分布式事务: 6 | 7 | CAP原理: 8 | 9 | BASE理论: 10 | 11 | # 1 seata实现2PC事务控制 12 | 13 | 代码实现步骤: 14 | 15 | # 2 Hmily实现TCC事务控制 16 | 17 | 代码实现步骤: 18 | 19 | # 3 RocketMQ事务消息方案 20 | 21 | 代码实现步骤: 22 | 23 | # 4 课程视频 24 | 25 | 分布式事务课程视频: 26 | # 5 系列讲义 27 | http://www.pbteach.com/post/java_distribut/subject_dtx-01/ 28 | 29 | http://www.pbteach.com/post/java_distribut/subject_dtx-02/ 30 | 31 | http://www.pbteach.com/post/java_distribut/subject_dtx-03/ 32 | 33 | http://www.pbteach.com/post/java_distribut/subject_dtx-04/ 34 | 35 | http://www.pbteach.com/post/java_distribut/subject_dtx-05/ 36 | 37 | http://www.pbteach.com/post/java_distribut/subject_dtx-06/ 38 | -------------------------------------------------------------------------------- /discover-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-parent 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | discover-server 13 | 14 | 15 | 16 | org.springframework.cloud 17 | spring-cloud-starter-netflix-eureka-server 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-actuator 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-logging 32 | 33 | 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-log4j2 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /discover-server/src/main/java/com/pbteach/dtx/discoverserver/DiscoveryServer.java: -------------------------------------------------------------------------------- 1 | 2 | package com.pbteach.dtx.discoverserver; 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 7 | 8 | 9 | @SpringBootApplication 10 | @EnableEurekaServer 11 | public class DiscoveryServer { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(DiscoveryServer.class, args); 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /discover-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: seata-demo-discovery 4 | 5 | 6 | server: 7 | port: 56080 #启动端口 8 | 9 | 10 | 11 | eureka: 12 | server: 13 | enable-self-preservation: false #关闭服务器自我保护,客户端心跳检测15分钟内错误达到80%服务会保护,导致别人还认为是好用的服务 14 | eviction-interval-timer-in-ms: 10000 #清理间隔(单位毫秒,默认是60*1000)5秒将客户端剔除的服务在服务注册列表中剔除# 15 | shouldUseReadOnlyResponseCache: true #eureka是CAP理论种基于AP策略,为了保证强一致性关闭此切换CP 默认不关闭 false关闭 16 | response-cache-update-interval-ms: 3000 ##eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上默认30s 17 | response-cache-auto-expiration-in-seconds: 180 ##eureka server缓存readWriteCacheMap失效时间,这个只有在这个时间过去后缓存才会失效,失效前不会更新,过期后从registry重新读取注册服务信息,registry是一个ConcurrentHashMap。 18 | client: 19 | register-with-eureka: false #false:不作为一个客户端注册到注册中心 20 | fetch-registry: false #为true时,可以启动,但报异常:Cannot execute request on any known server 21 | instance-info-replication-interval-seconds: 10 22 | serviceUrl: 23 | defaultZone: http://localhost:${server.port}/eureka/ 24 | instance: 25 | hostname: ${spring.cloud.client.ip-address} 26 | prefer-ip-address: true 27 | instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}} 28 | lease-renewal-interval-in-seconds: 5 ## 续约更新时间间隔(默认30秒) 29 | lease-expiration-duration-in-seconds: 10 # 续约到期时间(默认90秒) 30 | 31 | 32 | 33 | logging: 34 | config: classpath:log4j2-dev.xml -------------------------------------------------------------------------------- /discover-server/src/main/resources/log4j2-dev.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ${project.name} 5 | logs 6 | %date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-notifymsg-demo 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-notifymsg-demo-bank1 13 | 14 | 15 | org.springframework.cloud 16 | spring-cloud-starter-openfeign 17 | 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-starter-netflix-hystrix 22 | 23 | 24 | 25 | org.springframework.cloud 26 | spring-cloud-starter-netflix-eureka-client 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-actuator 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-configuration-processor 41 | true 42 | 43 | 44 | 45 | org.mybatis.spring.boot 46 | mybatis-spring-boot-starter 47 | 48 | 49 | 50 | com.alibaba 51 | druid-spring-boot-starter 52 | 53 | 54 | 55 | mysql 56 | mysql-connector-java 57 | 58 | 59 | 60 | 61 | javax.interceptor 62 | javax.interceptor-api 63 | 64 | 65 | 66 | 67 | io.springfox 68 | springfox-swagger2 69 | 70 | 71 | io.springfox 72 | springfox-swagger-ui 73 | 74 | 75 | 76 | org.projectlombok 77 | lombok 78 | 79 | 80 | 81 | org.apache.rocketmq 82 | rocketmq-spring-boot-starter 83 | 2.0.2 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/NotifyBank1Service.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 8 | import org.springframework.cloud.openfeign.EnableFeignClients; 9 | 10 | @SpringBootApplication 11 | @EnableDiscoveryClient 12 | @EnableHystrix 13 | @EnableFeignClients(basePackages = {"com.pbteach.dtx.notifydemo.bank1.spring"}) 14 | public class NotifyBank1Service { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(NotifyBank1Service.class, args); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/controller/AccountInfoController.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.controller; 2 | 3 | import com.pbteach.dtx.notifydemo.bank1.entity.AccountPay; 4 | import com.pbteach.dtx.notifydemo.bank1.service.AccountInfoService; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | /** 12 | * @author Administrator 13 | * @version 1.0 14 | **/ 15 | @RestController 16 | @Slf4j 17 | public class AccountInfoController { 18 | 19 | @Autowired 20 | private AccountInfoService accountInfoService; 21 | 22 | //主动查询充值结果 23 | @GetMapping(value = "/payresult/{txNo}") 24 | public AccountPay result(@PathVariable("txNo") String txNo){ 25 | AccountPay accountPay = accountInfoService.queryPayResult(txNo); 26 | return accountPay; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/dao/AccountInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.dao; 2 | 3 | import org.apache.ibatis.annotations.*; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Mapper 7 | @Component 8 | public interface AccountInfoDao { 9 | //修改账户金额 10 | @Update("update account_info set account_balance=account_balance+#{amount} where account_no=#{accountNo}") 11 | int updateAccountBalance(@Param("accountNo") String accountNo, @Param("amount") Double amount); 12 | 13 | 14 | //查询幂等记录,用于幂等控制 15 | @Select("select count(1) from de_duplication where tx_no = #{txNo}") 16 | int isExistTx(String txNo); 17 | 18 | //添加事务记录,用于幂等控制 19 | @Insert("insert into de_duplication values(#{txNo},now());") 20 | int addTx(String txNo); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/entity/AccountInfo.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class AccountInfo implements Serializable { 9 | private Long id; 10 | private String accountName; 11 | private String accountNo; 12 | private String accountPassword; 13 | private Double accountBalance; 14 | } 15 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/entity/AccountPay.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class AccountPay implements Serializable { 13 | 14 | 15 | /** 16 | * 事务号 17 | */ 18 | private String id; 19 | 20 | /** 21 | * 账号 22 | */ 23 | private String accountNo; 24 | /** 25 | * 变动金额 26 | */ 27 | private double payAmount; 28 | /** 29 | * 充值结果 30 | */ 31 | private String result; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/message/NotifyMsgListener.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.message; 2 | 3 | import com.pbteach.dtx.notifydemo.bank1.entity.AccountPay; 4 | import com.pbteach.dtx.notifydemo.bank1.model.AccountChangeEvent; 5 | import com.pbteach.dtx.notifydemo.bank1.service.AccountInfoService; 6 | import com.alibaba.fastjson.JSON; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; 9 | import org.apache.rocketmq.spring.core.RocketMQListener; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Component; 12 | 13 | /** 14 | * @author Administrator 15 | * @version 1.0 16 | **/ 17 | @Component 18 | @Slf4j 19 | @RocketMQMessageListener(topic = "topic_notifymsg",consumerGroup = "consumer_group_notifymsg_bank1") 20 | public class NotifyMsgListener implements RocketMQListener { 21 | 22 | @Autowired 23 | AccountInfoService accountInfoService; 24 | 25 | //接收消息 26 | @Override 27 | public void onMessage(AccountPay accountPay) { 28 | log.info("接收到消息:{}", JSON.toJSONString(accountPay)); 29 | if("success".equals(accountPay.getResult())){ 30 | //更新账户金额 31 | AccountChangeEvent accountChangeEvent = new AccountChangeEvent(); 32 | accountChangeEvent.setAccountNo(accountPay.getAccountNo()); 33 | accountChangeEvent.setAmount(accountPay.getPayAmount()); 34 | accountChangeEvent.setTxNo(accountPay.getId()); 35 | accountInfoService.updateAccountBalance(accountChangeEvent); 36 | } 37 | log.info("处理消息完成:{}", JSON.toJSONString(accountPay)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/model/AccountChangeEvent.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class AccountChangeEvent implements Serializable { 13 | 14 | 15 | /** 16 | * 账号 17 | */ 18 | private String accountNo; 19 | /** 20 | * 变动金额 21 | */ 22 | private double amount; 23 | /** 24 | * 事务号 25 | */ 26 | private String txNo; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/service/AccountInfoService.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.service; 2 | 3 | import com.pbteach.dtx.notifydemo.bank1.entity.AccountPay; 4 | import com.pbteach.dtx.notifydemo.bank1.model.AccountChangeEvent; 5 | 6 | /** 7 | * Created by Administrator. 8 | */ 9 | public interface AccountInfoService { 10 | 11 | //更新账户金额 12 | public void updateAccountBalance(AccountChangeEvent accountChange); 13 | 14 | //查询充值结果(远程调用) 15 | public AccountPay queryPayResult(String tx_no); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/service/impl/AccountInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.service.impl; 2 | 3 | import com.pbteach.dtx.notifydemo.bank1.dao.AccountInfoDao; 4 | import com.pbteach.dtx.notifydemo.bank1.entity.AccountPay; 5 | import com.pbteach.dtx.notifydemo.bank1.model.AccountChangeEvent; 6 | import com.pbteach.dtx.notifydemo.bank1.service.AccountInfoService; 7 | import com.pbteach.dtx.notifydemo.bank1.spring.PayClient; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | /** 14 | * @author Administrator 15 | * @version 1.0 16 | **/ 17 | @Service 18 | @Slf4j 19 | public class AccountInfoServiceImpl implements AccountInfoService { 20 | 21 | @Autowired 22 | AccountInfoDao accountInfoDao; 23 | 24 | @Autowired 25 | PayClient payClient; 26 | 27 | //更新账户金额 28 | @Override 29 | @Transactional 30 | public void updateAccountBalance(AccountChangeEvent accountChange) { 31 | //幂等校验 32 | if(accountInfoDao.isExistTx(accountChange.getTxNo())>0){ 33 | return ; 34 | } 35 | int i = accountInfoDao.updateAccountBalance(accountChange.getAccountNo(), accountChange.getAmount()); 36 | //插入事务记录,用于幂等控制 37 | accountInfoDao.addTx(accountChange.getTxNo()); 38 | } 39 | 40 | //远程调用查询充值结果 41 | @Override 42 | public AccountPay queryPayResult(String tx_no) { 43 | 44 | //远程调用 45 | AccountPay payresult = payClient.payresult(tx_no); 46 | if("success".equals(payresult.getResult())){ 47 | //更新账户金额 48 | AccountChangeEvent accountChangeEvent = new AccountChangeEvent(); 49 | accountChangeEvent.setAccountNo(payresult.getAccountNo());//账号 50 | accountChangeEvent.setAmount(payresult.getPayAmount());//金额 51 | accountChangeEvent.setTxNo(payresult.getId());//充值事务号 52 | updateAccountBalance(accountChangeEvent); 53 | } 54 | return payresult; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/spring/PayClient.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.spring; 2 | 3 | import com.pbteach.dtx.notifydemo.bank1.entity.AccountPay; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | 8 | /** 9 | * Created by Administrator. 10 | * 远程调用pay充值系统 11 | */ 12 | @FeignClient(value = "dtx-notifymsg-demo-pay",fallback = PayFallback.class) 13 | public interface PayClient { 14 | 15 | //远程调用充值系统的接口查询充值结果 16 | @GetMapping(value = "/pay/payresult/{txNo}") 17 | public AccountPay payresult(@PathVariable("txNo") String txNo); 18 | } 19 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/java/com/pbteach/dtx/notifydemo/bank1/spring/PayFallback.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifydemo.bank1.spring; 2 | 3 | import com.pbteach.dtx.notifydemo.bank1.entity.AccountPay; 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * @author Administrator 8 | * @version 1.0 9 | **/ 10 | @Component 11 | public class PayFallback implements PayClient { 12 | @Override 13 | public AccountPay payresult(String txNo) { 14 | AccountPay accountPay = new AccountPay(); 15 | accountPay.setResult("fail"); 16 | return accountPay; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | server.port=56081 2 | swagger.enable = true 3 | eureka.client.serviceUrl.defaultZone: http://localhost:56080/eureka/ 4 | 5 | spring.datasource.driver-class-name = com.mysql.jdbc.Driver 6 | spring.datasource.url = jdbc:mysql://localhost:3306/bank1?useUnicode=true 7 | spring.datasource.username = root 8 | spring.datasource.password = mysql 9 | 10 | 11 | rocketmq.producer.group = producer_notifymsg_bank1 12 | rocketmq.name-server = 127.0.0.1:9876 13 | 14 | logging.level.root = info 15 | logging.level.org.springframework.web = info 16 | logging.level.com.pbteach.wanxintx.effortdemo = debug 17 | 18 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-bank1/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name = dtx-notifymsg-demo-bank1 2 | spring.profiles.active = local 3 | 4 | server.servlet.context-path = /bank1 5 | spring.http.encoding.enabled = true 6 | spring.http.encoding.charset = UTF-8 7 | spring.http.encoding.force = true 8 | server.tomcat.remote_ip_header = x-forwarded-for 9 | server.tomcat.protocol_header = x-forwarded-proto 10 | server.use-forward-headers = true 11 | 12 | spring.mvc.throw-exception-if-no-handler-found = true 13 | spring.resources.add-mappings = true 14 | spring.freemarker.enabled = true 15 | spring.freemarker.suffix = .html 16 | spring.freemarker.request-context-attribute = rc 17 | spring.freemarker.content-type = text/html 18 | spring.freemarker.charset = UTF-8 19 | 20 | 21 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-pay/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-notifymsg-demo 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-notifymsg-demo-pay 13 | 14 | 15 | org.springframework.cloud 16 | spring-cloud-starter-openfeign 17 | 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-starter-netflix-hystrix 22 | 23 | 24 | 25 | org.springframework.cloud 26 | spring-cloud-starter-netflix-eureka-client 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-actuator 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-configuration-processor 41 | true 42 | 43 | 44 | 45 | org.mybatis.spring.boot 46 | mybatis-spring-boot-starter 47 | 48 | 49 | 50 | com.alibaba 51 | druid-spring-boot-starter 52 | 53 | 54 | 55 | mysql 56 | mysql-connector-java 57 | 58 | 59 | 60 | 61 | javax.interceptor 62 | javax.interceptor-api 63 | 64 | 65 | 66 | 67 | io.springfox 68 | springfox-swagger2 69 | 70 | 71 | io.springfox 72 | springfox-swagger-ui 73 | 74 | 75 | 76 | org.projectlombok 77 | lombok 78 | 79 | 80 | 81 | org.apache.rocketmq 82 | rocketmq-spring-boot-starter 83 | 2.0.2 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-pay/src/main/java/com/pbteach/dtx/notifymsg/pay/NotifyPayService.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifymsg.pay; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 8 | 9 | @SpringBootApplication 10 | @EnableDiscoveryClient 11 | @EnableHystrix 12 | public class NotifyPayService { 13 | public static void main(String[] args) { 14 | SpringApplication.run(NotifyPayService.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-pay/src/main/java/com/pbteach/dtx/notifymsg/pay/controller/AccountPayController.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifymsg.pay.controller; 2 | 3 | import com.pbteach.dtx.notifymsg.pay.entity.AccountPay; 4 | import com.pbteach.dtx.notifymsg.pay.service.AccountPayService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import java.util.UUID; 11 | 12 | /** 13 | * @author Administrator 14 | * @version 1.0 15 | **/ 16 | @RestController 17 | public class AccountPayController { 18 | 19 | @Autowired 20 | AccountPayService accountPayService; 21 | 22 | //充值 23 | @GetMapping(value = "/paydo") 24 | public AccountPay pay(AccountPay accountPay){ 25 | //生成事务编号 26 | String txNo = UUID.randomUUID().toString(); 27 | accountPay.setId(txNo); 28 | return accountPayService.insertAccountPay(accountPay); 29 | } 30 | 31 | //查询充值结果 32 | @GetMapping(value = "/payresult/{txNo}") 33 | public AccountPay payresult(@PathVariable("txNo") String txNo){ 34 | return accountPayService.getAccountPay(txNo); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-pay/src/main/java/com/pbteach/dtx/notifymsg/pay/dao/AccountPayDao.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifymsg.pay.dao; 2 | 3 | import com.pbteach.dtx.notifymsg.pay.entity.AccountPay; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.apache.ibatis.annotations.Select; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Mapper 11 | @Component 12 | public interface AccountPayDao { 13 | @Insert("insert into account_pay(id,account_no,pay_amount,result) values(#{id},#{accountNo},#{payAmount},#{result})") 14 | int insertAccountPay(@Param("id") String id,@Param("accountNo") String accountNo, @Param("payAmount") Double pay_amount,@Param("result") String result); 15 | 16 | @Select("select id,account_no accountNo,pay_amount payAmount,result from account_pay where id=#{txNo}") 17 | AccountPay findByIdTxNo(@Param("txNo") String txNo); 18 | 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-pay/src/main/java/com/pbteach/dtx/notifymsg/pay/entity/AccountPay.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifymsg.pay.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class AccountPay implements Serializable { 13 | 14 | 15 | /** 16 | * 事务号 17 | */ 18 | private String id; 19 | 20 | /** 21 | * 账号 22 | */ 23 | private String accountNo; 24 | /** 25 | * 变动金额 26 | */ 27 | private double payAmount; 28 | /** 29 | * 充值结果 30 | */ 31 | private String result; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-pay/src/main/java/com/pbteach/dtx/notifymsg/pay/service/AccountPayService.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifymsg.pay.service; 2 | 3 | import com.pbteach.dtx.notifymsg.pay.entity.AccountPay; 4 | 5 | /** 6 | * Created by Administrator. 7 | */ 8 | public interface AccountPayService { 9 | 10 | //充值 11 | public AccountPay insertAccountPay(AccountPay accountPay); 12 | //查询充值结果 13 | public AccountPay getAccountPay(String txNo); 14 | } 15 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-pay/src/main/java/com/pbteach/dtx/notifymsg/pay/service/impl/AccountPayServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.notifymsg.pay.service.impl; 2 | 3 | import com.pbteach.dtx.notifymsg.pay.dao.AccountPayDao; 4 | import com.pbteach.dtx.notifymsg.pay.entity.AccountPay; 5 | import com.pbteach.dtx.notifymsg.pay.service.AccountPayService; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.rocketmq.spring.core.RocketMQTemplate; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | /** 12 | * @author Administrator 13 | * @version 1.0 14 | **/ 15 | @Service 16 | @Slf4j 17 | public class AccountPayServiceImpl implements AccountPayService { 18 | 19 | @Autowired 20 | AccountPayDao accountPayDao; 21 | 22 | @Autowired 23 | RocketMQTemplate rocketMQTemplate; 24 | 25 | //插入充值记录 26 | @Override 27 | public AccountPay insertAccountPay(AccountPay accountPay) { 28 | int success = accountPayDao.insertAccountPay(accountPay.getId(), accountPay.getAccountNo(), accountPay.getPayAmount(), "success"); 29 | if(success>0){ 30 | //发送通知,使用普通消息发送通知 31 | accountPay.setResult("success"); 32 | rocketMQTemplate.convertAndSend("topic_notifymsg",accountPay); 33 | return accountPay; 34 | } 35 | return null; 36 | } 37 | 38 | //查询充值记录,接收通知方调用此方法来查询充值结果 39 | @Override 40 | public AccountPay getAccountPay(String txNo) { 41 | AccountPay accountPay = accountPayDao.findByIdTxNo(txNo); 42 | return accountPay; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-pay/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | server.port=56082 2 | swagger.enable = true 3 | eureka.client.serviceUrl.defaultZone: http://localhost:56080/eureka/ 4 | 5 | spring.datasource.driver-class-name = com.mysql.jdbc.Driver 6 | spring.datasource.url = jdbc:mysql://localhost:3306/bank1_pay?useUnicode=true 7 | spring.datasource.username = root 8 | spring.datasource.password = mysql 9 | 10 | 11 | rocketmq.producer.group = producer_notifymsg_pay 12 | rocketmq.name-server = 127.0.0.1:9876 13 | 14 | logging.level.root = info 15 | logging.level.org.springframework.web = info 16 | logging.level.com.pbteach.wanxintx.effortdemo = debug 17 | 18 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/dtx-notifymsg-demo-pay/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name = dtx-notifymsg-demo-pay 2 | spring.profiles.active = local 3 | 4 | server.servlet.context-path = /pay 5 | spring.http.encoding.enabled = true 6 | spring.http.encoding.charset = UTF-8 7 | spring.http.encoding.force = true 8 | server.tomcat.remote_ip_header = x-forwarded-for 9 | server.tomcat.protocol_header = x-forwarded-proto 10 | server.use-forward-headers = true 11 | 12 | spring.mvc.throw-exception-if-no-handler-found = true 13 | spring.resources.add-mappings = true 14 | spring.freemarker.enabled = true 15 | spring.freemarker.suffix = .html 16 | spring.freemarker.request-context-attribute = rc 17 | spring.freemarker.content-type = text/html 18 | spring.freemarker.charset = UTF-8 19 | 20 | 21 | -------------------------------------------------------------------------------- /dtx-notifymsg-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-parent 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-notifymsg-demo 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-dependencies 23 | Greenwich.RELEASE 24 | pom 25 | import 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-dependencies 31 | 2.1.3.RELEASE 32 | pom 33 | import 34 | 35 | 36 | 37 | org.apache.rocketmq 38 | rocketmq-spring-boot-starter 39 | 2.0.2 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-seata-demo 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-seata-demo-bank1 13 | 14 | 15 | 16 | com.alibaba.cloud 17 | spring-cloud-alibaba-seata 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-starter-openfeign 23 | 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-starter-netflix-hystrix 28 | 29 | 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-netflix-eureka-client 34 | 35 | 36 | 37 | 38 | com.netflix.hystrix 39 | hystrix-javanica 40 | 41 | 42 | 43 | org.springframework.retry 44 | spring-retry 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-web 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-actuator 59 | 60 | 61 | 62 | org.mybatis.spring.boot 63 | mybatis-spring-boot-starter 64 | 65 | 66 | 67 | mysql 68 | mysql-connector-java 69 | 70 | 71 | 72 | 73 | org.projectlombok 74 | lombok 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/java/com/pbteach/dtx/seatademo/bank1/Bank1Server.java: -------------------------------------------------------------------------------- 1 | 2 | package com.pbteach.dtx.seatademo.bank1; 3 | 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 8 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 9 | import org.springframework.cloud.openfeign.EnableFeignClients; 10 | 11 | 12 | @SpringBootApplication 13 | @EnableDiscoveryClient 14 | @EnableHystrix 15 | @EnableFeignClients(basePackages = {"com.pbteach.dtx.seatademo.bank1.spring"}) 16 | public class Bank1Server { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(Bank1Server.class, args); 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/java/com/pbteach/dtx/seatademo/bank1/config/DatabaseConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.seatademo.bank1.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import io.seata.rm.datasource.DataSourceProxy; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.ApplicationContext; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Primary; 10 | 11 | import javax.sql.DataSource; 12 | 13 | @Configuration 14 | public class DatabaseConfiguration { 15 | 16 | 17 | private final ApplicationContext applicationContext; 18 | 19 | public DatabaseConfiguration(ApplicationContext applicationContext) { 20 | this.applicationContext = applicationContext; 21 | } 22 | 23 | 24 | @Bean 25 | @ConfigurationProperties(prefix = "spring.datasource.ds0") 26 | public DruidDataSource ds0() { 27 | DruidDataSource druidDataSource = new DruidDataSource(); 28 | return druidDataSource; 29 | } 30 | 31 | 32 | @Primary 33 | @Bean 34 | public DataSource dataSource(DruidDataSource ds0) { 35 | DataSourceProxy pds0 = new DataSourceProxy(ds0); 36 | return pds0; 37 | } 38 | 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/java/com/pbteach/dtx/seatademo/bank1/controller/Bank1Controller.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.seatademo.bank1.controller; 2 | 3 | import com.pbteach.dtx.seatademo.bank1.service.AccountInfoService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | /** 9 | * @author Administrator 10 | * @version 1.0 11 | **/ 12 | @RestController 13 | public class Bank1Controller { 14 | 15 | @Autowired 16 | AccountInfoService accountInfoService; 17 | 18 | //张三转账 19 | @GetMapping("/transfer") 20 | public String transfer(Double amount){ 21 | accountInfoService.updateAccountBalance("1",amount); 22 | return "bank1"+amount; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/java/com/pbteach/dtx/seatademo/bank1/dao/AccountInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.seatademo.bank1.dao; 2 | 3 | import org.apache.ibatis.annotations.Mapper; 4 | import org.apache.ibatis.annotations.Param; 5 | import org.apache.ibatis.annotations.Update; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Created by Administrator. 10 | */ 11 | @Mapper 12 | @Component 13 | public interface AccountInfoDao { 14 | 15 | //更新账户金额 16 | @Update("update account_info set account_balance = account_balance + #{amount} where account_no = #{accountNo}") 17 | int updateAccountBalance(@Param("accountNo") String accountNo, @Param("amount") Double amount); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/java/com/pbteach/dtx/seatademo/bank1/entity/AccountInfo.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.seatademo.bank1.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | public class AccountInfo implements Serializable { 6 | private Long id; 7 | private String accountName; 8 | private String accountNo; 9 | private String accountPassword; 10 | private Double accountBalance; 11 | 12 | public Long getId() { 13 | return id; 14 | } 15 | public void setId(Long id) { 16 | this.id = id; 17 | } 18 | public String getAccountName() { 19 | return accountName; 20 | } 21 | public void setAccountName(String accountName) { 22 | this.accountName = accountName; 23 | } 24 | public String getAccountNo() { 25 | return accountNo; 26 | } 27 | public void setAccountNo(String accountNo) { 28 | this.accountNo = accountNo; 29 | } 30 | public String getAccountPassword() { 31 | return accountPassword; 32 | } 33 | public void setAccountPassword(String accountPassword) { 34 | this.accountPassword = accountPassword; 35 | } 36 | public Double getAccountBalance() { 37 | return accountBalance; 38 | } 39 | public void setAccountBalance(Double accountBalance) { 40 | this.accountBalance = accountBalance; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/java/com/pbteach/dtx/seatademo/bank1/service/AccountInfoService.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.seatademo.bank1.service; 2 | 3 | /** 4 | * Created by Administrator. 5 | */ 6 | public interface AccountInfoService { 7 | 8 | //张三扣减金额 9 | public void updateAccountBalance(String accountNo, Double amount); 10 | } 11 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/java/com/pbteach/dtx/seatademo/bank1/service/impl/AccountInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.seatademo.bank1.service.impl; 2 | 3 | import com.pbteach.dtx.seatademo.bank1.dao.AccountInfoDao; 4 | import com.pbteach.dtx.seatademo.bank1.service.AccountInfoService; 5 | import com.pbteach.dtx.seatademo.bank1.spring.Bank2Client; 6 | import io.seata.core.context.RootContext; 7 | import io.seata.spring.annotation.GlobalTransactional; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | /** 14 | * @author Administrator 15 | * @version 1.0 16 | **/ 17 | @Service 18 | @Slf4j 19 | public class AccountInfoServiceImpl implements AccountInfoService { 20 | 21 | @Autowired 22 | AccountInfoDao accountInfoDao; 23 | 24 | @Autowired 25 | Bank2Client bank2Client; 26 | 27 | @Transactional 28 | @GlobalTransactional//开启全局事务 29 | @Override 30 | public void updateAccountBalance(String accountNo, Double amount) { 31 | log.info("bank1 service begin,XID:{}", RootContext.getXID()); 32 | //扣减张三的金额 33 | accountInfoDao.updateAccountBalance(accountNo,amount *-1); 34 | //调用李四微服务,转账 35 | String transfer = bank2Client.transfer(amount); 36 | if("fallback".equals(transfer)){ 37 | //调用李四微服务异常 38 | throw new RuntimeException("调用李四微服务异常"); 39 | } 40 | if(amount == 2){ 41 | //人为制造异常 42 | throw new RuntimeException("bank1 make exception.."); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/java/com/pbteach/dtx/seatademo/bank1/spring/Bank2Client.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.seatademo.bank1.spring; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | 7 | /** 8 | * Created by Administrator. 9 | */ 10 | @FeignClient(value="seata-demo-bank2",fallback=Bank2ClientFallback.class) 11 | public interface Bank2Client { 12 | //远程调用李四的微服务 13 | @GetMapping("/bank2/transfer") 14 | public String transfer(@RequestParam("amount") Double amount); 15 | } 16 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/java/com/pbteach/dtx/seatademo/bank1/spring/Bank2ClientFallback.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.seatademo.bank1.spring; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | /** 6 | * @author Administrator 7 | * @version 1.0 8 | **/ 9 | @Component 10 | public class Bank2ClientFallback implements Bank2Client { 11 | 12 | @Override 13 | public String transfer(Double amount) { 14 | 15 | return "fallback"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/resources/application-local.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 56081 3 | 4 | eureka: 5 | client: 6 | serviceUrl: 7 | defaultZone: http://localhost:56080/eureka/ 8 | 9 | spring: 10 | ##################### DB ##################### 11 | datasource: 12 | ds0: 13 | url: jdbc:mysql://localhost:3306/bank1?useUnicode=true 14 | username: root 15 | password: mysql 16 | type: com.alibaba.druid.pool.DruidDataSource 17 | driver-class-name: com.mysql.jdbc.Driver 18 | initialSize: 5 19 | minIdle: 5 20 | maxActive: 20 21 | maxWait: 60000 22 | timeBetweenEvictionRunsMillis: 60000 23 | minEvictableIdleTimeMillis: 300000 24 | validationQuery: SELECT user() 25 | testWhileIdle: true 26 | testOnBorrow: false 27 | testOnReturn: false 28 | poolPreparedStatements: true 29 | connection-properties: druid.stat.mergeSql:true;druid.stat.slowSqlMillis:5000 30 | 31 | 32 | # cloud: 33 | # alibaba: 34 | # seata: 35 | # tx-service-group: seata-demo-bank1-fescar-service-group 36 | 37 | logging: 38 | level: 39 | root: INFO 40 | io: 41 | seata: DEBUG 42 | org: 43 | springframework: 44 | cloud: 45 | alibaba: 46 | seata: 47 | web: DEBUG 48 | 49 | 50 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: seata-demo-bank1 4 | profiles: 5 | active: local 6 | 7 | main: 8 | allow-bean-definition-overriding: true 9 | 10 | 11 | 12 | jackson: 13 | date-format: yyyy-MM-dd HH:mm:ss 14 | time-zone: GMT+8 15 | 16 | 17 | server: 18 | servlet: 19 | context-path: /bank1 20 | 21 | 22 | 23 | eureka: 24 | instance: 25 | preferIpAddress: true 26 | instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}} 27 | lease-renewal-interval-in-seconds: 5 # 续约更新时间间隔(默认30秒) 28 | lease-expiration-duration-in-seconds: 10 # 续约到期时间(默认90秒) 29 | client: 30 | registry-fetch-interval-seconds: 5 # 抓取服务列表 31 | 32 | management: 33 | endpoints: 34 | web: 35 | exposure: 36 | include: refresh,health,info,env 37 | 38 | 39 | feign: 40 | hystrix: 41 | enabled: true 42 | compression: 43 | request: 44 | enabled: true # 配置请求GZIP压缩 45 | mime-types: ["text/xml","application/xml","application/json"] # 配置压缩支持的MIME TYPE 46 | min-request-size: 2048 # 配置压缩数据大小的下限 47 | response: 48 | enabled: true # 配置响应GZIP压缩 49 | 50 | hystrix: 51 | command: 52 | default: 53 | execution: 54 | isolation: 55 | thread: 56 | timeoutInMilliseconds: 1000 # 设置熔断超时时间 default 1000 57 | timeout: 58 | enabled: true # 打开超时熔断功能 default true 59 | 60 | 61 | ribbon: 62 | ConnectTimeout: 600 # 设置连接超时时间 default 2000 63 | ReadTimeout: 6000 # 设置读取超时时间 default 5000 64 | OkToRetryOnAllOperations: true # 对所有操作请求都进行重试 default false 65 | MaxAutoRetriesNextServer: 2 # 切换实例的重试次数 default 1 66 | MaxAutoRetries: 1 # 对当前实例的重试次数 default 0 67 | 68 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/resources/file.conf: -------------------------------------------------------------------------------- 1 | transport { 2 | # tcp udt unix-domain-socket 3 | type = "TCP" 4 | #NIO NATIVE 5 | server = "NIO" 6 | #enable heartbeat 7 | heartbeat = true 8 | #thread factory for netty 9 | thread-factory { 10 | boss-thread-prefix = "NettyBoss" 11 | worker-thread-prefix = "NettyServerNIOWorker" 12 | server-executor-thread-prefix = "NettyServerBizHandler" 13 | share-boss-worker = false 14 | client-selector-thread-prefix = "NettyClientSelector" 15 | client-selector-thread-size = 1 16 | client-worker-thread-prefix = "NettyClientWorkerThread" 17 | # netty boss thread size,will not be used for UDT 18 | boss-thread-size = 1 19 | #auto default pin or 8 20 | worker-thread-size = 8 21 | } 22 | } 23 | ## transaction log store 24 | store { 25 | ## store mode: file、db 26 | mode = "file" 27 | 28 | ## file store 29 | file { 30 | dir = "sessionStore" 31 | 32 | # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions 33 | max-branch-session-size = 16384 34 | # globe session size , if exceeded throws exceptions 35 | max-global-session-size = 512 36 | # file buffer size , if exceeded allocate new buffer 37 | file-write-buffer-cache-size = 16384 38 | # when recover batch read size 39 | session.reload.read_size = 100 40 | # async, sync 41 | flush-disk-mode = async 42 | } 43 | 44 | ## database store 45 | // db { 46 | // driver_class = "com.mysql.jdbc.Driver" 47 | // url = "jdbc:mysql://172.16.0.203:3306/bank?useUnicode=true" 48 | // user = "root" 49 | // password = "pbteach0430" 50 | // } 51 | db { 52 | ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. 53 | datasource = "dbcp" 54 | ## mysql/oracle/h2/oceanbase etc. 55 | db-type = "mysql" 56 | url = "jdbc:mysql://127.0.0.1:3306/seata" 57 | user = "root" 58 | password = "mysql" 59 | min-conn = 1 60 | max-conn = 3 61 | global.table = "global_table" 62 | branch.table = "branch_table" 63 | lock-table = "lock_table" 64 | query-limit = 100 65 | } 66 | 67 | } 68 | 69 | service { 70 | #vgroup->rgroup 71 | vgroup_mapping.seata-demo-bank1-fescar-service-group = "default" 72 | #only support single node 73 | default.grouplist = "127.0.0.1:8888" 74 | #degrade current not support 75 | enableDegrade = false 76 | #disable 77 | disable = false 78 | } 79 | client { 80 | async.commit.buffer.limit = 10000 81 | lock { 82 | retry.internal = 10 83 | retry.times = 30 84 | } 85 | } -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank1/src/main/resources/registry.conf: -------------------------------------------------------------------------------- 1 | registry { 2 | # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa 3 | type = "file" 4 | 5 | nacos { 6 | serverAddr = "localhost" 7 | namespace = "public" 8 | cluster = "default" 9 | } 10 | eureka { 11 | serviceUrl = "http://localhost:1001/eureka" 12 | application = "default" 13 | weight = "1" 14 | } 15 | redis { 16 | serverAddr = "localhost:6379" 17 | db = "0" 18 | } 19 | zk { 20 | cluster = "default" 21 | serverAddr = "127.0.0.1:2181" 22 | session.timeout = 6000 23 | connect.timeout = 2000 24 | } 25 | consul { 26 | cluster = "default" 27 | serverAddr = "127.0.0.1:8500" 28 | } 29 | etcd3 { 30 | cluster = "default" 31 | serverAddr = "http://localhost:2379" 32 | } 33 | sofa { 34 | serverAddr = "127.0.0.1:9603" 35 | application = "default" 36 | region = "DEFAULT_ZONE" 37 | datacenter = "DefaultDataCenter" 38 | cluster = "default" 39 | group = "SEATA_GROUP" 40 | addressWaitTime = "3000" 41 | } 42 | file { 43 | name = "file.conf" 44 | } 45 | } 46 | 47 | config { 48 | # file、nacos 、apollo、zk 49 | type = "file" 50 | 51 | nacos { 52 | serverAddr = "localhost" 53 | namespace = "public" 54 | cluster = "default" 55 | } 56 | apollo { 57 | app.id = "seata-server" 58 | apollo.meta = "http://192.168.1.204:8801" 59 | } 60 | zk { 61 | serverAddr = "127.0.0.1:2181" 62 | session.timeout = 6000 63 | connect.timeout = 2000 64 | } 65 | file { 66 | name = "file.conf" 67 | } 68 | } -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-seata-demo 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-seata-demo-bank2 13 | 14 | 15 | 16 | com.alibaba.cloud 17 | spring-cloud-alibaba-seata 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-starter-openfeign 23 | 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-starter-netflix-hystrix 28 | 29 | 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-netflix-eureka-client 34 | 35 | 36 | 37 | 38 | com.netflix.hystrix 39 | hystrix-javanica 40 | 41 | 42 | 43 | org.springframework.retry 44 | spring-retry 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-web 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-actuator 59 | 60 | 61 | 62 | org.mybatis.spring.boot 63 | mybatis-spring-boot-starter 64 | 65 | 66 | 67 | mysql 68 | mysql-connector-java 69 | 70 | 71 | 72 | 73 | org.projectlombok 74 | lombok 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/java/com/pbteach/seatademo/bank2/Bank2Server.java: -------------------------------------------------------------------------------- 1 | 2 | package com.pbteach.seatademo.bank2; 3 | 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 8 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 9 | import org.springframework.cloud.openfeign.EnableFeignClients; 10 | 11 | 12 | @SpringBootApplication 13 | @EnableDiscoveryClient 14 | @EnableHystrix 15 | @EnableFeignClients(basePackages = {"com.pbteach.dtx.seatademo.bank2.spring"}) 16 | public class Bank2Server { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(Bank2Server.class, args); 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/java/com/pbteach/seatademo/bank2/config/DatabaseConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.seatademo.bank2.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import io.seata.rm.datasource.DataSourceProxy; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.ApplicationContext; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Primary; 10 | 11 | import javax.sql.DataSource; 12 | 13 | @Configuration 14 | public class DatabaseConfiguration { 15 | 16 | 17 | private final ApplicationContext applicationContext; 18 | 19 | public DatabaseConfiguration(ApplicationContext applicationContext) { 20 | this.applicationContext = applicationContext; 21 | } 22 | 23 | 24 | @Bean 25 | @ConfigurationProperties(prefix = "spring.datasource.ds0") 26 | public DruidDataSource ds0() { 27 | DruidDataSource druidDataSource = new DruidDataSource(); 28 | return druidDataSource; 29 | } 30 | 31 | 32 | @Primary 33 | @Bean 34 | public DataSource dataSource(DruidDataSource ds0) { 35 | DataSourceProxy pds0 = new DataSourceProxy(ds0); 36 | return pds0; 37 | } 38 | 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/java/com/pbteach/seatademo/bank2/controller/Bank2Controller.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.seatademo.bank2.controller; 2 | 3 | import com.pbteach.seatademo.bank2.service.AccountInfoService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | /** 9 | * @author Administrator 10 | * @version 1.0 11 | **/ 12 | @RestController 13 | public class Bank2Controller { 14 | 15 | @Autowired 16 | AccountInfoService accountInfoService; 17 | 18 | //接收张三的转账 19 | @GetMapping("/transfer") 20 | public String transfer(Double amount){ 21 | //李四增加金额 22 | accountInfoService.updateAccountBalance("2",amount); 23 | return "bank2"+amount; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/java/com/pbteach/seatademo/bank2/dao/AccountInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.seatademo.bank2.dao; 2 | 3 | import org.apache.ibatis.annotations.Mapper; 4 | import org.apache.ibatis.annotations.Param; 5 | import org.apache.ibatis.annotations.Update; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Created by Administrator. 10 | */ 11 | @Mapper 12 | @Component 13 | public interface AccountInfoDao { 14 | //更新账户 15 | @Update("UPDATE account_info SET account_balance = account_balance + #{amount} WHERE account_no = #{accountNo}") 16 | int updateAccountBalance(@Param("accountNo") String accountNo, @Param("amount") Double amount); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/java/com/pbteach/seatademo/bank2/entity/AccountInfo.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.seatademo.bank2.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | public class AccountInfo implements Serializable { 6 | private Long id; 7 | private String accountName; 8 | private String accountNo; 9 | private String accountPassword; 10 | private Double accountBalance; 11 | 12 | public Long getId() { 13 | return id; 14 | } 15 | public void setId(Long id) { 16 | this.id = id; 17 | } 18 | public String getAccountName() { 19 | return accountName; 20 | } 21 | public void setAccountName(String accountName) { 22 | this.accountName = accountName; 23 | } 24 | public String getAccountNo() { 25 | return accountNo; 26 | } 27 | public void setAccountNo(String accountNo) { 28 | this.accountNo = accountNo; 29 | } 30 | public String getAccountPassword() { 31 | return accountPassword; 32 | } 33 | public void setAccountPassword(String accountPassword) { 34 | this.accountPassword = accountPassword; 35 | } 36 | public Double getAccountBalance() { 37 | return accountBalance; 38 | } 39 | public void setAccountBalance(Double accountBalance) { 40 | this.accountBalance = accountBalance; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/java/com/pbteach/seatademo/bank2/service/AccountInfoService.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.seatademo.bank2.service; 2 | 3 | /** 4 | * Created by Administrator. 5 | */ 6 | public interface AccountInfoService { 7 | 8 | //李四增加金额 9 | public void updateAccountBalance(String accountNo, Double amount); 10 | } 11 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/java/com/pbteach/seatademo/bank2/service/impl/AccountInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.seatademo.bank2.service.impl; 2 | 3 | import com.pbteach.seatademo.bank2.dao.AccountInfoDao; 4 | import com.pbteach.seatademo.bank2.service.AccountInfoService; 5 | import io.seata.core.context.RootContext; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | /** 12 | * @author Administrator 13 | * @version 1.0 14 | **/ 15 | @Service 16 | @Slf4j 17 | public class AccountInfoServiceImpl implements AccountInfoService { 18 | 19 | @Autowired 20 | AccountInfoDao accountInfoDao; 21 | 22 | 23 | @Transactional 24 | @Override 25 | public void updateAccountBalance(String accountNo, Double amount) { 26 | log.info("bank2 service begin,XID:{}",RootContext.getXID()); 27 | //李四增加金额 28 | accountInfoDao.updateAccountBalance(accountNo,amount); 29 | if(amount==3){ 30 | //人为制造异常 31 | throw new RuntimeException("bank2 make exception.."); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/resources/application-local.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 56082 3 | 4 | eureka: 5 | client: 6 | serviceUrl: 7 | defaultZone: http://localhost:56080/eureka/ 8 | 9 | spring: 10 | ##################### DB ##################### 11 | datasource: 12 | ds0: 13 | url: jdbc:mysql://localhost:3306/bank2?useUnicode=true 14 | username: root 15 | password: mysql 16 | type: com.alibaba.druid.pool.DruidDataSource 17 | driver-class-name: com.mysql.jdbc.Driver 18 | initialSize: 5 19 | minIdle: 5 20 | maxActive: 20 21 | maxWait: 60000 22 | timeBetweenEvictionRunsMillis: 60000 23 | minEvictableIdleTimeMillis: 300000 24 | validationQuery: SELECT user() 25 | testWhileIdle: true 26 | testOnBorrow: false 27 | testOnReturn: false 28 | poolPreparedStatements: true 29 | connection-properties: druid.stat.mergeSql:true;druid.stat.slowSqlMillis:5000 30 | 31 | 32 | # cloud: 33 | # alibaba: 34 | # seata: 35 | # tx-service-group: seata-demo-bank1-fescar-service-group 36 | 37 | logging: 38 | level: 39 | root: INFO 40 | io: 41 | seata: DEBUG 42 | org: 43 | springframework: 44 | cloud: 45 | alibaba: 46 | seata: 47 | web: DEBUG 48 | 49 | 50 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: seata-demo-bank2 4 | profiles: 5 | active: local 6 | 7 | main: 8 | allow-bean-definition-overriding: true 9 | 10 | 11 | 12 | jackson: 13 | date-format: yyyy-MM-dd HH:mm:ss 14 | time-zone: GMT+8 15 | 16 | 17 | server: 18 | servlet: 19 | context-path: /bank2 20 | 21 | 22 | 23 | eureka: 24 | instance: 25 | preferIpAddress: true 26 | instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}} 27 | lease-renewal-interval-in-seconds: 5 # 续约更新时间间隔(默认30秒) 28 | lease-expiration-duration-in-seconds: 10 # 续约到期时间(默认90秒) 29 | client: 30 | registry-fetch-interval-seconds: 5 # 抓取服务列表 31 | 32 | management: 33 | endpoints: 34 | web: 35 | exposure: 36 | include: refresh,health,info,env 37 | 38 | 39 | feign: 40 | hystrix: 41 | enabled: true 42 | compression: 43 | request: 44 | enabled: true # 配置请求GZIP压缩 45 | mime-types: ["text/xml","application/xml","application/json"] # 配置压缩支持的MIME TYPE 46 | min-request-size: 2048 # 配置压缩数据大小的下限 47 | response: 48 | enabled: true # 配置响应GZIP压缩 49 | 50 | hystrix: 51 | command: 52 | default: 53 | execution: 54 | isolation: 55 | thread: 56 | timeoutInMilliseconds: 1000 # 设置熔断超时时间 default 1000 57 | timeout: 58 | enabled: true # 打开超时熔断功能 default true 59 | 60 | 61 | ribbon: 62 | ConnectTimeout: 600 # 设置连接超时时间 default 2000 63 | ReadTimeout: 6000 # 设置读取超时时间 default 5000 64 | OkToRetryOnAllOperations: true # 对所有操作请求都进行重试 default false 65 | MaxAutoRetriesNextServer: 2 # 切换实例的重试次数 default 1 66 | MaxAutoRetries: 1 # 对当前实例的重试次数 default 0 67 | 68 | -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/resources/file.conf: -------------------------------------------------------------------------------- 1 | transport { 2 | # tcp udt unix-domain-socket 3 | type = "TCP" 4 | #NIO NATIVE 5 | server = "NIO" 6 | #enable heartbeat 7 | heartbeat = true 8 | #thread factory for netty 9 | thread-factory { 10 | boss-thread-prefix = "NettyBoss" 11 | worker-thread-prefix = "NettyServerNIOWorker" 12 | server-executor-thread-prefix = "NettyServerBizHandler" 13 | share-boss-worker = false 14 | client-selector-thread-prefix = "NettyClientSelector" 15 | client-selector-thread-size = 1 16 | client-worker-thread-prefix = "NettyClientWorkerThread" 17 | # netty boss thread size,will not be used for UDT 18 | boss-thread-size = 1 19 | #auto default pin or 8 20 | worker-thread-size = 8 21 | } 22 | } 23 | ## transaction log store 24 | store { 25 | ## store mode: file、db 26 | mode = "file" 27 | 28 | ## file store 29 | file { 30 | dir = "sessionStore" 31 | 32 | # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions 33 | max-branch-session-size = 16384 34 | # globe session size , if exceeded throws exceptions 35 | max-global-session-size = 512 36 | # file buffer size , if exceeded allocate new buffer 37 | file-write-buffer-cache-size = 16384 38 | # when recover batch read size 39 | session.reload.read_size = 100 40 | # async, sync 41 | flush-disk-mode = async 42 | } 43 | 44 | ## database store 45 | // db { 46 | // driver_class = "com.mysql.jdbc.Driver" 47 | // url = "jdbc:mysql://172.16.0.203:3306/bank?useUnicode=true" 48 | // user = "root" 49 | // password = "pbteach0430" 50 | // } 51 | db { 52 | ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. 53 | datasource = "dbcp" 54 | ## mysql/oracle/h2/oceanbase etc. 55 | db-type = "mysql" 56 | url = "jdbc:mysql://127.0.0.1:3306/seata" 57 | user = "root" 58 | password = "mysql" 59 | min-conn = 1 60 | max-conn = 3 61 | global.table = "global_table" 62 | branch.table = "branch_table" 63 | lock-table = "lock_table" 64 | query-limit = 100 65 | } 66 | 67 | } 68 | 69 | service { 70 | #vgroup->rgroup 71 | vgroup_mapping.seata-demo-bank2-fescar-service-group = "default" 72 | #only support single node 73 | default.grouplist = "127.0.0.1:8888" 74 | #degrade current not support 75 | enableDegrade = false 76 | #disable 77 | disable = false 78 | } 79 | client { 80 | async.commit.buffer.limit = 10000 81 | lock { 82 | retry.internal = 10 83 | retry.times = 30 84 | } 85 | } -------------------------------------------------------------------------------- /dtx-seata-demo/dtx-seata-demo-bank2/src/main/resources/registry.conf: -------------------------------------------------------------------------------- 1 | registry { 2 | # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa 3 | type = "file" 4 | 5 | nacos { 6 | serverAddr = "localhost" 7 | namespace = "public" 8 | cluster = "default" 9 | } 10 | eureka { 11 | serviceUrl = "http://localhost:1001/eureka" 12 | application = "default" 13 | weight = "1" 14 | } 15 | redis { 16 | serverAddr = "localhost:6379" 17 | db = "0" 18 | } 19 | zk { 20 | cluster = "default" 21 | serverAddr = "127.0.0.1:2181" 22 | session.timeout = 6000 23 | connect.timeout = 2000 24 | } 25 | consul { 26 | cluster = "default" 27 | serverAddr = "127.0.0.1:8500" 28 | } 29 | etcd3 { 30 | cluster = "default" 31 | serverAddr = "http://localhost:2379" 32 | } 33 | sofa { 34 | serverAddr = "127.0.0.1:9603" 35 | application = "default" 36 | region = "DEFAULT_ZONE" 37 | datacenter = "DefaultDataCenter" 38 | cluster = "default" 39 | group = "SEATA_GROUP" 40 | addressWaitTime = "3000" 41 | } 42 | file { 43 | name = "file.conf" 44 | } 45 | } 46 | 47 | config { 48 | # file、nacos 、apollo、zk 49 | type = "file" 50 | 51 | nacos { 52 | serverAddr = "localhost" 53 | namespace = "public" 54 | cluster = "default" 55 | } 56 | apollo { 57 | app.id = "seata-server" 58 | apollo.meta = "http://192.168.1.204:8801" 59 | } 60 | zk { 61 | serverAddr = "127.0.0.1:2181" 62 | session.timeout = 6000 63 | connect.timeout = 2000 64 | } 65 | file { 66 | name = "file.conf" 67 | } 68 | } -------------------------------------------------------------------------------- /dtx-seata-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.pbteach.dtx 8 | dtx-parent 9 | 1.0-SNAPSHOT 10 | 11 | dtx-seata-demo 12 | 13 | dtx-seata-demo-bank1 14 | dtx-seata-demo-bank2 15 | 16 | 17 | 2.1.0.RELEASE 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-dependencies 27 | 2.1.3.RELEASE 28 | pom 29 | import 30 | 31 | 32 | 33 | org.springframework.cloud 34 | spring-cloud-dependencies 35 | Greenwich.RELEASE 36 | pom 37 | import 38 | 39 | 40 | 41 | com.alibaba.cloud 42 | spring-cloud-alibaba-dependencies 43 | 2.1.0.RELEASE 44 | pom 45 | import 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-tcc-demo 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-tcc-demo-bank1 13 | 14 | 15 | 16 | org.dromara 17 | hmily-springcloud 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-openfeign 24 | 25 | 26 | 27 | org.springframework.cloud 28 | spring-cloud-starter-netflix-hystrix 29 | 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-netflix-eureka-client 34 | 35 | 36 | 37 | 38 | com.netflix.hystrix 39 | hystrix-javanica 40 | 41 | 42 | 43 | org.springframework.retry 44 | spring-retry 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-web 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-actuator 57 | 58 | 59 | 60 | org.mybatis.spring.boot 61 | mybatis-spring-boot-starter 62 | 63 | 64 | 65 | com.alibaba 66 | druid-spring-boot-starter 67 | 68 | 69 | 70 | mysql 71 | mysql-connector-java 72 | 73 | 74 | 75 | org.projectlombok 76 | lombok 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/java/com/pbteach/dtx/tccdemo/bank1/Bank1TccServer.java: -------------------------------------------------------------------------------- 1 | 2 | package com.pbteach.dtx.tccdemo.bank1; 3 | 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 8 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 9 | import org.springframework.cloud.openfeign.EnableFeignClients; 10 | import org.springframework.context.annotation.ComponentScan; 11 | 12 | 13 | @SpringBootApplication 14 | @EnableDiscoveryClient 15 | @EnableHystrix 16 | @EnableFeignClients(basePackages = {"com.pbteach.dtx.tccdemo.bank1.spring"}) 17 | @ComponentScan({"com.pbteach.dtx.tccdemo.bank1","org.dromara.hmily"}) 18 | public class Bank1TccServer { 19 | 20 | public static void main(String[] args) { 21 | SpringApplication.run(Bank1TccServer.class, args); 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/java/com/pbteach/dtx/tccdemo/bank1/config/DatabaseConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank1.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import org.dromara.hmily.common.config.HmilyDbConfig; 5 | import org.dromara.hmily.core.bootstrap.HmilyTransactionBootstrap; 6 | import org.dromara.hmily.core.service.HmilyInitService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.ApplicationContext; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 13 | import org.springframework.core.env.Environment; 14 | 15 | @Configuration 16 | @EnableAspectJAutoProxy(proxyTargetClass=true) 17 | public class DatabaseConfiguration { 18 | 19 | 20 | private final ApplicationContext applicationContext; 21 | 22 | 23 | @Autowired 24 | private Environment env; 25 | 26 | public DatabaseConfiguration(ApplicationContext applicationContext) { 27 | this.applicationContext = applicationContext; 28 | } 29 | 30 | 31 | @Bean 32 | @ConfigurationProperties(prefix = "spring.datasource.ds0") 33 | public DruidDataSource ds0() { 34 | DruidDataSource druidDataSource = new DruidDataSource(); 35 | return druidDataSource; 36 | } 37 | 38 | 39 | 40 | @Bean 41 | public HmilyTransactionBootstrap hmilyTransactionBootstrap(HmilyInitService hmilyInitService){ 42 | HmilyTransactionBootstrap hmilyTransactionBootstrap = new HmilyTransactionBootstrap(hmilyInitService); 43 | hmilyTransactionBootstrap.setSerializer(env.getProperty("org.dromara.hmily.serializer")); 44 | hmilyTransactionBootstrap.setRecoverDelayTime(Integer.parseInt(env.getProperty("org.dromara.hmily.recoverDelayTime"))); 45 | hmilyTransactionBootstrap.setRetryMax(Integer.parseInt(env.getProperty("org.dromara.hmily.retryMax"))); 46 | hmilyTransactionBootstrap.setScheduledDelay(Integer.parseInt(env.getProperty("org.dromara.hmily.scheduledDelay"))); 47 | hmilyTransactionBootstrap.setScheduledThreadMax(Integer.parseInt(env.getProperty("org.dromara.hmily.scheduledThreadMax"))); 48 | hmilyTransactionBootstrap.setRepositorySupport(env.getProperty("org.dromara.hmily.repositorySupport")); 49 | hmilyTransactionBootstrap.setStarted(Boolean.parseBoolean(env.getProperty("org.dromara.hmily.started"))); 50 | HmilyDbConfig hmilyDbConfig = new HmilyDbConfig(); 51 | hmilyDbConfig.setDriverClassName(env.getProperty("org.dromara.hmily.hmilyDbConfig.driverClassName")); 52 | hmilyDbConfig.setUrl(env.getProperty("org.dromara.hmily.hmilyDbConfig.url")); 53 | hmilyDbConfig.setUsername(env.getProperty("org.dromara.hmily.hmilyDbConfig.username")); 54 | hmilyDbConfig.setPassword(env.getProperty("org.dromara.hmily.hmilyDbConfig.password")); 55 | hmilyTransactionBootstrap.setHmilyDbConfig(hmilyDbConfig); 56 | return hmilyTransactionBootstrap; 57 | } 58 | 59 | 60 | /*@Bean 61 | @ConfigurationProperties(prefix = "org.dromara.hmily") 62 | public HmilyConfig hmilyConfig(){ 63 | return new HmilyConfig(); 64 | } 65 | 66 | 67 | 68 | @Bean 69 | public HmilyTransactionBootstrap hmilyTransactionBootstrap(HmilyInitService hmilyInitService, HmilyConfig hmilyConfig){ 70 | HmilyTransactionBootstrap hmilyTransactionBootstrap = new HmilyTransactionBootstrap(hmilyInitService); 71 | return hmilyTransactionBootstrap; 72 | }*/ 73 | 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/java/com/pbteach/dtx/tccdemo/bank1/controller/Bank1Controller.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank1.controller; 2 | 3 | import com.pbteach.dtx.tccdemo.bank1.service.AccountInfoService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | /** 10 | * @author Administrator 11 | * @version 1.0 12 | **/ 13 | @RestController 14 | public class Bank1Controller { 15 | @Autowired 16 | AccountInfoService accountInfoService; 17 | 18 | @RequestMapping("/transfer") 19 | public Boolean transfer(@RequestParam("amount") Double amount) { 20 | this.accountInfoService.updateAccountBalance("1", amount); 21 | return true; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/java/com/pbteach/dtx/tccdemo/bank1/dao/AccountInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank1.dao; 2 | 3 | import org.apache.ibatis.annotations.*; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Mapper 7 | @Component 8 | public interface AccountInfoDao { 9 | @Update("update account_info set account_balance=account_balance - #{amount} where account_balance>=#{amount} and account_no=#{accountNo} ") 10 | int subtractAccountBalance(@Param("accountNo") String accountNo, @Param("amount") Double amount); 11 | 12 | @Update("update account_info set account_balance=account_balance + #{amount} where account_no=#{accountNo} ") 13 | int addAccountBalance(@Param("accountNo") String accountNo, @Param("amount") Double amount); 14 | 15 | 16 | /** 17 | * 增加某分支事务try执行记录 18 | * @param localTradeNo 本地事务编号 19 | * @return 20 | */ 21 | @Insert("insert into local_try_log values(#{txNo},now());") 22 | int addTry(String localTradeNo); 23 | 24 | @Insert("insert into local_confirm_log values(#{txNo},now());") 25 | int addConfirm(String localTradeNo); 26 | 27 | @Insert("insert into local_cancel_log values(#{txNo},now());") 28 | int addCancel(String localTradeNo); 29 | 30 | /** 31 | * 查询分支事务try是否已执行 32 | * @param localTradeNo 本地事务编号 33 | * @return 34 | */ 35 | @Select("select count(1) from local_try_log where tx_no = #{txNo} ") 36 | int isExistTry(String localTradeNo); 37 | /** 38 | * 查询分支事务confirm是否已执行 39 | * @param localTradeNo 本地事务编号 40 | * @return 41 | */ 42 | @Select("select count(1) from local_confirm_log where tx_no = #{txNo} ") 43 | int isExistConfirm(String localTradeNo); 44 | 45 | /** 46 | * 查询分支事务cancel是否已执行 47 | * @param localTradeNo 本地事务编号 48 | * @return 49 | */ 50 | @Select("select count(1) from local_cancel_log where tx_no = #{txNo} ") 51 | int isExistCancel(String localTradeNo); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/java/com/pbteach/dtx/tccdemo/bank1/entity/AccountInfo.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank1.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class AccountInfo implements Serializable { 9 | private Long id; 10 | private String accountName; 11 | private String accountNo; 12 | private String accountPassword; 13 | private Double accountBalance; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/java/com/pbteach/dtx/tccdemo/bank1/service/AccountInfoService.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank1.service; 2 | 3 | /** 4 | * Created by Administrator. 5 | */ 6 | public interface AccountInfoService { 7 | 8 | //账户扣款 9 | public void updateAccountBalance(String accountNo, Double amount); 10 | } 11 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/java/com/pbteach/dtx/tccdemo/bank1/service/impl/AccountInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank1.service.impl; 2 | 3 | import com.pbteach.dtx.tccdemo.bank1.dao.AccountInfoDao; 4 | import com.pbteach.dtx.tccdemo.bank1.service.AccountInfoService; 5 | import com.pbteach.dtx.tccdemo.bank1.spring.Bank2Client; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.dromara.hmily.annotation.Hmily; 8 | import org.dromara.hmily.core.concurrent.threadlocal.HmilyTransactionContextLocal; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | /** 14 | * @author Administrator 15 | * @version 1.0 16 | **/ 17 | @Service 18 | @Slf4j 19 | public class AccountInfoServiceImpl implements AccountInfoService { 20 | 21 | @Autowired 22 | AccountInfoDao accountInfoDao; 23 | 24 | @Autowired 25 | Bank2Client bank2Client; 26 | 27 | // 账户扣款,就是tcc的try方法 28 | 29 | /** 30 | * try幂等校验 31 | * try悬挂处理 32 | * 检查余额是够扣减金额 33 | * 扣减金额 34 | * @param accountNo 35 | * @param amount 36 | */ 37 | @Override 38 | @Transactional 39 | //只要标记@Hmily就是try方法,在注解中指定confirm、cancel两个方法的名字 40 | @Hmily(confirmMethod="commit",cancelMethod="rollback") 41 | public void updateAccountBalance(String accountNo, Double amount) { 42 | //获取全局事务id 43 | String transId = HmilyTransactionContextLocal.getInstance().get().getTransId(); 44 | log.info("bank1 try begin 开始执行...xid:{}",transId); 45 | //幂等判断 判断local_try_log表中是否有try日志记录,如果有则不再执行 46 | if(accountInfoDao.isExistTry(transId)>0){ 47 | log.info("bank1 try 已经执行,无需重复执行,xid:{}",transId); 48 | return ; 49 | } 50 | 51 | //try悬挂处理,如果cancel、confirm有一个已经执行了,try不再执行 52 | if(accountInfoDao.isExistConfirm(transId)>0 || accountInfoDao.isExistCancel(transId)>0){ 53 | log.info("bank1 try悬挂处理 cancel或confirm已经执行,不允许执行try,xid:{}",transId); 54 | return ; 55 | } 56 | 57 | //扣减金额 58 | if(accountInfoDao.subtractAccountBalance(accountNo, amount)<=0){ 59 | //扣减失败 60 | throw new RuntimeException("bank1 try 扣减金额失败,xid:{}"+transId); 61 | } 62 | //插入try执行记录,用于幂等判断 63 | accountInfoDao.addTry(transId); 64 | 65 | //远程调用李四,转账 66 | if(!bank2Client.transfer(amount)){ 67 | throw new RuntimeException("bank1 远程调用李四微服务失败,xid:{}"+transId); 68 | } 69 | if(amount == 2){ 70 | throw new RuntimeException("人为制造异常,xid:{}"+transId); 71 | } 72 | log.info("bank1 try end 结束执行...xid:{}",transId); 73 | } 74 | 75 | //confirm方法 76 | @Transactional 77 | public void commit(String accountNo, Double amount){ 78 | //获取全局事务id 79 | String transId = HmilyTransactionContextLocal.getInstance().get().getTransId(); 80 | log.info("bank1 confirm begin 开始执行...xid:{},accountNo:{},amount:{}",transId,accountNo,amount); 81 | } 82 | 83 | 84 | 85 | /** cancel方法 86 | * cancel幂等校验 87 | * cancel空回滚处理 88 | * 增加可用余额 89 | * @param accountNo 90 | * @param amount 91 | */ 92 | @Transactional 93 | public void rollback(String accountNo, Double amount){ 94 | //获取全局事务id 95 | String transId = HmilyTransactionContextLocal.getInstance().get().getTransId(); 96 | log.info("bank1 cancel begin 开始执行...xid:{}",transId); 97 | // cancel幂等校验 98 | if(accountInfoDao.isExistCancel(transId)>0){ 99 | log.info("bank1 cancel 已经执行,无需重复执行,xid:{}",transId); 100 | return ; 101 | } 102 | //cancel空回滚处理,如果try没有执行,cancel不允许执行 103 | if(accountInfoDao.isExistTry(transId)<=0){ 104 | log.info("bank1 空回滚处理,try没有执行,不允许cancel执行,xid:{}",transId); 105 | return ; 106 | } 107 | // 增加可用余额 108 | accountInfoDao.addAccountBalance(accountNo,amount); 109 | //插入一条cancel的执行记录 110 | accountInfoDao.addCancel(transId); 111 | log.info("bank1 cancel end 结束执行...xid:{}",transId); 112 | 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/java/com/pbteach/dtx/tccdemo/bank1/spring/Bank2Client.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank1.spring; 2 | 3 | import org.dromara.hmily.annotation.Hmily; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | 8 | /** 9 | * Created by Administrator. 10 | */ 11 | @FeignClient(value="tcc-demo-bank2",fallback=Bank2ClientFallback.class) 12 | public interface Bank2Client { 13 | //远程调用李四的微服务 14 | @GetMapping("/bank2/transfer") 15 | @Hmily 16 | public Boolean transfer(@RequestParam("amount") Double amount); 17 | } 18 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/java/com/pbteach/dtx/tccdemo/bank1/spring/Bank2ClientFallback.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank1.spring; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | /** 6 | * @author Administrator 7 | * @version 1.0 8 | **/ 9 | @Component 10 | public class Bank2ClientFallback implements Bank2Client { 11 | 12 | @Override 13 | public Boolean transfer(Double amount) { 14 | 15 | return false; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/resources/application-local.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 56081 3 | 4 | eureka: 5 | client: 6 | serviceUrl: 7 | defaultZone: http://localhost:56080/eureka/ 8 | 9 | spring: 10 | ##################### DB ##################### 11 | datasource: 12 | ds0: 13 | url: jdbc:mysql://localhost:3306/bank1?useUnicode=true 14 | username: root 15 | password: mysql 16 | type: com.alibaba.druid.pool.DruidDataSource 17 | driver-class-name: com.mysql.jdbc.Driver 18 | initialSize: 5 19 | minIdle: 5 20 | maxActive: 20 21 | maxWait: 60000 22 | timeBetweenEvictionRunsMillis: 60000 23 | minEvictableIdleTimeMillis: 300000 24 | validationQuery: SELECT user() 25 | testWhileIdle: true 26 | testOnBorrow: false 27 | testOnReturn: false 28 | poolPreparedStatements: true 29 | connection-properties: druid.stat.mergeSql:true;druid.stat.slowSqlMillis:5000 30 | 31 | org: 32 | dromara: 33 | hmily : 34 | serializer : kryo 35 | recoverDelayTime : 30 36 | retryMax : 30 37 | scheduledDelay : 30 38 | scheduledThreadMax : 10 39 | repositorySupport : db 40 | started: true 41 | hmilyDbConfig : 42 | driverClassName : com.mysql.jdbc.Driver 43 | url : jdbc:mysql://localhost:3306/hmily?useUnicode=true 44 | username : root 45 | password : mysql 46 | 47 | 48 | 49 | logging: 50 | level: 51 | root: info 52 | org.springframework.web: info 53 | org.apache.ibatis: info 54 | org.dromara.hmily.bonuspoint: debug 55 | org.dromara.hmily.lottery: debug 56 | org.dromara.hmily: debug 57 | io.netty: info 58 | com.pbteach.wanxintx.seatademo.bank2: debug 59 | 60 | 61 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank1/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: tcc-demo-bank1 4 | profiles: 5 | active: local 6 | 7 | main: 8 | allow-bean-definition-overriding: true 9 | 10 | 11 | 12 | jackson: 13 | date-format: yyyy-MM-dd HH:mm:ss 14 | time-zone: GMT+8 15 | 16 | 17 | server: 18 | servlet: 19 | context-path: /bank1 20 | 21 | 22 | 23 | eureka: 24 | instance: 25 | preferIpAddress: true 26 | instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}} 27 | lease-renewal-interval-in-seconds: 5 # 续约更新时间间隔(默认30秒) 28 | lease-expiration-duration-in-seconds: 10 # 续约到期时间(默认90秒) 29 | client: 30 | registry-fetch-interval-seconds: 5 # 抓取服务列表 31 | 32 | management: 33 | endpoints: 34 | web: 35 | exposure: 36 | include: refresh,health,info,env 37 | 38 | 39 | feign: 40 | hystrix: 41 | enabled: true 42 | compression: 43 | request: 44 | enabled: true # 配置请求GZIP压缩 45 | mime-types: ["text/xml","application/xml","application/json"] # 配置压缩支持的MIME TYPE 46 | min-request-size: 2048 # 配置压缩数据大小的下限 47 | response: 48 | enabled: true # 配置响应GZIP压缩 49 | 50 | hystrix: 51 | command: 52 | default: 53 | execution: 54 | isolation: 55 | thread: 56 | timeoutInMilliseconds: 1000 # 设置熔断超时时间 default 1000 57 | timeout: 58 | enabled: true # 打开超时熔断功能 default true 59 | 60 | 61 | ribbon: 62 | ConnectTimeout: 600 # 设置连接超时时间 default 2000 63 | ReadTimeout: 6000 # 设置读取超时时间 default 5000 64 | OkToRetryOnAllOperations: true # 对所有操作请求都进行重试 default false 65 | MaxAutoRetriesNextServer: 2 # 切换实例的重试次数 default 1 66 | MaxAutoRetries: 1 # 对当前实例的重试次数 default 0 67 | 68 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-tcc-demo 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-tcc-demo-bank2 13 | 14 | 15 | 16 | org.dromara 17 | hmily-springcloud 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-openfeign 24 | 25 | 26 | 27 | org.springframework.cloud 28 | spring-cloud-starter-netflix-hystrix 29 | 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-netflix-eureka-client 34 | 35 | 36 | 37 | 38 | com.netflix.hystrix 39 | hystrix-javanica 40 | 41 | 42 | 43 | org.springframework.retry 44 | spring-retry 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-web 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-actuator 57 | 58 | 59 | 60 | org.mybatis.spring.boot 61 | mybatis-spring-boot-starter 62 | 63 | 64 | 65 | com.alibaba 66 | druid-spring-boot-starter 67 | 68 | 69 | 70 | mysql 71 | mysql-connector-java 72 | 73 | 74 | 75 | org.projectlombok 76 | lombok 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/src/main/java/com/pbteach/dtx/tccdemo/bank2/Bank2TccServer.java: -------------------------------------------------------------------------------- 1 | 2 | package com.pbteach.dtx.tccdemo.bank2; 3 | 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 8 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 9 | import org.springframework.context.annotation.ComponentScan; 10 | 11 | 12 | @SpringBootApplication 13 | @EnableDiscoveryClient 14 | @EnableHystrix 15 | @ComponentScan({"com.pbteach.dtx.tccdemo.bank2","org.dromara.hmily"}) 16 | public class Bank2TccServer { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(Bank2TccServer.class, args); 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/src/main/java/com/pbteach/dtx/tccdemo/bank2/config/DatabaseConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank2.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import org.dromara.hmily.common.config.HmilyDbConfig; 5 | import org.dromara.hmily.core.bootstrap.HmilyTransactionBootstrap; 6 | import org.dromara.hmily.core.service.HmilyInitService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.ApplicationContext; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 13 | import org.springframework.core.env.Environment; 14 | 15 | @Configuration 16 | @EnableAspectJAutoProxy(proxyTargetClass=true) 17 | public class DatabaseConfiguration { 18 | 19 | @Autowired 20 | private Environment env; 21 | 22 | private final ApplicationContext applicationContext; 23 | 24 | public DatabaseConfiguration(ApplicationContext applicationContext) { 25 | this.applicationContext = applicationContext; 26 | } 27 | 28 | 29 | @Bean 30 | @ConfigurationProperties(prefix = "spring.datasource.ds1") 31 | public DruidDataSource ds1() { 32 | DruidDataSource druidDataSource = new DruidDataSource(); 33 | return druidDataSource; 34 | } 35 | 36 | @Bean 37 | public HmilyTransactionBootstrap hmilyTransactionBootstrap(HmilyInitService hmilyInitService){ 38 | HmilyTransactionBootstrap hmilyTransactionBootstrap = new HmilyTransactionBootstrap(hmilyInitService); 39 | hmilyTransactionBootstrap.setSerializer(env.getProperty("org.dromara.hmily.serializer")); 40 | hmilyTransactionBootstrap.setRecoverDelayTime(Integer.parseInt(env.getProperty("org.dromara.hmily.recoverDelayTime"))); 41 | hmilyTransactionBootstrap.setRetryMax(Integer.parseInt(env.getProperty("org.dromara.hmily.retryMax"))); 42 | hmilyTransactionBootstrap.setScheduledDelay(Integer.parseInt(env.getProperty("org.dromara.hmily.scheduledDelay"))); 43 | hmilyTransactionBootstrap.setScheduledThreadMax(Integer.parseInt(env.getProperty("org.dromara.hmily.scheduledThreadMax"))); 44 | hmilyTransactionBootstrap.setRepositorySupport(env.getProperty("org.dromara.hmily.repositorySupport")); 45 | hmilyTransactionBootstrap.setStarted(Boolean.parseBoolean(env.getProperty("org.dromara.hmily.started"))); 46 | HmilyDbConfig hmilyDbConfig = new HmilyDbConfig(); 47 | hmilyDbConfig.setDriverClassName(env.getProperty("org.dromara.hmily.hmilyDbConfig.driverClassName")); 48 | hmilyDbConfig.setUrl(env.getProperty("org.dromara.hmily.hmilyDbConfig.url")); 49 | hmilyDbConfig.setUsername(env.getProperty("org.dromara.hmily.hmilyDbConfig.username")); 50 | hmilyDbConfig.setPassword(env.getProperty("org.dromara.hmily.hmilyDbConfig.password")); 51 | hmilyTransactionBootstrap.setHmilyDbConfig(hmilyDbConfig); 52 | return hmilyTransactionBootstrap; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/src/main/java/com/pbteach/dtx/tccdemo/bank2/controller/Bank2Controller.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank2.controller; 2 | 3 | import com.pbteach.dtx.tccdemo.bank2.service.AccountInfoService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | /** 10 | * @author Administrator 11 | * @version 1.0 12 | **/ 13 | @RestController 14 | public class Bank2Controller { 15 | @Autowired 16 | AccountInfoService accountInfoService; 17 | 18 | @RequestMapping("/transfer") 19 | public Boolean transfer(@RequestParam("amount") Double amount) { 20 | this.accountInfoService.updateAccountBalance("2", amount); 21 | return true; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/src/main/java/com/pbteach/dtx/tccdemo/bank2/dao/AccountInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank2.dao; 2 | 3 | import org.apache.ibatis.annotations.*; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | @Mapper 8 | public interface AccountInfoDao { 9 | 10 | @Update("update account_info set account_balance=account_balance + #{amount} where account_no=#{accountNo} ") 11 | int addAccountBalance(@Param("accountNo") String accountNo, @Param("amount") Double amount); 12 | 13 | 14 | /** 15 | * 增加某分支事务try执行记录 16 | * @param localTradeNo 本地事务编号 17 | * @return 18 | */ 19 | @Insert("insert into local_try_log values(#{txNo},now());") 20 | int addTry(String localTradeNo); 21 | 22 | @Insert("insert into local_confirm_log values(#{txNo},now());") 23 | int addConfirm(String localTradeNo); 24 | 25 | @Insert("insert into local_cancel_log values(#{txNo},now());") 26 | int addCancel(String localTradeNo); 27 | 28 | /** 29 | * 查询分支事务try是否已执行 30 | * @param localTradeNo 本地事务编号 31 | * @return 32 | */ 33 | @Select("select count(1) from local_try_log where tx_no = #{txNo} ") 34 | int isExistTry(String localTradeNo); 35 | /** 36 | * 查询分支事务confirm是否已执行 37 | * @param localTradeNo 本地事务编号 38 | * @return 39 | */ 40 | @Select("select count(1) from local_confirm_log where tx_no = #{txNo} ") 41 | int isExistConfirm(String localTradeNo); 42 | 43 | /** 44 | * 查询分支事务cancel是否已执行 45 | * @param localTradeNo 本地事务编号 46 | * @return 47 | */ 48 | @Select("select count(1) from local_cancel_log where tx_no = #{txNo} ") 49 | int isExistCancel(String localTradeNo); 50 | 51 | } 52 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/src/main/java/com/pbteach/dtx/tccdemo/bank2/entity/AccountInfo.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank2.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class AccountInfo implements Serializable { 9 | private Long id; 10 | private String accountName; 11 | private String accountNo; 12 | private String accountPassword; 13 | private Double accountBalance; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/src/main/java/com/pbteach/dtx/tccdemo/bank2/service/AccountInfoService.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank2.service; 2 | 3 | /** 4 | * Created by Administrator. 5 | */ 6 | public interface AccountInfoService { 7 | 8 | //账户扣款 9 | public void updateAccountBalance(String accountNo, Double amount); 10 | } 11 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/src/main/java/com/pbteach/dtx/tccdemo/bank2/service/impl/AccountInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.tccdemo.bank2.service.impl; 2 | 3 | import com.pbteach.dtx.tccdemo.bank2.dao.AccountInfoDao; 4 | import com.pbteach.dtx.tccdemo.bank2.service.AccountInfoService; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.dromara.hmily.annotation.Hmily; 7 | import org.dromara.hmily.core.concurrent.threadlocal.HmilyTransactionContextLocal; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | /** 13 | * @author Administrator 14 | * @version 1.0 15 | **/ 16 | @Service 17 | @Slf4j 18 | public class AccountInfoServiceImpl implements AccountInfoService { 19 | 20 | @Autowired 21 | AccountInfoDao accountInfoDao; 22 | 23 | @Override 24 | @Hmily(confirmMethod="confirmMethod", cancelMethod="cancelMethod") 25 | public void updateAccountBalance(String accountNo, Double amount) { 26 | //获取全局事务id 27 | String transId = HmilyTransactionContextLocal.getInstance().get().getTransId(); 28 | log.info("bank2 try begin 开始执行...xid:{}",transId); 29 | } 30 | 31 | /** 32 | * confirm方法 33 | * confirm幂等校验 34 | * 正式增加金额 35 | * @param accountNo 36 | * @param amount 37 | */ 38 | @Transactional 39 | public void confirmMethod(String accountNo, Double amount){ 40 | //获取全局事务id 41 | String transId = HmilyTransactionContextLocal.getInstance().get().getTransId(); 42 | log.info("bank2 confirm begin 开始执行...xid:{}",transId); 43 | if(accountInfoDao.isExistConfirm(transId)>0){ 44 | log.info("bank2 confirm 已经执行,无需重复执行...xid:{}",transId); 45 | return ; 46 | } 47 | //增加金额 48 | accountInfoDao.addAccountBalance(accountNo,amount); 49 | //增加一条confirm日志,用于幂等 50 | accountInfoDao.addConfirm(transId); 51 | log.info("bank2 confirm end 结束执行...xid:{}",transId); 52 | } 53 | 54 | 55 | 56 | /** 57 | * @param accountNo 58 | * @param amount 59 | */ 60 | public void cancelMethod(String accountNo, Double amount){ 61 | //获取全局事务id 62 | String transId = HmilyTransactionContextLocal.getInstance().get().getTransId(); 63 | log.info("bank2 cancel begin 开始执行...xid:{}",transId); 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/src/main/resources/application-local.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 56082 3 | 4 | eureka: 5 | client: 6 | serviceUrl: 7 | defaultZone: http://localhost:56080/eureka/ 8 | 9 | spring: 10 | ##################### DB ##################### 11 | datasource: 12 | ds1: 13 | url: jdbc:mysql://localhost:3306/bank2?useUnicode=true 14 | username: root 15 | password: mysql 16 | type: com.alibaba.druid.pool.DruidDataSource 17 | driver-class-name: com.mysql.jdbc.Driver 18 | initialSize: 5 19 | minIdle: 5 20 | maxActive: 20 21 | maxWait: 60000 22 | timeBetweenEvictionRunsMillis: 60000 23 | minEvictableIdleTimeMillis: 300000 24 | validationQuery: SELECT user() 25 | testWhileIdle: true 26 | testOnBorrow: false 27 | testOnReturn: false 28 | poolPreparedStatements: true 29 | connection-properties: druid.stat.mergeSql:true;druid.stat.slowSqlMillis:5000 30 | 31 | org: 32 | dromara: 33 | hmily : 34 | serializer : kryo 35 | recoverDelayTime : 30 36 | retryMax : 30 37 | scheduledDelay : 30 38 | scheduledThreadMax : 10 39 | repositorySupport : db 40 | started: false 41 | hmilyDbConfig : 42 | driverClassName : com.mysql.jdbc.Driver 43 | url : jdbc:mysql://localhost:3306/hmily?useUnicode=true 44 | username : root 45 | password : mysql 46 | 47 | 48 | 49 | logging: 50 | level: 51 | root: info 52 | org.springframework.web: info 53 | org.apache.ibatis: info 54 | org.dromara.hmily.bonuspoint: debug 55 | org.dromara.hmily.lottery: debug 56 | org.dromara.hmily: debug 57 | io.netty: info 58 | com.pbteach.wanxintx.seatademo.bank2: debug 59 | 60 | 61 | -------------------------------------------------------------------------------- /dtx-tcc-demo/dtx-tcc-demo-bank2/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: tcc-demo-bank2 4 | profiles: 5 | active: local 6 | 7 | main: 8 | allow-bean-definition-overriding: true 9 | 10 | 11 | 12 | jackson: 13 | date-format: yyyy-MM-dd HH:mm:ss 14 | time-zone: GMT+8 15 | 16 | 17 | server: 18 | servlet: 19 | context-path: /bank2 20 | 21 | 22 | 23 | eureka: 24 | instance: 25 | preferIpAddress: true 26 | instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}} 27 | lease-renewal-interval-in-seconds: 5 # 续约更新时间间隔(默认30秒) 28 | lease-expiration-duration-in-seconds: 10 # 续约到期时间(默认90秒) 29 | client: 30 | registry-fetch-interval-seconds: 5 # 抓取服务列表 31 | 32 | management: 33 | endpoints: 34 | web: 35 | exposure: 36 | include: refresh,health,info,env 37 | 38 | 39 | feign: 40 | hystrix: 41 | enabled: true 42 | compression: 43 | request: 44 | enabled: true # 配置请求GZIP压缩 45 | mime-types: ["text/xml","application/xml","application/json"] # 配置压缩支持的MIME TYPE 46 | min-request-size: 2048 # 配置压缩数据大小的下限 47 | response: 48 | enabled: true # 配置响应GZIP压缩 49 | 50 | hystrix: 51 | command: 52 | default: 53 | execution: 54 | isolation: 55 | thread: 56 | timeoutInMilliseconds: 1000 # 设置熔断超时时间 default 1000 57 | timeout: 58 | enabled: true # 打开超时熔断功能 default true 59 | 60 | 61 | ribbon: 62 | ConnectTimeout: 600 # 设置连接超时时间 default 2000 63 | ReadTimeout: 6000 # 设置读取超时时间 default 5000 64 | OkToRetryOnAllOperations: true # 对所有操作请求都进行重试 default false 65 | MaxAutoRetriesNextServer: 2 # 切换实例的重试次数 default 1 66 | MaxAutoRetries: 1 # 对当前实例的重试次数 default 0 67 | 68 | -------------------------------------------------------------------------------- /dtx-tcc-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-parent 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-tcc-demo 13 | 14 | 15 | 16 | 17 | 18 | org.dromara 19 | hmily-springcloud 20 | 2.0.4-RELEASE 21 | 22 | 23 | 24 | 25 | org.springframework.cloud 26 | spring-cloud-dependencies 27 | Greenwich.RELEASE 28 | pom 29 | import 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-dependencies 35 | 2.1.3.RELEASE 36 | pom 37 | import 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-txmsg-demo 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-txmsg-demo-bank1 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-web 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-actuator 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-configuration-processor 28 | true 29 | 30 | 31 | 32 | org.mybatis.spring.boot 33 | mybatis-spring-boot-starter 34 | 35 | 36 | 37 | com.alibaba 38 | druid-spring-boot-starter 39 | 40 | 41 | 42 | mysql 43 | mysql-connector-java 44 | 45 | 46 | 47 | 48 | javax.interceptor 49 | javax.interceptor-api 50 | 51 | 52 | 53 | 54 | io.springfox 55 | springfox-swagger2 56 | 57 | 58 | io.springfox 59 | springfox-swagger-ui 60 | 61 | 62 | 63 | org.projectlombok 64 | lombok 65 | 66 | 67 | 68 | org.apache.rocketmq 69 | rocketmq-spring-boot-starter 70 | 2.0.2 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/java/com/pbteach/dtx/txmsgdemo/bank1/TxMsgBank1Service.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank1; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | @SpringBootApplication 8 | public class TxMsgBank1Service { 9 | 10 | public static void main(String[] args) { 11 | SpringApplication.run(TxMsgBank1Service.class, args); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/java/com/pbteach/dtx/txmsgdemo/bank1/controller/AccountInfoController.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank1.controller; 2 | 3 | import com.pbteach.dtx.txmsgdemo.bank1.model.AccountChangeEvent; 4 | import com.pbteach.dtx.txmsgdemo.bank1.service.AccountInfoService; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import java.util.UUID; 12 | 13 | /** 14 | * @author Administrator 15 | * @version 1.0 16 | **/ 17 | @RestController 18 | @Slf4j 19 | public class AccountInfoController { 20 | @Autowired 21 | private AccountInfoService accountInfoService; 22 | 23 | @GetMapping(value = "/transfer") 24 | public String transfer(@RequestParam("accountNo")String accountNo, @RequestParam("amount") Double amount){ 25 | //创建一个事务id,作为消息内容发到mq 26 | String tx_no = UUID.randomUUID().toString(); 27 | AccountChangeEvent accountChangeEvent = new AccountChangeEvent(accountNo,amount,tx_no); 28 | //发送消息 29 | accountInfoService.sendUpdateAccountBalance(accountChangeEvent); 30 | return "转账成功"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/java/com/pbteach/dtx/txmsgdemo/bank1/dao/AccountInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank1.dao; 2 | 3 | import com.pbteach.dtx.txmsgdemo.bank1.entity.AccountInfo; 4 | import org.apache.ibatis.annotations.*; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Mapper 8 | @Component 9 | public interface AccountInfoDao { 10 | @Update("update account_info set account_balance=account_balance+#{amount} where account_no=#{accountNo}") 11 | int updateAccountBalance(@Param("accountNo") String accountNo, @Param("amount") Double amount); 12 | 13 | 14 | @Select("select * from account_info where where account_no=#{accountNo}") 15 | AccountInfo findByIdAccountNo(@Param("accountNo") String accountNo); 16 | 17 | 18 | 19 | @Select("select count(1) from de_duplication where tx_no = #{txNo}") 20 | int isExistTx(String txNo); 21 | 22 | 23 | @Insert("insert into de_duplication values(#{txNo},now());") 24 | int addTx(String txNo); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/java/com/pbteach/dtx/txmsgdemo/bank1/entity/AccountInfo.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank1.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class AccountInfo implements Serializable { 9 | private Long id; 10 | private String accountName; 11 | private String accountNo; 12 | private String accountPassword; 13 | private Double accountBalance; 14 | } 15 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/java/com/pbteach/dtx/txmsgdemo/bank1/message/ProducerTxmsgListener.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank1.message; 2 | 3 | import com.pbteach.dtx.txmsgdemo.bank1.dao.AccountInfoDao; 4 | import com.pbteach.dtx.txmsgdemo.bank1.model.AccountChangeEvent; 5 | import com.pbteach.dtx.txmsgdemo.bank1.service.AccountInfoService; 6 | import com.alibaba.fastjson.JSONObject; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; 9 | import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; 10 | import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.messaging.Message; 13 | import org.springframework.stereotype.Component; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | /** 17 | * @author Administrator 18 | * @version 1.0 19 | **/ 20 | @Component 21 | @Slf4j 22 | @RocketMQTransactionListener(txProducerGroup = "producer_group_txmsg_bank1") 23 | public class ProducerTxmsgListener implements RocketMQLocalTransactionListener { 24 | 25 | @Autowired 26 | AccountInfoService accountInfoService; 27 | 28 | @Autowired 29 | AccountInfoDao accountInfoDao; 30 | 31 | //事务消息发送后的回调方法,当消息发送给mq成功,此方法被回调 32 | @Override 33 | @Transactional 34 | public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) { 35 | 36 | try { 37 | //解析message,转成AccountChangeEvent 38 | String messageString = new String((byte[]) message.getPayload()); 39 | JSONObject jsonObject = JSONObject.parseObject(messageString); 40 | String accountChangeString = jsonObject.getString("accountChange"); 41 | //将accountChange(json)转成AccountChangeEvent 42 | AccountChangeEvent accountChangeEvent = JSONObject.parseObject(accountChangeString, AccountChangeEvent.class); 43 | //执行本地事务,扣减金额 44 | accountInfoService.doUpdateAccountBalance(accountChangeEvent); 45 | //当返回RocketMQLocalTransactionState.COMMIT,自动向mq发送commit消息,mq将消息的状态改为可消费 46 | return RocketMQLocalTransactionState.COMMIT; 47 | } catch (Exception e) { 48 | e.printStackTrace(); 49 | return RocketMQLocalTransactionState.ROLLBACK; 50 | } 51 | 52 | 53 | } 54 | 55 | //事务状态回查,查询是否扣减金额 56 | @Override 57 | public RocketMQLocalTransactionState checkLocalTransaction(Message message) { 58 | //解析message,转成AccountChangeEvent 59 | String messageString = new String((byte[]) message.getPayload()); 60 | JSONObject jsonObject = JSONObject.parseObject(messageString); 61 | String accountChangeString = jsonObject.getString("accountChange"); 62 | //将accountChange(json)转成AccountChangeEvent 63 | AccountChangeEvent accountChangeEvent = JSONObject.parseObject(accountChangeString, AccountChangeEvent.class); 64 | //事务id 65 | String txNo = accountChangeEvent.getTxNo(); 66 | int existTx = accountInfoDao.isExistTx(txNo); 67 | if(existTx>0){ 68 | return RocketMQLocalTransactionState.COMMIT; 69 | }else{ 70 | return RocketMQLocalTransactionState.UNKNOWN; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/java/com/pbteach/dtx/txmsgdemo/bank1/model/AccountChangeEvent.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank1.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class AccountChangeEvent implements Serializable { 13 | /** 14 | * 账号 15 | */ 16 | private String accountNo; 17 | /** 18 | * 变动金额 19 | */ 20 | private double amount; 21 | /** 22 | * 事务号 23 | */ 24 | private String txNo; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/java/com/pbteach/dtx/txmsgdemo/bank1/service/AccountInfoService.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank1.service; 2 | 3 | import com.pbteach.dtx.txmsgdemo.bank1.model.AccountChangeEvent; 4 | 5 | /** 6 | * Created by Administrator. 7 | */ 8 | public interface AccountInfoService { 9 | 10 | //向mq发送转账消息 11 | public void sendUpdateAccountBalance(AccountChangeEvent accountChangeEvent); 12 | //更新账户,扣减金额 13 | public void doUpdateAccountBalance(AccountChangeEvent accountChangeEvent); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/java/com/pbteach/dtx/txmsgdemo/bank1/service/impl/AccountInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank1.service.impl; 2 | 3 | import com.pbteach.dtx.txmsgdemo.bank1.dao.AccountInfoDao; 4 | import com.pbteach.dtx.txmsgdemo.bank1.model.AccountChangeEvent; 5 | import com.pbteach.dtx.txmsgdemo.bank1.service.AccountInfoService; 6 | import com.alibaba.fastjson.JSONObject; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.apache.rocketmq.spring.core.RocketMQTemplate; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.messaging.Message; 11 | import org.springframework.messaging.support.MessageBuilder; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | /** 16 | * @author Administrator 17 | * @version 1.0 18 | **/ 19 | @Service 20 | @Slf4j 21 | public class AccountInfoServiceImpl implements AccountInfoService { 22 | 23 | @Autowired 24 | AccountInfoDao accountInfoDao; 25 | 26 | @Autowired 27 | RocketMQTemplate rocketMQTemplate; 28 | 29 | 30 | //向mq发送转账消息 31 | @Override 32 | public void sendUpdateAccountBalance(AccountChangeEvent accountChangeEvent) { 33 | 34 | //将accountChangeEvent转成json 35 | JSONObject jsonObject =new JSONObject(); 36 | jsonObject.put("accountChange",accountChangeEvent); 37 | String jsonString = jsonObject.toJSONString(); 38 | //生成message类型 39 | Message message = MessageBuilder.withPayload(jsonString).build(); 40 | //发送一条事务消息 41 | /** 42 | * String txProducerGroup 生产组 43 | * String destination topic, 44 | * Message message, 消息内容 45 | * Object arg 参数 46 | */ 47 | rocketMQTemplate.sendMessageInTransaction("producer_group_txmsg_bank1","topic_txmsg",message,null); 48 | 49 | } 50 | 51 | //更新账户,扣减金额 52 | @Override 53 | @Transactional 54 | public void doUpdateAccountBalance(AccountChangeEvent accountChangeEvent) { 55 | //幂等判断 56 | if(accountInfoDao.isExistTx(accountChangeEvent.getTxNo())>0){ 57 | return ; 58 | } 59 | //扣减金额 60 | accountInfoDao.updateAccountBalance(accountChangeEvent.getAccountNo(),accountChangeEvent.getAmount() * -1); 61 | //添加事务日志 62 | accountInfoDao.addTx(accountChangeEvent.getTxNo()); 63 | if(accountChangeEvent.getAmount() == 3){ 64 | throw new RuntimeException("人为制造异常"); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | server.port=56081 2 | swagger.enable = true 3 | 4 | spring.datasource.driver-class-name = com.mysql.jdbc.Driver 5 | spring.datasource.url = jdbc:mysql://localhost:3306/bank1?useUnicode=true 6 | spring.datasource.username = root 7 | spring.datasource.password = mysql 8 | 9 | rocketmq.producer.group = producer_bank1 10 | rocketmq.name-server = 127.0.0.1:9876 11 | 12 | logging.level.root = info 13 | logging.level.org.springframework.web = info 14 | logging.level.com.pbteach.wanxintx.ensuredemo = debug 15 | 16 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank1/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name = dtx-txmsg-demo-bank1 2 | spring.profiles.active = local 3 | 4 | server.servlet.context-path = /bank1 5 | spring.http.encoding.enabled = true 6 | spring.http.encoding.charset = UTF-8 7 | spring.http.encoding.force = true 8 | server.tomcat.remote_ip_header = x-forwarded-for 9 | server.tomcat.protocol_header = x-forwarded-proto 10 | server.use-forward-headers = true 11 | 12 | spring.mvc.throw-exception-if-no-handler-found = true 13 | spring.resources.add-mappings = true 14 | spring.freemarker.enabled = true 15 | spring.freemarker.suffix = .html 16 | spring.freemarker.request-context-attribute = rc 17 | spring.freemarker.content-type = text/html 18 | spring.freemarker.charset = UTF-8 19 | 20 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-txmsg-demo 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-txmsg-demo-bank2 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-web 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-actuator 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-configuration-processor 28 | true 29 | 30 | 31 | 32 | org.mybatis.spring.boot 33 | mybatis-spring-boot-starter 34 | 35 | 36 | 37 | com.alibaba 38 | druid-spring-boot-starter 39 | 40 | 41 | 42 | mysql 43 | mysql-connector-java 44 | 45 | 46 | 47 | 48 | javax.interceptor 49 | javax.interceptor-api 50 | 51 | 52 | 53 | 54 | io.springfox 55 | springfox-swagger2 56 | 57 | 58 | io.springfox 59 | springfox-swagger-ui 60 | 61 | 62 | 63 | org.projectlombok 64 | lombok 65 | 66 | 67 | 68 | org.apache.rocketmq 69 | rocketmq-spring-boot-starter 70 | 2.0.2 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/src/main/java/com/pbteach/dtx/txmsgdemo/bank2/TxMsgBank2Service.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank2; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | @SpringBootApplication 8 | public class TxMsgBank2Service { 9 | 10 | public static void main(String[] args) { 11 | SpringApplication.run(TxMsgBank2Service.class, args); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/src/main/java/com/pbteach/dtx/txmsgdemo/bank2/dao/AccountInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank2.dao; 2 | 3 | import org.apache.ibatis.annotations.*; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Mapper 7 | @Component 8 | public interface AccountInfoDao { 9 | @Update("update account_info set account_balance=account_balance+#{amount} where account_no=#{accountNo}") 10 | int updateAccountBalance(@Param("accountNo") String accountNo, @Param("amount") Double amount); 11 | 12 | @Select("select count(1) from de_duplication where tx_no = #{txNo}") 13 | int isExistTx(String txNo); 14 | 15 | @Insert("insert into de_duplication values(#{txNo},now());") 16 | int addTx(String txNo); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/src/main/java/com/pbteach/dtx/txmsgdemo/bank2/entity/AccountInfo.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank2.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | @Data 8 | public class AccountInfo implements Serializable { 9 | private Long id; 10 | private String accountName; 11 | private String accountNo; 12 | private String accountPassword; 13 | private Double accountBalance; 14 | } 15 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/src/main/java/com/pbteach/dtx/txmsgdemo/bank2/message/TxmsgConsumer.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank2.message; 2 | 3 | import com.pbteach.dtx.txmsgdemo.bank2.model.AccountChangeEvent; 4 | import com.pbteach.dtx.txmsgdemo.bank2.service.AccountInfoService; 5 | import com.alibaba.fastjson.JSONObject; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; 8 | import org.apache.rocketmq.spring.core.RocketMQListener; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @author Administrator 14 | * @version 1.0 15 | **/ 16 | @Component 17 | @Slf4j 18 | @RocketMQMessageListener(consumerGroup = "consumer_group_txmsg_bank2",topic = "topic_txmsg") 19 | public class TxmsgConsumer implements RocketMQListener { 20 | 21 | @Autowired 22 | AccountInfoService accountInfoService; 23 | 24 | //接收消息 25 | @Override 26 | public void onMessage(String message) { 27 | log.info("开始消费消息:{}",message); 28 | //解析消息 29 | JSONObject jsonObject = JSONObject.parseObject(message); 30 | String accountChangeString = jsonObject.getString("accountChange"); 31 | //转成AccountChangeEvent 32 | AccountChangeEvent accountChangeEvent = JSONObject.parseObject(accountChangeString, AccountChangeEvent.class); 33 | //设置账号为李四的 34 | accountChangeEvent.setAccountNo("2"); 35 | //更新本地账户,增加金额 36 | accountInfoService.addAccountInfoBalance(accountChangeEvent); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/src/main/java/com/pbteach/dtx/txmsgdemo/bank2/model/AccountChangeEvent.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank2.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class AccountChangeEvent implements Serializable { 13 | /** 14 | * 账号 15 | */ 16 | private String accountNo; 17 | /** 18 | * 变动金额 19 | */ 20 | private double amount; 21 | /** 22 | * 事务号 23 | */ 24 | private String txNo; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/src/main/java/com/pbteach/dtx/txmsgdemo/bank2/service/AccountInfoService.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank2.service; 2 | 3 | import com.pbteach.dtx.txmsgdemo.bank2.model.AccountChangeEvent; 4 | 5 | /** 6 | * Created by Administrator. 7 | */ 8 | public interface AccountInfoService { 9 | 10 | //更新账户,增加金额 11 | public void addAccountInfoBalance(AccountChangeEvent accountChangeEvent); 12 | } 13 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/src/main/java/com/pbteach/dtx/txmsgdemo/bank2/service/impl/AccountInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.pbteach.dtx.txmsgdemo.bank2.service.impl; 2 | 3 | import com.pbteach.dtx.txmsgdemo.bank2.dao.AccountInfoDao; 4 | import com.pbteach.dtx.txmsgdemo.bank2.model.AccountChangeEvent; 5 | import com.pbteach.dtx.txmsgdemo.bank2.service.AccountInfoService; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | /** 12 | * @author Administrator 13 | * @version 1.0 14 | **/ 15 | @Service 16 | @Slf4j 17 | public class AccountInfoServiceImpl implements AccountInfoService { 18 | 19 | @Autowired 20 | AccountInfoDao accountInfoDao; 21 | 22 | //更新账户,增加金额 23 | @Override 24 | @Transactional 25 | public void addAccountInfoBalance(AccountChangeEvent accountChangeEvent) { 26 | log.info("bank2更新本地账号,账号:{},金额:{}",accountChangeEvent.getAccountNo(),accountChangeEvent.getAmount()); 27 | if(accountInfoDao.isExistTx(accountChangeEvent.getTxNo())>0){ 28 | 29 | return ; 30 | } 31 | //增加金额 32 | accountInfoDao.updateAccountBalance(accountChangeEvent.getAccountNo(),accountChangeEvent.getAmount()); 33 | //添加事务记录,用于幂等 34 | accountInfoDao.addTx(accountChangeEvent.getTxNo()); 35 | if(accountChangeEvent.getAmount() == 4){ 36 | throw new RuntimeException("人为制造异常"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | server.port=56082 2 | swagger.enable = true 3 | 4 | spring.datasource.driver-class-name = com.mysql.jdbc.Driver 5 | spring.datasource.url = jdbc:mysql://localhost:3306/bank2?useUnicode=true 6 | spring.datasource.username = root 7 | spring.datasource.password = mysql 8 | 9 | rocketmq.producer.group = producer_bank2 10 | rocketmq.name-server = 127.0.0.1:9876 11 | 12 | logging.level.root = info 13 | logging.level.org.springframework.web = info 14 | logging.level.com.pbteach.wanxintx.ensuredemo = debug 15 | 16 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/dtx-txmsg-demo-bank2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name = dtx-txmsg-demo-bank1 2 | spring.profiles.active = local 3 | 4 | server.servlet.context-path = /bank2 5 | spring.http.encoding.enabled = true 6 | spring.http.encoding.charset = UTF-8 7 | spring.http.encoding.force = true 8 | server.tomcat.remote_ip_header = x-forwarded-for 9 | server.tomcat.protocol_header = x-forwarded-proto 10 | server.use-forward-headers = true 11 | 12 | spring.mvc.throw-exception-if-no-handler-found = true 13 | spring.resources.add-mappings = true 14 | spring.freemarker.enabled = true 15 | spring.freemarker.suffix = .html 16 | spring.freemarker.request-context-attribute = rc 17 | spring.freemarker.content-type = text/html 18 | spring.freemarker.charset = UTF-8 19 | 20 | -------------------------------------------------------------------------------- /dtx-txmsg-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | dtx-parent 7 | com.pbteach.dtx 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | dtx-txmsg-demo 13 | 14 | 15 | 16 | 17 | org.springframework.cloud 18 | spring-cloud-dependencies 19 | Greenwich.RELEASE 20 | pom 21 | import 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-dependencies 27 | 2.1.3.RELEASE 28 | pom 29 | import 30 | 31 | 32 | 33 | org.apache.rocketmq 34 | rocketmq-spring-boot-starter 35 | 2.0.2 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.pbteach.dtx 8 | dtx-parent 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | dtx-seata-demo 13 | 14 | 15 | 16 | UTF-8 17 | UTF-8 18 | 1.8 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-dependencies 28 | 2.1.3.RELEASE 29 | pom 30 | import 31 | 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-dependencies 36 | Greenwich.RELEASE 37 | pom 38 | import 39 | 40 | 41 | io.springfox 42 | springfox-swagger2 43 | 2.9.2 44 | 45 | 46 | io.springfox 47 | springfox-swagger-ui 48 | 2.9.2 49 | 50 | 51 | 52 | org.projectlombok 53 | lombok 54 | 1.18.0 55 | 56 | 57 | 58 | javax.servlet 59 | javax.servlet-api 60 | 3.1.0 61 | provided 62 | 63 | 64 | 65 | javax.interceptor 66 | javax.interceptor-api 67 | 1.2 68 | 69 | 70 | 71 | 72 | mysql 73 | mysql-connector-java 74 | 5.1.47 75 | 76 | 77 | 78 | org.mybatis.spring.boot 79 | mybatis-spring-boot-starter 80 | 2.0.0 81 | 82 | 83 | 84 | com.alibaba 85 | druid-spring-boot-starter 86 | 1.1.16 87 | 88 | 89 | 90 | org.apache.rocketmq 91 | rocketmq-spring-boot-starter 92 | 2.0.2 93 | 94 | 95 | 96 | commons-lang 97 | commons-lang 98 | 2.6 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | ${project.name} 107 | 108 | 109 | src/main/resources 110 | true 111 | 112 | **/* 113 | 114 | 115 | 116 | src/main/java 117 | 118 | **/*.xml 119 | 120 | 121 | 122 | 123 | 124 | org.springframework.boot 125 | spring-boot-maven-plugin 126 | 127 | 128 | 129 | org.apache.maven.plugins 130 | maven-compiler-plugin 131 | 132 | 1.8 133 | 1.8 134 | 135 | 136 | 137 | 138 | maven-resources-plugin 139 | 140 | utf-8 141 | true 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /sql/ban1_pay.sql: -------------------------------------------------------------------------------- 1 | /* 2 | SQLyog v10.2 3 | MySQL - 5.7.21-log : Database - bank1_pay 4 | ********************************************************************* 5 | */ 6 | 7 | /*!40101 SET NAMES utf8 */; 8 | 9 | /*!40101 SET SQL_MODE=''*/; 10 | 11 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 12 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 13 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 14 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 15 | CREATE DATABASE /*!32312 IF NOT EXISTS*/`bank1_pay` /*!40100 DEFAULT CHARACTER SET utf8 */; 16 | 17 | USE `bank1_pay`; 18 | 19 | /*Table structure for table `account_pay` */ 20 | 21 | DROP TABLE IF EXISTS `account_pay`; 22 | 23 | CREATE TABLE `account_pay` ( 24 | `id` varchar(64) COLLATE utf8_bin NOT NULL, 25 | `account_no` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '账号', 26 | `pay_amount` double DEFAULT NULL COMMENT '充值余额', 27 | `result` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '充值结果:success,fail', 28 | PRIMARY KEY (`id`) USING BTREE 29 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=DYNAMIC; 30 | 31 | /*Data for the table `account_pay` */ 32 | 33 | insert into `account_pay`(`id`,`account_no`,`pay_amount`,`result`) values ('5678ef0a-1ff0-4cfd-97ac-640d749d596f','1',2,'success'),('7d7d469c-f100-4066-b927-014c0c3aa010','1',2,'success'),('947fafad-c19c-46bc-b0f0-43703a124fd4','1',2,'success'); 34 | 35 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 36 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 37 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 38 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 39 | -------------------------------------------------------------------------------- /sql/bank2.sql: -------------------------------------------------------------------------------- 1 | /* 2 | SQLyog v10.2 3 | MySQL - 5.7.21-log : Database - bank2 4 | ********************************************************************* 5 | */ 6 | 7 | /*!40101 SET NAMES utf8 */; 8 | 9 | /*!40101 SET SQL_MODE=''*/; 10 | 11 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 12 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 13 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 14 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 15 | CREATE DATABASE /*!32312 IF NOT EXISTS*/`bank2` /*!40100 DEFAULT CHARACTER SET utf8 */; 16 | 17 | USE `bank2`; 18 | 19 | /*Table structure for table `account_info` */ 20 | 21 | DROP TABLE IF EXISTS `account_info`; 22 | 23 | CREATE TABLE `account_info` ( 24 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 25 | `account_name` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '户主姓名', 26 | `account_no` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '银行卡号', 27 | `account_password` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '帐户密码', 28 | `account_balance` double DEFAULT NULL COMMENT '帐户余额', 29 | PRIMARY KEY (`id`) USING BTREE 30 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=DYNAMIC; 31 | 32 | /*Data for the table `account_info` */ 33 | 34 | insert into `account_info`(`id`,`account_name`,`account_no`,`account_password`,`account_balance`) values (3,'李四的账户','2',NULL,0); 35 | 36 | /*Table structure for table `de_duplication` */ 37 | 38 | DROP TABLE IF EXISTS `de_duplication`; 39 | 40 | CREATE TABLE `de_duplication` ( 41 | `tx_no` varchar(64) COLLATE utf8_bin NOT NULL, 42 | `create_time` datetime DEFAULT NULL, 43 | PRIMARY KEY (`tx_no`) USING BTREE 44 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=DYNAMIC; 45 | 46 | /*Data for the table `de_duplication` */ 47 | 48 | /*Table structure for table `local_cancel_log` */ 49 | 50 | DROP TABLE IF EXISTS `local_cancel_log`; 51 | 52 | CREATE TABLE `local_cancel_log` ( 53 | `tx_no` varchar(64) NOT NULL COMMENT '事务id', 54 | `create_time` datetime DEFAULT NULL, 55 | PRIMARY KEY (`tx_no`) 56 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 57 | 58 | /*Data for the table `local_cancel_log` */ 59 | 60 | /*Table structure for table `local_confirm_log` */ 61 | 62 | DROP TABLE IF EXISTS `local_confirm_log`; 63 | 64 | CREATE TABLE `local_confirm_log` ( 65 | `tx_no` varchar(64) NOT NULL COMMENT '事务id', 66 | `create_time` datetime DEFAULT NULL 67 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 68 | 69 | /*Data for the table `local_confirm_log` */ 70 | 71 | /*Table structure for table `local_trade_log` */ 72 | 73 | DROP TABLE IF EXISTS `local_trade_log`; 74 | 75 | CREATE TABLE `local_trade_log` ( 76 | `tx_no` bigint(20) NOT NULL, 77 | `create_time` datetime DEFAULT NULL, 78 | PRIMARY KEY (`tx_no`) USING BTREE 79 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=DYNAMIC; 80 | 81 | /*Data for the table `local_trade_log` */ 82 | 83 | insert into `local_trade_log`(`tx_no`,`create_time`) values (182530043150692,'2019-08-12 10:06:48'),(182557045478629,'2019-08-12 10:07:15'),(182557298838620,'2019-08-12 10:07:16'),(182557478780006,'2019-08-12 10:07:16'),(182557803225927,'2019-08-12 10:07:16'),(182558121161357,'2019-08-12 10:07:16'),(182558382192161,'2019-08-12 10:07:17'),(182558480291123,'2019-08-12 10:07:17'),(182558659445955,'2019-08-12 10:07:17'),(182558825761766,'2019-08-12 10:07:17'),(182558980406535,'2019-08-12 10:07:17'),(182559237487433,'2019-08-12 10:07:17'),(182559420651610,'2019-08-12 10:07:18'),(182559864651139,'2019-08-12 10:07:18'),(182560768945751,'2019-08-12 10:07:19'),(182561304373304,'2019-08-12 10:07:20'),(182561522443399,'2019-08-12 10:07:20'),(182561724393702,'2019-08-12 10:07:20'),(182561839080669,'2019-08-12 10:07:20'),(182561927471144,'2019-08-12 10:07:20'),(182562029940456,'2019-08-12 10:07:20'),(182562184613303,'2019-08-12 10:07:20'),(182562307269367,'2019-08-12 10:07:21'),(182562468465469,'2019-08-12 10:07:21'),(182562669951205,'2019-08-12 10:07:21'),(182562751311925,'2019-08-12 10:07:21'),(182562893359802,'2019-08-12 10:07:21'),(182563048699232,'2019-08-12 10:07:21'),(182563228518824,'2019-08-12 10:07:21'),(182564068898018,'2019-08-12 10:07:23'),(182564485765274,'2019-08-12 10:07:23'),(182564688805886,'2019-08-12 10:07:23'),(182564907236622,'2019-08-12 10:07:23'),(182565058272798,'2019-08-12 10:07:23'),(182565257721225,'2019-08-12 10:07:23'),(182565386131494,'2019-08-12 10:07:24'),(182565579594893,'2019-08-12 10:07:24'),(182565988310360,'2019-08-12 10:07:24'),(182566730066953,'2019-08-12 10:07:25'),(182567002307880,'2019-08-12 10:07:25'),(182567188527839,'2019-08-12 10:07:25'),(182567464102776,'2019-08-12 10:07:26'),(182567776949856,'2019-08-12 10:07:26'),(182567899156670,'2019-08-12 10:07:26'),(182568409374757,'2019-08-12 10:07:27'),(182568888376107,'2019-08-12 10:07:27'),(182569269700033,'2019-08-12 10:07:27'),(182569431217757,'2019-08-12 10:07:28'),(182569682047067,'2019-08-12 10:07:28'),(182569797946135,'2019-08-12 10:07:28'),(182570034011792,'2019-08-12 10:07:28'),(182570737610867,'2019-08-12 10:07:29'),(182571087964926,'2019-08-12 10:07:29'),(182571203200693,'2019-08-12 10:07:29'),(182571289163682,'2019-08-12 10:07:29'),(182571497529667,'2019-08-12 10:07:30'),(182571659441215,'2019-08-12 10:07:30'),(182571789972662,'2019-08-12 10:07:30'),(182572179439260,'2019-08-12 10:07:30'),(182572312499566,'2019-08-12 10:07:31'),(182572405242159,'2019-08-12 10:07:31'),(182572589511596,'2019-08-12 10:07:31'),(182572669632865,'2019-08-12 10:07:31'),(182572809048685,'2019-08-12 10:07:31'),(182573016886654,'2019-08-12 10:07:31'),(182573656245407,'2019-08-12 10:07:32'),(182574188445063,'2019-08-12 10:07:32'),(182574518024550,'2019-08-12 10:07:33'),(182574684064320,'2019-08-12 10:07:33'),(182574803672990,'2019-08-12 10:07:33'),(182574984635401,'2019-08-12 10:07:33'),(182575172390178,'2019-08-12 10:07:33'),(182575364553230,'2019-08-12 10:07:34'),(182575592219135,'2019-08-12 10:07:34'),(182575798944552,'2019-08-12 10:07:34'),(182575966673388,'2019-08-12 10:07:34'),(182576097432378,'2019-08-12 10:07:34'),(182577038883173,'2019-08-12 10:07:35'),(182577727858623,'2019-08-12 10:07:36'),(182577911009673,'2019-08-12 10:07:36'),(182578086864042,'2019-08-12 10:07:36'),(182578276155098,'2019-08-12 10:07:36'),(182578402804827,'2019-08-12 10:07:37'),(182578601148361,'2019-08-12 10:07:37'),(182578810534276,'2019-08-12 10:07:37'),(182578915304905,'2019-08-12 10:07:37'),(182579036498716,'2019-08-12 10:07:37'),(182579912388785,'2019-08-12 10:07:38'),(182580237212485,'2019-08-12 10:07:38'),(182580419223999,'2019-08-12 10:07:39'),(182580732411299,'2019-08-12 10:07:39'),(182581045796240,'2019-08-12 10:07:39'),(182581413833718,'2019-08-12 10:07:40'),(182581565248402,'2019-08-12 10:07:40'),(182581760549646,'2019-08-12 10:07:40'),(182581935175869,'2019-08-12 10:07:40'),(182582031136148,'2019-08-12 10:07:40'),(182582167077933,'2019-08-12 10:07:40'),(182582983316456,'2019-08-12 10:07:41'),(182583247688199,'2019-08-12 10:07:41'),(182583639066302,'2019-08-12 10:07:42'),(182583894253563,'2019-08-12 10:07:42'),(182584010666426,'2019-08-12 10:07:42'),(182584293597117,'2019-08-12 10:07:43'),(182584487757001,'2019-08-12 10:07:43'),(182584766115325,'2019-08-12 10:07:43'),(182585007773644,'2019-08-12 10:07:43'),(182585144535895,'2019-08-12 10:07:43'),(182585800712748,'2019-08-12 10:07:44'),(182586182307975,'2019-08-12 10:07:44'),(182624670660818,'2019-08-12 10:08:23'),(182624908182163,'2019-08-12 10:08:23'),(182625083422095,'2019-08-12 10:08:23'),(182625283185582,'2019-08-12 10:08:23'),(182625605658737,'2019-08-12 10:08:24'),(182625876981471,'2019-08-12 10:08:24'),(182626023471170,'2019-08-12 10:08:24'),(182626125919332,'2019-08-12 10:08:24'),(182626400402137,'2019-08-12 10:08:25'),(182627354974195,'2019-08-12 10:08:26'),(182627678104453,'2019-08-12 10:08:26'),(182627969030496,'2019-08-12 10:08:26'),(182628214644557,'2019-08-12 10:08:27'),(182628534246810,'2019-08-12 10:08:27'),(182628809232470,'2019-08-12 10:08:27'),(182628987115761,'2019-08-12 10:08:27'),(182629067952477,'2019-08-12 10:08:27'),(182629871208670,'2019-08-12 10:08:28'),(182630439944602,'2019-08-12 10:08:29'),(182630787578723,'2019-08-12 10:08:29'),(182631113329003,'2019-08-12 10:08:29'),(182631290820294,'2019-08-12 10:08:30'),(182631591596310,'2019-08-12 10:08:30'),(182631824484756,'2019-08-12 10:08:30'),(182632087674298,'2019-08-12 10:08:30'),(182632466543754,'2019-08-12 10:08:31'),(182632618071481,'2019-08-12 10:08:31'),(182632728020528,'2019-08-12 10:08:31'),(182632911758303,'2019-08-12 10:08:31'),(182633049995934,'2019-08-12 10:08:31'),(182634021980839,'2019-08-12 10:08:32'),(182634547108804,'2019-08-12 10:08:33'),(182634770735826,'2019-08-12 10:08:33'),(182635123752936,'2019-08-12 10:08:34'),(182635715669046,'2019-08-12 10:08:34'),(182635909490169,'2019-08-12 10:08:34'),(182636291519696,'2019-08-12 10:08:35'),(182636539834367,'2019-08-12 10:08:35'),(182636717212252,'2019-08-12 10:08:35'),(182636809814818,'2019-08-12 10:08:35'),(182636907350758,'2019-08-12 10:08:35'),(182637062336111,'2019-08-12 10:08:35'),(182637463340654,'2019-08-12 10:08:36'),(182637678289696,'2019-08-12 10:08:36'),(182637833749097,'2019-08-12 10:08:36'),(182638011446051,'2019-08-12 10:08:36'),(182638082887151,'2019-08-12 10:08:36'),(182638675546421,'2019-08-12 10:08:37'),(182639177158364,'2019-08-12 10:08:37'),(182639429596881,'2019-08-12 10:08:38'),(182639675672226,'2019-08-12 10:08:38'),(182639991963441,'2019-08-12 10:08:38'),(182640125217742,'2019-08-12 10:08:38'),(182640387842804,'2019-08-12 10:08:39'),(182640683207024,'2019-08-12 10:08:39'),(182641011260808,'2019-08-12 10:08:39'),(182642051592379,'2019-08-12 10:08:40'),(182642342700748,'2019-08-12 10:08:41'),(182642580716197,'2019-08-12 10:08:41'),(182642685082427,'2019-08-12 10:08:41'),(182642888502641,'2019-08-12 10:08:41'),(182643014410670,'2019-08-12 10:08:41'),(182643238065406,'2019-08-12 10:08:41'),(182643591505511,'2019-08-12 10:08:42'),(182643878854687,'2019-08-12 10:08:42'),(182644035968148,'2019-08-12 10:08:42'),(182644177538695,'2019-08-12 10:08:42'),(182644961028215,'2019-08-12 10:08:43'),(182645181724532,'2019-08-12 10:08:43'),(182645400821487,'2019-08-12 10:08:44'),(182645761887189,'2019-08-12 10:08:44'),(182646073830297,'2019-08-12 10:08:44'),(182646326031061,'2019-08-12 10:08:45'),(182646505008673,'2019-08-12 10:08:45'),(182646719578112,'2019-08-12 10:08:45'),(182646913411269,'2019-08-12 10:08:45'),(182647133994908,'2019-08-12 10:08:45'),(182648196127544,'2019-08-12 10:08:46'),(182648473970615,'2019-08-12 10:08:47'),(182648623682012,'2019-08-12 10:08:47'),(182648711210450,'2019-08-12 10:08:47'),(182648851868274,'2019-08-12 10:08:47'),(182649169099561,'2019-08-12 10:08:47'),(182649459319640,'2019-08-12 10:08:48'),(182649645828767,'2019-08-12 10:08:48'),(182649770309184,'2019-08-12 10:08:48'),(182649921919322,'2019-08-12 10:08:48'),(182650093040148,'2019-08-12 10:08:48'),(182650833998518,'2019-08-12 10:08:49'),(182651079715411,'2019-08-12 10:08:49'),(182651297845674,'2019-08-12 10:08:50'),(182651568954357,'2019-08-12 10:08:50'),(182651754921248,'2019-08-12 10:08:50'),(182651897052994,'2019-08-12 10:08:50'),(182652177788117,'2019-08-12 10:08:50'),(182652334768480,'2019-08-12 10:08:51'),(182652573150769,'2019-08-12 10:08:51'),(182652679999912,'2019-08-12 10:08:51'),(182652919576070,'2019-08-12 10:08:51'),(182653005229105,'2019-08-12 10:08:51'),(182653108534198,'2019-08-12 10:08:51'),(182653847746616,'2019-08-12 10:08:52'),(182654403070294,'2019-08-12 10:08:53'),(182654613274852,'2019-08-12 10:08:53'),(182654940526039,'2019-08-12 10:08:53'),(182655155231129,'2019-08-12 10:08:53'),(182655296181404,'2019-08-12 10:08:54'),(182655424746649,'2019-08-12 10:08:54'),(182655531064494,'2019-08-12 10:08:54'),(182655782010857,'2019-08-12 10:08:54'),(182655910177902,'2019-08-12 10:08:54'),(182656097665390,'2019-08-12 10:08:54'),(182656789185379,'2019-08-12 10:08:55'),(182657257350375,'2019-08-12 10:08:56'),(182657534685850,'2019-08-12 10:08:56'),(182657725455203,'2019-08-12 10:08:56'),(182657910063402,'2019-08-12 10:08:56'),(182658123782473,'2019-08-12 10:08:56'),(182658322922406,'2019-08-12 10:08:57'),(182658439889175,'2019-08-12 10:08:57'),(182658606528067,'2019-08-12 10:08:57'),(182658796402200,'2019-08-12 10:08:57'),(182658942081278,'2019-08-12 10:08:57'),(182659138418133,'2019-08-12 10:08:57'),(182660133321761,'2019-08-12 10:08:59'),(182660489688197,'2019-08-12 10:08:59'),(182660689145012,'2019-08-12 10:08:59'),(182661052397165,'2019-08-12 10:08:59'),(182661231309139,'2019-08-12 10:08:59'),(182661400622022,'2019-08-12 10:09:00'),(182661590305078,'2019-08-12 10:09:00'),(182661705054400,'2019-08-12 10:09:00'),(182661869006539,'2019-08-12 10:09:00'),(182662016009667,'2019-08-12 10:09:00'),(182662192195141,'2019-08-12 10:09:00'),(182662401775051,'2019-08-12 10:09:01'),(182662669649274,'2019-08-12 10:09:01'),(182662798416901,'2019-08-12 10:09:01'),(182662962385084,'2019-08-12 10:09:01'),(182663138630725,'2019-08-12 10:09:01'),(182663906745436,'2019-08-12 10:09:02'),(182664566244630,'2019-08-12 10:09:03'),(182664781625055,'2019-08-12 10:09:03'),(182665013622293,'2019-08-12 10:09:03'),(182665198114532,'2019-08-12 10:09:03'),(182665292504256,'2019-08-12 10:09:04'),(182665463504382,'2019-08-12 10:09:04'),(182665696224724,'2019-08-12 10:09:04'),(182665879388172,'2019-08-12 10:09:04'),(182666012267976,'2019-08-12 10:09:04'),(182666194553343,'2019-08-12 10:09:04'),(182666844078585,'2019-08-12 10:09:05'),(182667186195891,'2019-08-12 10:09:05'),(182667324270158,'2019-08-12 10:09:06'),(182667513621016,'2019-08-12 10:09:06'),(182667877910604,'2019-08-12 10:09:06'),(182668076901758,'2019-08-12 10:09:06'),(182668398601123,'2019-08-12 10:09:07'),(182668650255274,'2019-08-12 10:09:07'),(182668782782095,'2019-08-12 10:09:07'),(182668945877302,'2019-08-12 10:09:07'),(182669089093523,'2019-08-12 10:09:07'),(182669299315585,'2019-08-12 10:09:08'),(182669659768307,'2019-08-12 10:09:08'),(182669806385269,'2019-08-12 10:09:08'),(182669879997141,'2019-08-12 10:09:08'),(182670030877610,'2019-08-12 10:09:08'),(182670125454036,'2019-08-12 10:09:08'),(182670858669757,'2019-08-12 10:09:09'),(182671285490181,'2019-08-12 10:09:10'),(182671531645385,'2019-08-12 10:09:10'),(182671659123603,'2019-08-12 10:09:10'),(182671882073103,'2019-08-12 10:09:10'),(182672072862147,'2019-08-12 10:09:10'),(182672346981759,'2019-08-12 10:09:11'),(182672558234692,'2019-08-12 10:09:11'),(182672719847590,'2019-08-12 10:09:11'),(182672885199991,'2019-08-12 10:09:11'),(182673098831911,'2019-08-12 10:09:11'),(182673735164419,'2019-08-12 10:09:12'),(182674262917147,'2019-08-12 10:09:13'),(184254808744930,'2019-08-12 10:35:33'),(184255116226890,'2019-08-12 10:35:33'),(184255256161610,'2019-08-12 10:35:34'),(184255408723489,'2019-08-12 10:35:34'),(184255666142419,'2019-08-12 10:35:34'),(184255873125644,'2019-08-12 10:35:34'),(184256135728827,'2019-08-12 10:35:34'),(184256275857542,'2019-08-12 10:35:35'),(184256487865303,'2019-08-12 10:35:35'),(184256660654046,'2019-08-12 10:35:35'),(184257264251043,'2019-08-12 10:35:36'),(184257630443748,'2019-08-12 10:35:36'),(184258036856075,'2019-08-12 10:35:36'),(184258410345460,'2019-08-12 10:35:37'),(184258641570000,'2019-08-12 10:35:37'),(184258859378276,'2019-08-12 10:35:37'),(184258994247255,'2019-08-12 10:35:37'),(184259198608999,'2019-08-12 10:35:38'),(184259424286823,'2019-08-12 10:35:38'),(184259704660941,'2019-08-12 10:35:38'),(184259888691166,'2019-08-12 10:35:38'),(184260126599772,'2019-08-12 10:35:38'),(184260389328760,'2019-08-12 10:35:39'),(184260556643716,'2019-08-12 10:35:39'),(184260660511103,'2019-08-12 10:35:39'),(184260764406567,'2019-08-12 10:35:39'),(184261442245918,'2019-08-12 10:35:40'),(184261931309103,'2019-08-12 10:35:40'),(184262165326146,'2019-08-12 10:35:41'),(184262462959228,'2019-08-12 10:35:41'),(184262649879683,'2019-08-12 10:35:41'),(184262899411926,'2019-08-12 10:35:41'),(184263074743385,'2019-08-12 10:35:41'),(184263174676909,'2019-08-12 10:35:41'),(184263359855787,'2019-08-12 10:35:42'),(184263654630365,'2019-08-12 10:35:42'),(184264413850856,'2019-08-12 10:35:43'),(184264888990910,'2019-08-12 10:35:43'),(184265153237942,'2019-08-12 10:35:43'),(184265329930646,'2019-08-12 10:35:44'),(184265521700239,'2019-08-12 10:35:44'),(184265719769554,'2019-08-12 10:35:44'),(184265988964181,'2019-08-12 10:35:44'),(184266141075350,'2019-08-12 10:35:44'),(184266297332244,'2019-08-12 10:35:45'),(184266509109181,'2019-08-12 10:35:45'),(184266662985264,'2019-08-12 10:35:45'),(184267580210425,'2019-08-12 10:35:46'),(184268056308419,'2019-08-12 10:35:46'),(184268198377810,'2019-08-12 10:35:47'),(184268417468930,'2019-08-12 10:35:47'),(184268731310415,'2019-08-12 10:35:47'),(184269058776382,'2019-08-12 10:35:47'),(184269259203899,'2019-08-12 10:35:48'),(184269420457615,'2019-08-12 10:35:48'),(184269542871187,'2019-08-12 10:35:48'),(184269693847560,'2019-08-12 10:35:48'),(184269841753201,'2019-08-12 10:35:48'),(184269970644080,'2019-08-12 10:35:48'),(184270102559016,'2019-08-12 10:35:48'),(184270305617495,'2019-08-12 10:35:49'),(184270403478339,'2019-08-12 10:35:49'),(184270547966100,'2019-08-12 10:35:49'),(184270628669717,'2019-08-12 10:35:49'),(184270854507988,'2019-08-12 10:35:50'),(184271610260642,'2019-08-12 10:35:50'),(184271776416370,'2019-08-12 10:35:50'),(184271926525967,'2019-08-12 10:35:50'),(184272068075729,'2019-08-12 10:35:50'),(184272198272061,'2019-08-12 10:35:51'),(184272403949104,'2019-08-12 10:35:51'),(184272529278066,'2019-08-12 10:35:51'),(184272626856669,'2019-08-12 10:35:51'),(184273695771462,'2019-08-12 10:35:52'),(184274226956292,'2019-08-12 10:35:53'),(184274452921097,'2019-08-12 10:35:53'),(184274797270071,'2019-08-12 10:35:53'),(184275084642584,'2019-08-12 10:35:53'),(184275247246241,'2019-08-12 10:35:54'),(184275339977894,'2019-08-12 10:35:54'),(184275444128980,'2019-08-12 10:35:54'),(184275538996398,'2019-08-12 10:35:54'),(184275628259484,'2019-08-12 10:35:54'),(184275693638250,'2019-08-12 10:35:54'),(184276466036888,'2019-08-12 10:35:55'),(184276776042603,'2019-08-12 10:35:55'),(184276980971381,'2019-08-12 10:35:55'),(184277087281933,'2019-08-12 10:35:55'),(184277254195044,'2019-08-12 10:35:56'),(184277482604473,'2019-08-12 10:35:56'),(184277705368365,'2019-08-12 10:35:56'),(184277954964787,'2019-08-12 10:35:56'),(184278126453547,'2019-08-12 10:35:56'),(184278327952046,'2019-08-12 10:35:57'),(184278450410470,'2019-08-12 10:35:57'),(184278567237212,'2019-08-12 10:35:57'),(184278670111652,'2019-08-12 10:35:57'),(184278843466335,'2019-08-12 10:35:57'),(184279538296267,'2019-08-12 10:35:58'),(184279987774322,'2019-08-12 10:35:58'),(184280203765903,'2019-08-12 10:35:59'),(184280357010410,'2019-08-12 10:35:59'),(184280532099011,'2019-08-12 10:35:59'),(184280717624673,'2019-08-12 10:35:59'),(184281789950782,'2019-08-12 10:36:00'),(184282039562520,'2019-08-12 10:36:00'),(184282272485608,'2019-08-12 10:36:01'),(184282577925518,'2019-08-12 10:36:01'),(184282707515799,'2019-08-12 10:36:01'),(184282888221495,'2019-08-12 10:36:01'),(184283082408728,'2019-08-12 10:36:01'),(184283212148152,'2019-08-12 10:36:02'),(184283333772252,'2019-08-12 10:36:02'),(184283538907058,'2019-08-12 10:36:02'),(184283704440327,'2019-08-12 10:36:02'),(184283857033201,'2019-08-12 10:36:02'),(184284281154472,'2019-08-12 10:36:03'),(184284558138059,'2019-08-12 10:36:03'),(184284666908187,'2019-08-12 10:36:03'),(184284801702777,'2019-08-12 10:36:03'),(184285032267663,'2019-08-12 10:36:03'),(184285163030663,'2019-08-12 10:36:03'),(184285385725636,'2019-08-12 10:36:04'),(184285475735529,'2019-08-12 10:36:04'),(184285858075375,'2019-08-12 10:36:04'),(184286172709613,'2019-08-12 10:36:05'),(184286430771059,'2019-08-12 10:36:05'),(184286552089217,'2019-08-12 10:36:05'),(184287191595653,'2019-08-12 10:36:06'),(184287784311809,'2019-08-12 10:36:06'),(184287907014549,'2019-08-12 10:36:06'),(184288083558840,'2019-08-12 10:36:06'),(184288226154788,'2019-08-12 10:36:07'),(184288469281194,'2019-08-12 10:36:07'),(184288662218402,'2019-08-12 10:36:07'),(184288862642638,'2019-08-12 10:36:07'),(184289052795729,'2019-08-12 10:36:07'),(184289122522966,'2019-08-12 10:36:07'),(184289274265837,'2019-08-12 10:36:08'),(184289369836304,'2019-08-12 10:36:08'),(184289459402780,'2019-08-12 10:36:08'),(184289619545768,'2019-08-12 10:36:08'),(184290213361348,'2019-08-12 10:36:09'),(184290848984973,'2019-08-12 10:36:09'),(184291098823888,'2019-08-12 10:36:09'),(184291439561353,'2019-08-12 10:36:10'),(184291799153497,'2019-08-12 10:36:10'),(184292183384062,'2019-08-12 10:36:10'),(184292338496679,'2019-08-12 10:36:11'),(184292539491595,'2019-08-12 10:36:11'),(184293739140946,'2019-08-12 10:36:12'),(184294287949756,'2019-08-12 10:36:13'),(184294519735131,'2019-08-12 10:36:13'),(184294902193853,'2019-08-12 10:36:13'),(184295174450460,'2019-08-12 10:36:14'),(184295451037306,'2019-08-12 10:36:14'),(184295695708742,'2019-08-12 10:36:14'),(184295981035559,'2019-08-12 10:36:14'),(184296241893154,'2019-08-12 10:36:15'),(184296413264496,'2019-08-12 10:36:15'),(184296548487552,'2019-08-12 10:36:15'),(184296733059650,'2019-08-12 10:36:15'),(184297297672829,'2019-08-12 10:36:16'),(184297937546834,'2019-08-12 10:36:16'),(184298138102710,'2019-08-12 10:36:16'),(184298274932420,'2019-08-12 10:36:17'),(184298437615936,'2019-08-12 10:36:17'),(184298565914256,'2019-08-12 10:36:17'),(184298703009433,'2019-08-12 10:36:17'),(184298915582040,'2019-08-12 10:36:17'),(184299154359976,'2019-08-12 10:36:17'),(184299330723764,'2019-08-12 10:36:18'),(184299477774662,'2019-08-12 10:36:18'),(184299685668422,'2019-08-12 10:36:18'),(184299951150895,'2019-08-12 10:36:18'),(184300162105907,'2019-08-12 10:36:18'),(184300233430683,'2019-08-12 10:36:19'),(184300425201369,'2019-08-12 10:36:19'),(184300585360401,'2019-08-12 10:36:19'),(184300708110181,'2019-08-12 10:36:19'),(184301202703308,'2019-08-12 10:36:20'),(184301658184990,'2019-08-12 10:36:20'),(184301937616483,'2019-08-12 10:36:20'),(184302071302167,'2019-08-12 10:36:20'),(184302165309372,'2019-08-12 10:36:20'),(184302347528008,'2019-08-12 10:36:21'),(184302623897521,'2019-08-12 10:36:21'),(184303625089932,'2019-08-12 10:36:22'),(184304113651720,'2019-08-12 10:36:22'),(184304418573825,'2019-08-12 10:36:23'),(184304659110475,'2019-08-12 10:36:23'),(184304877334454,'2019-08-12 10:36:23'),(184305136990157,'2019-08-12 10:36:23'),(184305357420278,'2019-08-12 10:36:24'),(184305470683280,'2019-08-12 10:36:24'),(184305675016217,'2019-08-12 10:36:24'),(184306295669433,'2019-08-12 10:36:25'),(184306564210603,'2019-08-12 10:36:25'),(184306756697466,'2019-08-12 10:36:25'),(184306958461432,'2019-08-12 10:36:25'),(184307272781340,'2019-08-12 10:36:26'),(184307418139889,'2019-08-12 10:36:26'),(184307515297320,'2019-08-12 10:36:26'),(184307643761557,'2019-08-12 10:36:26'),(184308313353945,'2019-08-12 10:36:27'),(184308761061253,'2019-08-12 10:36:27'),(184308946143498,'2019-08-12 10:36:27'),(184309136401609,'2019-08-12 10:36:27'),(184309291688895,'2019-08-12 10:36:28'),(184309438391550,'2019-08-12 10:36:28'),(184309808615844,'2019-08-12 10:36:28'),(184310006713966,'2019-08-12 10:36:28'),(184310139635341,'2019-08-12 10:36:28'),(184310276098941,'2019-08-12 10:36:29'),(184310464680384,'2019-08-12 10:36:29'),(184310596707632,'2019-08-12 10:36:29'),(184310705470468,'2019-08-12 10:36:29'),(184311482885984,'2019-08-12 10:36:30'),(184312073705222,'2019-08-12 10:36:30'),(184312232848334,'2019-08-12 10:36:31'),(184312439206547,'2019-08-12 10:36:31'),(184326113963497,'2019-08-12 10:36:44'),(184326287695229,'2019-08-12 10:36:45'),(184326461982691,'2019-08-12 10:36:45'),(184326614855982,'2019-08-12 10:36:45'),(184327003135639,'2019-08-12 10:36:45'),(184327293356447,'2019-08-12 10:36:46'),(184327594335938,'2019-08-12 10:36:46'),(184328169530215,'2019-08-12 10:36:46'),(184328570208030,'2019-08-12 10:36:47'),(184328802414212,'2019-08-12 10:36:47'),(184329021348533,'2019-08-12 10:36:47'),(184329349858861,'2019-08-12 10:36:48'),(184329462915470,'2019-08-12 10:36:48'),(184329718860113,'2019-08-12 10:36:48'),(184330124570485,'2019-08-12 10:36:48'),(184330386325853,'2019-08-12 10:36:49'),(184330537345255,'2019-08-12 10:36:49'),(184330652792885,'2019-08-12 10:36:49'),(184330999232408,'2019-08-12 10:36:49'),(184331437255295,'2019-08-12 10:36:50'),(184331700844861,'2019-08-12 10:36:50'),(184332009548404,'2019-08-12 10:36:50'),(184332272856094,'2019-08-12 10:36:51'),(184332419766236,'2019-08-12 10:36:51'),(184332712621652,'2019-08-12 10:36:51'),(184333369393617,'2019-08-12 10:36:52'),(184333562483613,'2019-08-12 10:36:52'),(184333809574878,'2019-08-12 10:36:52'),(184334047069969,'2019-08-12 10:36:52'),(184334191700673,'2019-08-12 10:36:52'),(184334336233286,'2019-08-12 10:36:53'),(184334659278945,'2019-08-12 10:36:53'),(184335003837594,'2019-08-12 10:36:53'),(184335319440711,'2019-08-12 10:36:54'),(184335453484483,'2019-08-12 10:36:54'),(184335558488124,'2019-08-12 10:36:54'),(184335714109795,'2019-08-12 10:36:54'),(184336637941716,'2019-08-12 10:36:55'),(184337340113180,'2019-08-12 10:36:56'),(184337576605114,'2019-08-12 10:36:56'),(184337885878972,'2019-08-12 10:36:56'),(184338397599425,'2019-08-12 10:36:57'),(184338557185953,'2019-08-12 10:36:57'),(184338708660076,'2019-08-12 10:36:57'),(184339570825020,'2019-08-12 10:36:58'),(184339991067127,'2019-08-12 10:36:58'),(184340205134076,'2019-08-12 10:36:59'),(184340308563881,'2019-08-12 10:36:59'),(184340560107178,'2019-08-12 10:36:59'),(184340893141011,'2019-08-12 10:36:59'),(184341048986578,'2019-08-12 10:36:59'),(184341163548469,'2019-08-12 10:37:00'),(184341464533065,'2019-08-12 10:37:00'),(184342217177063,'2019-08-12 10:37:01'),(184342685282986,'2019-08-12 10:37:01'),(184343137077674,'2019-08-12 10:37:01'),(184343492048587,'2019-08-12 10:37:02'),(184344122665910,'2019-08-12 10:37:02'),(184344435442247,'2019-08-12 10:37:03'),(184344701842548,'2019-08-12 10:37:03'),(184345197129972,'2019-08-12 10:37:04'),(184345483934723,'2019-08-12 10:37:04'),(184345611806765,'2019-08-12 10:37:04'),(184345982570378,'2019-08-12 10:37:04'),(184346325952661,'2019-08-12 10:37:05'),(184346532758301,'2019-08-12 10:37:05'),(184347222222748,'2019-08-12 10:37:06'),(184347463084304,'2019-08-12 10:37:06'),(184347677964062,'2019-08-12 10:37:06'),(184347837230791,'2019-08-12 10:37:06'),(184348069997443,'2019-08-12 10:37:06'),(184348365701518,'2019-08-12 10:37:07'),(184348726132726,'2019-08-12 10:37:07'),(184349830169311,'2019-08-12 10:37:08'),(184350144092113,'2019-08-12 10:37:08'),(184350318398901,'2019-08-12 10:37:09'),(184350513193280,'2019-08-12 10:37:09'),(184350728963882,'2019-08-12 10:37:09'),(184350914756104,'2019-08-12 10:37:09'),(184351058120009,'2019-08-12 10:37:09'),(184351207179043,'2019-08-12 10:37:10'),(184351371557460,'2019-08-12 10:37:10'),(184351525447400,'2019-08-12 10:37:10'),(184351632451155,'2019-08-12 10:37:10'),(184351904800019,'2019-08-12 10:37:10'),(184352129335389,'2019-08-12 10:37:11'),(184352343380824,'2019-08-12 10:37:11'),(184352455861648,'2019-08-12 10:37:11'),(184352578183327,'2019-08-12 10:37:11'),(184352673417949,'2019-08-12 10:37:11'),(184353350056867,'2019-08-12 10:37:12'),(184353886094117,'2019-08-12 10:37:12'),(184516298078322,'2019-08-12 10:39:55'),(184516747776992,'2019-08-12 10:39:55'),(184516938517173,'2019-08-12 10:39:55'),(184517091986669,'2019-08-12 10:39:55'),(184517411885748,'2019-08-12 10:39:56'),(184517599054166,'2019-08-12 10:39:56'),(184517724506744,'2019-08-12 10:39:56'),(184518258509238,'2019-08-12 10:39:57'),(184518572580818,'2019-08-12 10:39:57'),(184518762414110,'2019-08-12 10:39:57'),(184519109146813,'2019-08-12 10:39:57'),(184519233607903,'2019-08-12 10:39:58'),(184519503444317,'2019-08-12 10:39:58'),(184519749706364,'2019-08-12 10:39:58'),(184520517177829,'2019-08-12 10:39:59'),(184521307248947,'2019-08-12 10:40:00'),(184521528306269,'2019-08-12 10:40:00'),(184521795437332,'2019-08-12 10:40:00'),(184522082977949,'2019-08-12 10:40:00'),(184522478221725,'2019-08-12 10:40:01'),(184522708931012,'2019-08-12 10:40:01'),(184523011901866,'2019-08-12 10:40:01'),(184523210321611,'2019-08-12 10:40:02'),(184523388402909,'2019-08-12 10:40:02'),(184523504196593,'2019-08-12 10:40:02'),(184523617719592,'2019-08-12 10:40:02'),(184523719830816,'2019-08-12 10:40:02'),(184524533656074,'2019-08-12 10:40:03'),(184524882223704,'2019-08-12 10:40:03'),(184525054868409,'2019-08-12 10:40:03'),(184525176710571,'2019-08-12 10:40:03'),(184525332571819,'2019-08-12 10:40:04'),(184525480195219,'2019-08-12 10:40:04'),(184525564181067,'2019-08-12 10:40:04'),(184525704627028,'2019-08-12 10:40:04'),(184525819576909,'2019-08-12 10:40:04'),(184526525660356,'2019-08-12 10:40:05'),(184526697682966,'2019-08-12 10:40:05'),(184526953390950,'2019-08-12 10:40:05'),(184527172934968,'2019-08-12 10:40:05'),(184527402430695,'2019-08-12 10:40:06'),(184527505166567,'2019-08-12 10:40:06'),(184527704849466,'2019-08-12 10:40:06'),(184528045443987,'2019-08-12 10:40:06'),(184528276330130,'2019-08-12 10:40:07'),(184528416354919,'2019-08-12 10:40:07'),(184528751120118,'2019-08-12 10:40:07'),(184529616488163,'2019-08-12 10:40:08'),(184529886315096,'2019-08-12 10:40:08'),(184530057833757,'2019-08-12 10:40:08'),(184530127710866,'2019-08-12 10:40:09'),(184530570954836,'2019-08-12 10:40:09'),(184530757086185,'2019-08-12 10:40:09'),(184531272669392,'2019-08-12 10:40:10'),(184531498834390,'2019-08-12 10:40:10'),(184531704854571,'2019-08-12 10:40:10'),(184532287466228,'2019-08-12 10:40:11'),(184532469688146,'2019-08-12 10:40:11'),(184532662721256,'2019-08-12 10:40:11'),(184532741595052,'2019-08-12 10:40:11'),(184533176511107,'2019-08-12 10:40:12'),(184533388864558,'2019-08-12 10:40:12'),(184533630615499,'2019-08-12 10:40:12'),(184533797981871,'2019-08-12 10:40:12'),(184533965970339,'2019-08-12 10:40:12'),(184534061521844,'2019-08-12 10:40:12'),(184534169647633,'2019-08-12 10:40:12'),(184534355367289,'2019-08-12 10:40:13'),(184534502202313,'2019-08-12 10:40:13'),(184534734262271,'2019-08-12 10:40:13'),(184535233598422,'2019-08-12 10:40:14'),(184535647001852,'2019-08-12 10:40:14'),(184535821911409,'2019-08-12 10:40:14'),(184535994375977,'2019-08-12 10:40:14'),(184536194031162,'2019-08-12 10:40:15'),(184536342809779,'2019-08-12 10:40:15'),(184536572100207,'2019-08-12 10:40:15'),(184536732918894,'2019-08-12 10:40:15'),(184536891488409,'2019-08-12 10:40:15'),(184537000149871,'2019-08-12 10:40:15'),(184537245955739,'2019-08-12 10:40:16'),(184537523690508,'2019-08-12 10:40:16'),(184537708412477,'2019-08-12 10:40:16'),(184538439695545,'2019-08-12 10:40:17'),(184538746518214,'2019-08-12 10:40:17'),(184538938540146,'2019-08-12 10:40:17'),(184539333679630,'2019-08-12 10:40:18'),(184539698667161,'2019-08-12 10:40:18'),(184539901558995,'2019-08-12 10:40:18'),(184540634971263,'2019-08-12 10:40:19'),(184540833774622,'2019-08-12 10:40:19'),(184541104358936,'2019-08-12 10:40:19'),(184541418945405,'2019-08-12 10:40:20'),(184541633954250,'2019-08-12 10:40:20'),(184541971513045,'2019-08-12 10:40:20'),(184542366117586,'2019-08-12 10:40:21'),(184542519648709,'2019-08-12 10:40:21'),(184542708590063,'2019-08-12 10:40:21'),(184543101165317,'2019-08-12 10:40:22'),(184544023780395,'2019-08-12 10:40:22'),(184544257127573,'2019-08-12 10:40:23'),(184544504659701,'2019-08-12 10:40:23'),(184544667287425,'2019-08-12 10:40:23'),(184545215414701,'2019-08-12 10:40:24'),(184545498403372,'2019-08-12 10:40:24'),(184545707775066,'2019-08-12 10:40:24'),(184546039237980,'2019-08-12 10:40:24'),(184546235857075,'2019-08-12 10:40:25'),(184546384690755,'2019-08-12 10:40:25'),(184546508230006,'2019-08-12 10:40:25'),(184546594679075,'2019-08-12 10:40:25'),(184546818262704,'2019-08-12 10:40:25'),(187003094149418,'2019-08-12 11:21:22'),(187003594703142,'2019-08-12 11:21:22'),(187003874858469,'2019-08-12 11:21:22'),(187004158219449,'2019-08-12 11:21:23'),(187004552260238,'2019-08-12 11:21:23'),(187004771815560,'2019-08-12 11:21:23'),(187005024565490,'2019-08-12 11:21:23'),(187005236552101,'2019-08-12 11:21:24'),(187005500050139,'2019-08-12 11:21:24'),(187005717239965,'2019-08-12 11:21:24'),(187005966717511,'2019-08-12 11:21:24'),(187006190642818,'2019-08-12 11:21:25'),(187006453996090,'2019-08-12 11:21:25'),(187007254048818,'2019-08-12 11:21:26'),(187007765892158,'2019-08-12 11:21:26'),(187008033895468,'2019-08-12 11:21:27'),(187008609535349,'2019-08-12 11:21:27'),(187008794297066,'2019-08-12 11:21:27'),(187009054177395,'2019-08-12 11:21:28'),(187009253303470,'2019-08-12 11:21:28'),(187009838902719,'2019-08-12 11:21:29'),(187010406997592,'2019-08-12 11:21:29'),(187010715288350,'2019-08-12 11:21:29'),(187011029469690,'2019-08-12 11:21:29'),(187011181068888,'2019-08-12 11:21:30'),(187011274179415,'2019-08-12 11:21:30'),(187011906661566,'2019-08-12 11:21:30'),(187012236055810,'2019-08-12 11:21:31'),(187012378491676,'2019-08-12 11:21:31'),(187012522313583,'2019-08-12 11:21:31'),(187012636289844,'2019-08-12 11:21:31'),(187012806936987,'2019-08-12 11:21:31'),(187012988700902,'2019-08-12 11:21:31'),(187013130486230,'2019-08-12 11:21:32'),(187013238445373,'2019-08-12 11:21:32'),(187013514646781,'2019-08-12 11:21:32'),(187014564148613,'2019-08-12 11:21:33'),(187014690563142,'2019-08-12 11:21:33'),(187014960967683,'2019-08-12 11:21:33'),(187015251052840,'2019-08-12 11:21:34'),(187015354117993,'2019-08-12 11:21:34'),(187015482793727,'2019-08-12 11:21:34'),(187015724802112,'2019-08-12 11:21:34'),(187016519470394,'2019-08-12 11:21:35'),(187016716197062,'2019-08-12 11:21:35'),(187016848066780,'2019-08-12 11:21:35'),(187017077562507,'2019-08-12 11:21:36'),(187017355439491,'2019-08-12 11:21:36'),(187017578425091,'2019-08-12 11:21:36'),(187017798735971,'2019-08-12 11:21:36'),(187018075056985,'2019-08-12 11:21:37'),(187018305897912,'2019-08-12 11:21:37'),(187018516389452,'2019-08-12 11:21:37'),(187019668297145,'2019-08-12 11:21:38'),(187019887710618,'2019-08-12 11:21:38'),(187020195489404,'2019-08-12 11:21:39'),(187020561588393,'2019-08-12 11:21:39'),(187021097019227,'2019-08-12 11:21:40'),(187021371109667,'2019-08-12 11:21:40'),(187022673204628,'2019-08-12 11:21:41'),(187022958667095,'2019-08-12 11:21:41'),(187023194698474,'2019-08-12 11:21:42'),(187023359207801,'2019-08-12 11:21:42'),(187023585990519,'2019-08-12 11:21:42'),(187023715880909,'2019-08-12 11:21:42'),(187023863735863,'2019-08-12 11:21:42'),(187023939965204,'2019-08-12 11:21:42'),(187024109334244,'2019-08-12 11:21:43'),(187024241117540,'2019-08-12 11:21:43'),(187024353977602,'2019-08-12 11:21:43'),(187024527138290,'2019-08-12 11:21:43'),(187025530376761,'2019-08-12 11:21:44'),(187025885066164,'2019-08-12 11:21:44'),(187026175463098,'2019-08-12 11:21:45'),(187026450657339,'2019-08-12 11:21:45'),(187026663793332,'2019-08-12 11:21:45'),(187026901468197,'2019-08-12 11:21:45'),(187027014659362,'2019-08-12 11:21:45'),(187027159710875,'2019-08-12 11:21:46'),(187027299873137,'2019-08-12 11:21:46'),(187027500860760,'2019-08-12 11:21:46'),(187028272446955,'2019-08-12 11:21:47'),(187028632143754,'2019-08-12 11:21:47'),(187028731370218,'2019-08-12 11:21:47'),(187028906069736,'2019-08-12 11:21:48'),(187029278173080,'2019-08-12 11:21:48'),(187029666949028,'2019-08-12 11:21:48'),(187029815696285,'2019-08-12 11:21:48'),(187030294091585,'2019-08-12 11:21:49'),(187030486985398,'2019-08-12 11:21:49'),(187031143088592,'2019-08-12 11:21:50'),(187031475651295,'2019-08-12 11:21:50'),(187031709389744,'2019-08-12 11:21:50'),(187032034395405,'2019-08-12 11:21:51'),(187032226299190,'2019-08-12 11:21:51'),(187032338336597,'2019-08-12 11:21:51'),(187032516061265,'2019-08-12 11:21:51'),(187032699741790,'2019-08-12 11:21:51'),(187032791580046,'2019-08-12 11:21:51'),(187032904434273,'2019-08-12 11:21:51'),(187033020920796,'2019-08-12 11:21:51'),(187033229418056,'2019-08-12 11:21:52'),(187033323693279,'2019-08-12 11:21:52'),(187033918721691,'2019-08-12 11:21:53'),(187034942814228,'2019-08-12 11:21:53'),(187035084999214,'2019-08-12 11:21:54'),(187035160221387,'2019-08-12 11:21:54'),(187035341397119,'2019-08-12 11:21:54'),(187035526767074,'2019-08-12 11:21:54'),(187035671797072,'2019-08-12 11:21:54'),(187035903769149,'2019-08-12 11:21:54'),(187036115096835,'2019-08-12 11:21:55'),(187036382604947,'2019-08-12 11:21:55'),(187036569527225,'2019-08-12 11:21:55'),(187037987268915,'2019-08-12 11:21:56'),(187038157183474,'2019-08-12 11:21:57'),(187038376320540,'2019-08-12 11:21:57'),(187038711101419,'2019-08-12 11:21:57'),(187038998266810,'2019-08-12 11:21:57'),(187039169080964,'2019-08-12 11:21:58'),(187039306476615,'2019-08-12 11:21:58'),(187039503022050,'2019-08-12 11:21:58'),(187040257063029,'2019-08-12 11:21:59'),(187040473139939,'2019-08-12 11:21:59'),(187040617170062,'2019-08-12 11:21:59'),(187040774968339,'2019-08-12 11:21:59'),(187040939410205,'2019-08-12 11:21:59'),(187041187572816,'2019-08-12 11:22:00'),(187041402129492,'2019-08-12 11:22:00'),(187041673067154,'2019-08-12 11:22:00'),(187041830515365,'2019-08-12 11:22:00'),(187041914784182,'2019-08-12 11:22:00'),(187042068192417,'2019-08-12 11:22:01'),(187042290114329,'2019-08-12 11:22:01'),(187043056678540,'2019-08-12 11:22:02'),(187043480311543,'2019-08-12 11:22:02'),(187043812870964,'2019-08-12 11:22:02'),(187044013363390,'2019-08-12 11:22:02'),(187044189079557,'2019-08-12 11:22:03'),(187044364697632,'2019-08-12 11:22:03'),(187044615322736,'2019-08-12 11:22:03'),(187044854162298,'2019-08-12 11:22:03'),(187045053999809,'2019-08-12 11:22:04'),(187045337227691,'2019-08-12 11:22:04'),(187045767828823,'2019-08-12 11:22:04'),(187046094979001,'2019-08-12 11:22:05'),(187046346840639,'2019-08-12 11:22:05'),(187046491185457,'2019-08-12 11:22:05'),(187047410547112,'2019-08-12 11:22:06'),(187048082692427,'2019-08-12 11:22:07'),(187048149417487,'2019-08-12 11:22:07'),(187048394310631,'2019-08-12 11:22:07'),(187048751338180,'2019-08-12 11:22:07'),(187048898776338,'2019-08-12 11:22:07'),(187049209895698,'2019-08-12 11:22:08'),(187049472599525,'2019-08-12 11:22:08'),(187050545749382,'2019-08-12 11:22:09'),(187051038520345,'2019-08-12 11:22:10'),(187051590461149,'2019-08-12 11:22:11'),(187053332666263,'2019-08-12 11:22:12'),(187054144034134,'2019-08-12 11:22:13'),(187054320953287,'2019-08-12 11:22:13'),(187054449261088,'2019-08-12 11:22:13'),(187054561093196,'2019-08-12 11:22:13'),(187055274076583,'2019-08-12 11:22:14'),(187055744837170,'2019-08-12 11:22:14'),(187056032293188,'2019-08-12 11:22:14'),(187056275485597,'2019-08-12 11:22:15'),(187056432452468,'2019-08-12 11:22:15'),(187056607348533,'2019-08-12 11:22:15'),(188496205774405,'2019-08-12 11:46:15'),(188496461009071,'2019-08-12 11:46:15'),(188496704568319,'2019-08-12 11:46:15'),(188496958887710,'2019-08-12 11:46:16'),(188497244290375,'2019-08-12 11:46:16'),(188497503172287,'2019-08-12 11:46:16'),(188497671031304,'2019-08-12 11:46:16'),(188497932334503,'2019-08-12 11:46:16'),(188498032334029,'2019-08-12 11:46:17'),(188498154176191,'2019-08-12 11:46:17'),(188498244727957,'2019-08-12 11:46:17'),(188498422130637,'2019-08-12 11:46:17'),(188499199479423,'2019-08-12 11:46:18'),(188499697589615,'2019-08-12 11:46:18'),(188500055859168,'2019-08-12 11:46:19'),(188500368643893,'2019-08-12 11:46:19'),(188500764335460,'2019-08-12 11:46:19'),(188500916409435,'2019-08-12 11:46:19'),(188501133433345,'2019-08-12 11:46:20'),(188501228313526,'2019-08-12 11:46:20'),(188501313289037,'2019-08-12 11:46:20'),(188501538159887,'2019-08-12 11:46:20'),(188502190836813,'2019-08-12 11:46:21'),(188502539148822,'2019-08-12 11:46:21'),(188502680182238,'2019-08-12 11:46:21'),(188502877386964,'2019-08-12 11:46:21'),(188503041197253,'2019-08-12 11:46:22'),(188503177954398,'2019-08-12 11:46:22'),(188503424035943,'2019-08-12 11:46:22'),(188503650168851,'2019-08-12 11:46:22'),(188504466699461,'2019-08-12 11:46:23'),(188504699912811,'2019-08-12 11:46:23'),(188504973618179,'2019-08-12 11:46:24'),(188505165290045,'2019-08-12 11:46:24'),(188505349000471,'2019-08-12 11:46:24'),(188505670441297,'2019-08-12 11:46:24'),(188506057036628,'2019-08-12 11:46:25'),(188506244526304,'2019-08-12 11:46:25'),(188506423493705,'2019-08-12 11:46:25'),(188506635840593,'2019-08-12 11:46:25'),(188506918460965,'2019-08-12 11:46:25'),(188507021192462,'2019-08-12 11:46:26'),(188507266281424,'2019-08-12 11:46:26'),(188507384249891,'2019-08-12 11:46:26'),(188507473974262,'2019-08-12 11:46:26'),(188507718768950,'2019-08-12 11:46:27'),(188508263099109,'2019-08-12 11:46:27'),(188508471468011,'2019-08-12 11:46:27'),(188508758707061,'2019-08-12 11:46:27'),(188509117147636,'2019-08-12 11:46:28'),(188509356595072,'2019-08-12 11:46:28'),(188509630297522,'2019-08-12 11:46:28'),(188509897012153,'2019-08-12 11:46:28'),(188510135151219,'2019-08-12 11:46:29'),(188510368620555,'2019-08-12 11:46:29'),(188510494602243,'2019-08-12 11:46:29'),(188511393933216,'2019-08-12 11:46:30'),(188511870579282,'2019-08-12 11:46:30'),(188512221991924,'2019-08-12 11:46:31'),(188512497881191,'2019-08-12 11:46:31'),(188512937597156,'2019-08-12 11:46:32'),(188513228204130,'2019-08-12 11:46:32'),(188513455971408,'2019-08-12 11:46:32'),(188514315104273,'2019-08-12 11:46:33'),(188514812379778,'2019-08-12 11:46:33'),(188514939397077,'2019-08-12 11:46:34'),(188515139296944,'2019-08-12 11:46:34'),(188515537112607,'2019-08-12 11:46:34'),(188515875763535,'2019-08-12 11:46:34'),(188516019028254,'2019-08-12 11:46:35'),(188516168483300,'2019-08-12 11:46:35'),(188516314676172,'2019-08-12 11:46:35'),(188516431316943,'2019-08-12 11:46:35'),(188516617587223,'2019-08-12 11:46:35'),(188517501259324,'2019-08-12 11:46:36'),(188517879043212,'2019-08-12 11:46:36'),(188518254405448,'2019-08-12 11:46:37'),(188518462894320,'2019-08-12 11:46:37'),(188518905181809,'2019-08-12 11:46:37'),(188519149681494,'2019-08-12 11:46:38'),(188519497875356,'2019-08-12 11:46:38'),(188519733372156,'2019-08-12 11:46:38'),(188519914121975,'2019-08-12 11:46:38'),(188520104867261,'2019-08-12 11:46:39'),(188520224878142,'2019-08-12 11:46:39'),(188520367552855,'2019-08-12 11:46:39'),(188520886861344,'2019-08-12 11:46:39'),(188521101108431,'2019-08-12 11:46:40'),(188521306603513,'2019-08-12 11:46:40'),(188521475126561,'2019-08-12 11:46:40'),(188521654562904,'2019-08-12 11:46:40'),(188521824811484,'2019-08-12 11:46:40'),(188521961287483,'2019-08-12 11:46:41'),(188522230013532,'2019-08-12 11:46:41'),(188522625087379,'2019-08-12 11:46:41'),(188523051116508,'2019-08-12 11:46:42'),(188523350093332,'2019-08-12 11:46:42'),(188524156105199,'2019-08-12 11:46:43'),(188524663156651,'2019-08-12 11:46:43'),(188524907368626,'2019-08-12 11:46:43'),(188525147358663,'2019-08-12 11:46:44'),(188526356451764,'2019-08-12 11:46:45'),(188526631698879,'2019-08-12 11:46:45'),(188526812150048,'2019-08-12 11:46:45'),(188526934115827,'2019-08-12 11:46:45'),(188527018189920,'2019-08-12 11:46:46'),(188527085975751,'2019-08-12 11:46:46'),(188527285630936,'2019-08-12 11:46:46'),(188527396494530,'2019-08-12 11:46:46'),(188527491381639,'2019-08-12 11:46:46'),(188527792194120,'2019-08-12 11:46:47'),(188528646387414,'2019-08-12 11:46:47'),(188529087402268,'2019-08-12 11:46:48'),(188529461367888,'2019-08-12 11:46:48'),(188529760826417,'2019-08-12 11:46:48'),(188530018438612,'2019-08-12 11:46:49'),(188530099242144,'2019-08-12 11:46:49'),(188530284654764,'2019-08-12 11:46:49'),(188530399667729,'2019-08-12 11:46:49'),(188530501969301,'2019-08-12 11:46:49'),(188531116425625,'2019-08-12 11:46:50'),(188531782064825,'2019-08-12 11:46:50'),(188531973955482,'2019-08-12 11:46:51'),(188532125871198,'2019-08-12 11:46:51'),(188532354681744,'2019-08-12 11:46:51'),(188532518420926,'2019-08-12 11:46:51'),(188533204647631,'2019-08-12 11:46:52'),(188533758075849,'2019-08-12 11:46:52'),(188534052336997,'2019-08-12 11:46:53'),(188534265875931,'2019-08-12 11:46:53'),(188534435529034,'2019-08-12 11:46:53'),(188534656166642,'2019-08-12 11:46:53'),(188534812323987,'2019-08-12 11:46:53'),(188534924389837,'2019-08-12 11:46:53'),(188535099807719,'2019-08-12 11:46:54'),(188535336633674,'2019-08-12 11:46:54'),(188535513726765,'2019-08-12 11:46:54'),(188536580980934,'2019-08-12 11:46:55'),(188536991848576,'2019-08-12 11:46:56'),(188537469677571,'2019-08-12 11:46:56'),(188538669418814,'2019-08-12 11:46:57'),(188538908627039,'2019-08-12 11:46:57'),(188539196020702,'2019-08-12 11:46:58'),(188539544947513,'2019-08-12 11:46:58'),(188539674873639,'2019-08-12 11:46:58'),(188539840295688,'2019-08-12 11:46:58'),(188540069151816,'2019-08-12 11:46:59'),(188540224465721,'2019-08-12 11:46:59'),(188540358740318,'2019-08-12 11:46:59'),(188540458945507,'2019-08-12 11:46:59'),(188541481412062,'2019-08-12 11:47:00'),(188541995952730,'2019-08-12 11:47:01'),(188542374473579,'2019-08-12 11:47:01'),(188542522317594,'2019-08-12 11:47:01'),(188542658980295,'2019-08-12 11:47:01'),(188543072612725,'2019-08-12 11:47:02'),(188543446447435,'2019-08-12 11:47:02'),(188543789039883,'2019-08-12 11:47:02'),(188544040567135,'2019-08-12 11:47:03'),(188544212639337,'2019-08-12 11:47:03'),(188544504655690,'2019-08-12 11:47:03'),(188544671650482,'2019-08-12 11:47:03'),(188544909012111,'2019-08-12 11:47:03'),(188545026528774,'2019-08-12 11:47:04'),(188545193192463,'2019-08-12 11:47:04'),(188545335302695,'2019-08-12 11:47:04'),(188545488999734,'2019-08-12 11:47:04'),(188545579074535,'2019-08-12 11:47:04'),(188545768085538,'2019-08-12 11:47:04'),(188546570189797,'2019-08-12 11:47:05'),(188546819145161,'2019-08-12 11:47:05'),(188547105470759,'2019-08-12 11:47:06'),(188547336273398,'2019-08-12 11:47:06'),(188547571746495,'2019-08-12 11:47:06'),(188548108399642,'2019-08-12 11:47:07'),(188548446154255,'2019-08-12 11:47:07'),(188549231388633,'2019-08-12 11:47:08'),(188549801147777,'2019-08-12 11:47:08'),(188549935113514,'2019-08-12 11:47:08'),(188550107906633,'2019-08-12 11:47:09'),(188550486312251,'2019-08-12 11:47:09'),(188550752604980,'2019-08-12 11:47:09'),(188550976543050,'2019-08-12 11:47:10'),(188551131147343,'2019-08-12 11:47:10'),(188551360756112,'2019-08-12 11:47:10'),(188551488573457,'2019-08-12 11:47:10'),(188552705749791,'2019-08-12 11:47:12'),(188553429234782,'2019-08-12 11:47:12'),(188553684604004,'2019-08-12 11:47:12'),(188553969476101,'2019-08-12 11:47:13'),(188554221399730,'2019-08-12 11:47:13'),(188554720531312,'2019-08-12 11:47:13'),(188555181926914,'2019-08-12 11:47:14'),(188555530905506,'2019-08-12 11:47:14'),(188555857596588,'2019-08-12 11:47:14'),(188556033915888,'2019-08-12 11:47:15'),(188556245070365,'2019-08-12 11:47:15'),(188556477365887,'2019-08-12 11:47:15'),(188557205329165,'2019-08-12 11:47:16'),(188557512966831,'2019-08-12 11:47:16'),(188557802888624,'2019-08-12 11:47:16'),(188557996857431,'2019-08-12 11:47:17'),(188558114491148,'2019-08-12 11:47:17'),(188558248858731,'2019-08-12 11:47:17'),(188558393456617,'2019-08-12 11:47:17'),(188558667348686,'2019-08-12 11:47:17'),(188558971118127,'2019-08-12 11:47:18'),(188559150862601,'2019-08-12 11:47:18'),(188559502675996,'2019-08-12 11:47:18'),(188559884147606,'2019-08-12 11:47:18'),(188560062426910,'2019-08-12 11:47:19'),(188560206247723,'2019-08-12 11:47:19'),(188560404282761,'2019-08-12 11:47:19'),(188560487452882,'2019-08-12 11:47:19'),(188560583658936,'2019-08-12 11:47:19'),(188560690939098,'2019-08-12 11:47:19'),(188561613937425,'2019-08-12 11:47:20'),(188562064921856,'2019-08-12 11:47:21'),(188562297846403,'2019-08-12 11:47:21'),(188562503424990,'2019-08-12 11:47:21'),(188562663561779,'2019-08-12 11:47:21'),(188562979190057,'2019-08-12 11:47:22'),(188563167433468,'2019-08-12 11:47:22'),(188563424880840,'2019-08-12 11:47:22'),(188563540236214,'2019-08-12 11:47:22'),(188563691917094,'2019-08-12 11:47:22'),(188563786334167,'2019-08-12 11:47:22'),(188564040990860,'2019-08-12 11:47:23'),(188564274815367,'2019-08-12 11:47:23'),(188564449697576,'2019-08-12 11:47:23'),(188565130809311,'2019-08-12 11:47:24'),(188565509040991,'2019-08-12 11:47:24'),(188565917511048,'2019-08-12 11:47:25'),(188566311962435,'2019-08-12 11:47:25'),(188566609508730,'2019-08-12 11:47:25'),(188567258175217,'2019-08-12 11:47:26'),(188567536107992,'2019-08-12 11:47:26'),(188567990580682,'2019-08-12 11:47:27'),(188568205266445,'2019-08-12 11:47:27'),(188568381171866,'2019-08-12 11:47:27'),(188568534393400,'2019-08-12 11:47:27'),(188569203350565,'2019-08-12 11:47:28'),(188569692677028,'2019-08-12 11:47:28'),(188569968055782,'2019-08-12 11:47:29'),(188570348291953,'2019-08-12 11:47:29'),(188570873632145,'2019-08-12 11:47:30'),(188571683412687,'2019-08-12 11:47:30'),(188571998014471,'2019-08-12 11:47:31'),(188572202021045,'2019-08-12 11:47:31'),(188572461331058,'2019-08-12 11:47:31'),(188572693124820,'2019-08-12 11:47:31'),(188572907198698,'2019-08-12 11:47:31'),(188573191643058,'2019-08-12 11:47:32'),(188573467068853,'2019-08-12 11:47:32'),(188573861294885,'2019-08-12 11:47:33'),(188574967867258,'2019-08-12 11:47:34'),(188575181124680,'2019-08-12 11:47:34'),(188575437792792,'2019-08-12 11:47:34'),(188576175684442,'2019-08-12 11:47:35'),(188576571763269,'2019-08-12 11:47:35'),(188576791825457,'2019-08-12 11:47:35'),(188576995202277,'2019-08-12 11:47:36'),(188577219148735,'2019-08-12 11:47:36'),(188577344666221,'2019-08-12 11:47:36'),(188577498637114,'2019-08-12 11:47:36'),(188577628847303,'2019-08-12 11:47:36'),(188577838520929,'2019-08-12 11:47:36'),(188578001579671,'2019-08-12 11:47:37'),(188578205894740,'2019-08-12 11:47:37'),(188578380540654,'2019-08-12 11:47:37'),(188578559436219,'2019-08-12 11:47:37'),(188579347646884,'2019-08-12 11:47:38'),(188579703184466,'2019-08-12 11:47:38'),(188579827410721,'2019-08-12 11:47:38'),(188579884178602,'2019-08-12 11:47:38'),(188579962738067,'2019-08-12 11:47:39'),(188580195973661,'2019-08-12 11:47:39'),(188580368820384,'2019-08-12 11:47:39'),(188580470962968,'2019-08-12 11:47:39'),(188580892732601,'2019-08-12 11:47:39'),(188581240684334,'2019-08-12 11:47:40'),(188581461802553,'2019-08-12 11:47:40'),(188581648526460,'2019-08-12 11:47:40'),(188582864180738,'2019-08-12 11:47:42'),(188583382284418,'2019-08-12 11:47:42'),(188583918973301,'2019-08-12 11:47:42'),(188584016407502,'2019-08-12 11:47:43'),(188584129170566,'2019-08-12 11:47:43'),(188584357281711,'2019-08-12 11:47:43'),(188584692041075,'2019-08-12 11:47:43'),(188585155520297,'2019-08-12 11:47:44'),(188585466433629,'2019-08-12 11:47:44'),(188585698163577,'2019-08-12 11:47:44'),(188585823222696,'2019-08-12 11:47:44'),(188586040253535,'2019-08-12 11:47:45'),(188586274044494,'2019-08-12 11:47:45'),(188586531627152,'2019-08-12 11:47:45'),(188586840607101,'2019-08-12 11:47:46'),(188587955648873,'2019-08-12 11:47:47'),(188588209059552,'2019-08-12 11:47:47'),(188588357152624,'2019-08-12 11:47:47'),(188588517186580,'2019-08-12 11:47:47'),(188588746521496,'2019-08-12 11:47:48'),(188589331684986,'2019-08-12 11:47:48'),(188589837110456,'2019-08-12 11:47:48'),(188590155101313,'2019-08-12 11:47:49'),(188590404082202,'2019-08-12 11:47:49'),(188590733627777,'2019-08-12 11:47:49'),(188591455034253,'2019-08-12 11:47:50'),(188591896226329,'2019-08-12 11:47:50'),(188592130488053,'2019-08-12 11:47:51'),(188592275033794,'2019-08-12 11:47:51'),(188592354297037,'2019-08-12 11:47:51'),(188592497449443,'2019-08-12 11:47:51'),(188592851363232,'2019-08-12 11:47:51'),(188592979664469,'2019-08-12 11:47:52'),(188593166349723,'2019-08-12 11:47:52'),(188593377960379,'2019-08-12 11:47:52'),(188593523468070,'2019-08-12 11:47:52'),(188593690025645,'2019-08-12 11:47:52'),(188593878674549,'2019-08-12 11:47:52'),(188594034758234,'2019-08-12 11:47:53'),(188594222169509,'2019-08-12 11:47:53'),(188594289400341,'2019-08-12 11:47:53'),(188594496670547,'2019-08-12 11:47:53'),(188595458224955,'2019-08-12 11:47:54'),(188595821984704,'2019-08-12 11:47:54'),(188596014978068,'2019-08-12 11:47:55'),(188596355315874,'2019-08-12 11:47:55'),(188596612315454,'2019-08-12 11:47:55'),(188597130032238,'2019-08-12 11:47:56'),(188597389312350,'2019-08-12 11:47:56'),(188597552890721,'2019-08-12 11:47:56'),(188597741373343,'2019-08-12 11:47:56'),(188598002489112,'2019-08-12 11:47:57'),(188598325134383,'2019-08-12 11:47:57'),(188598817944728,'2019-08-12 11:47:57'),(188598940419560,'2019-08-12 11:47:57'),(188599057422065,'2019-08-12 11:47:58'),(188599282992317,'2019-08-12 11:47:58'),(188599575219438,'2019-08-12 11:47:58'),(188600482869210,'2019-08-12 11:47:59'),(188600659571760,'2019-08-12 11:47:59'),(188600919001744,'2019-08-12 11:47:59'),(188601126105304,'2019-08-12 11:48:00'),(188601391559699,'2019-08-12 11:48:00'),(188601613666488,'2019-08-12 11:48:00'),(188602023355575,'2019-08-12 11:48:01'),(188602304380597,'2019-08-12 11:48:01'),(188602709305874,'2019-08-12 11:48:01'),(188602908223734,'2019-08-12 11:48:01'),(188603049272465,'2019-08-12 11:48:02'),(188603207941165,'2019-08-12 11:48:02'),(188603391638828,'2019-08-12 11:48:02'),(188603612767987,'2019-08-12 11:48:02'),(188605141291588,'2019-08-12 11:48:04'),(188605269102734,'2019-08-12 11:48:04'),(188605579344013,'2019-08-12 11:48:04'),(188606357876822,'2019-08-12 11:48:05'),(188606935120077,'2019-08-12 11:48:06'),(188607380066971,'2019-08-12 11:48:06'),(188607700431346,'2019-08-12 11:48:06'),(188608143266542,'2019-08-12 11:48:07'),(188608291664828,'2019-08-12 11:48:07'),(188608587482309,'2019-08-12 11:48:07'),(188609583460931,'2019-08-12 11:48:08'),(188610038643962,'2019-08-12 11:48:09'),(188610193327384,'2019-08-12 11:48:09'),(188610284802083,'2019-08-12 11:48:09'),(188610355206478,'2019-08-12 11:48:09'),(188610439503373,'2019-08-12 11:48:09'),(188610546068817,'2019-08-12 11:48:09'),(188610729734026,'2019-08-12 11:48:09'),(188610982699830,'2019-08-12 11:48:10'),(188611098370626,'2019-08-12 11:48:10'),(188611307376210,'2019-08-12 11:48:10'),(188611563279283,'2019-08-12 11:48:10'),(188612250295823,'2019-08-12 11:48:11'),(188612964401973,'2019-08-12 11:48:12'),(188613076208920,'2019-08-12 11:48:12'),(188613190983768,'2019-08-12 11:48:12'),(188613554846348,'2019-08-12 11:48:12'),(188614472001496,'2019-08-12 11:48:13'),(188614759811956,'2019-08-12 11:48:13'),(188615114476197,'2019-08-12 11:48:14'),(188615505124267,'2019-08-12 11:48:14'),(188616117435711,'2019-08-12 11:48:15'),(188616583329656,'2019-08-12 11:48:15'),(188616837633002,'2019-08-12 11:48:15'),(188616999894980,'2019-08-12 11:48:16'),(188617203726886,'2019-08-12 11:48:16'),(188617455322328,'2019-08-12 11:48:16'),(188618508886379,'2019-08-12 11:48:17'),(188619171103322,'2019-08-12 11:48:18'),(188619501695812,'2019-08-12 11:48:18'),(188619643633929,'2019-08-12 11:48:18'),(188619824417660,'2019-08-12 11:48:18'),(188619991187462,'2019-08-12 11:48:19'),(188620198406982,'2019-08-12 11:48:19'),(188620367471538,'2019-08-12 11:48:19'),(188620605150048,'2019-08-12 11:48:19'),(188621773050271,'2019-08-12 11:48:21'),(188622145674702,'2019-08-12 11:48:21'),(188622341114149,'2019-08-12 11:48:21'),(188622526730244,'2019-08-12 11:48:21'),(188622644901823,'2019-08-12 11:48:21'),(188622929542730,'2019-08-12 11:48:21'),(188623069969000,'2019-08-12 11:48:22'),(188623355012119,'2019-08-12 11:48:22'),(188624329784421,'2019-08-12 11:48:23'),(188625171172971,'2019-08-12 11:48:24'),(188625660704368,'2019-08-12 11:48:24'),(188625819416827,'2019-08-12 11:48:24'),(188625918939753,'2019-08-12 11:48:24'),(188626909289611,'2019-08-12 11:48:26'),(188627339990657,'2019-08-12 11:48:26'),(188627731214877,'2019-08-12 11:48:26'),(188627882724006,'2019-08-12 11:48:26'),(188628140377042,'2019-08-12 11:48:27'),(188628555636913,'2019-08-12 11:48:27'),(188628754619316,'2019-08-12 11:48:27'),(188628909579144,'2019-08-12 11:48:27'),(188628981896502,'2019-08-12 11:48:28'),(188629836337030,'2019-08-12 11:48:29'),(188630495857009,'2019-08-12 11:48:29'),(188630789540549,'2019-08-12 11:48:29'),(188631005700235,'2019-08-12 11:48:30'),(188631779923226,'2019-08-12 11:48:30'),(188631896120944,'2019-08-12 11:48:30'),(188632083480439,'2019-08-12 11:48:31'),(188632231271215,'2019-08-12 11:48:31'),(188632384824947,'2019-08-12 11:48:31'),(188632517946515,'2019-08-12 11:48:31'),(188632709195749,'2019-08-12 11:48:31'),(188632986483091,'2019-08-12 11:48:32'),(188634134049606,'2019-08-12 11:48:33'),(188634396755985,'2019-08-12 11:48:33'),(188634546546511,'2019-08-12 11:48:33'),(188634670944517,'2019-08-12 11:48:33'),(188634791091778,'2019-08-12 11:48:33'),(188634888396892,'2019-08-12 11:48:33'),(188634992391907,'2019-08-12 11:48:34'),(188635124544960,'2019-08-12 11:48:34'),(188635289392318,'2019-08-12 11:48:34'),(188635447765651,'2019-08-12 11:48:34'),(188635631464773,'2019-08-12 11:48:34'),(188635920628819,'2019-08-12 11:48:35'),(188636810259694,'2019-08-12 11:48:36'),(188637434754879,'2019-08-12 11:48:36'),(188637748637934,'2019-08-12 11:48:36'),(188637924180527,'2019-08-12 11:48:36'),(188638166232670,'2019-08-12 11:48:37'),(188638489858489,'2019-08-12 11:48:37'),(188638728446806,'2019-08-12 11:48:37'),(188638928473207,'2019-08-12 11:48:37'),(188639049170362,'2019-08-12 11:48:38'),(188639222161487,'2019-08-12 11:48:38'),(188639405884675,'2019-08-12 11:48:38'),(188639590421037,'2019-08-12 11:48:38'),(188639780458170,'2019-08-12 11:48:38'),(188639957376958,'2019-08-12 11:48:39'),(188640744385366,'2019-08-12 11:48:39'),(188641185071305,'2019-08-12 11:48:40'),(188641540042219,'2019-08-12 11:48:40'),(188641774022432,'2019-08-12 11:48:40'),(188642739120890,'2019-08-12 11:48:42'),(188643969188026,'2019-08-12 11:48:43'),(188644319631789,'2019-08-12 11:48:43'),(188644624769038,'2019-08-12 11:48:43'),(188644807424162,'2019-08-12 11:48:43'),(188644950805570,'2019-08-12 11:48:44'),(188645054374671,'2019-08-12 11:48:44'),(188645147770355,'2019-08-12 11:48:44'),(188646066611652,'2019-08-12 11:48:45'),(188646434029587,'2019-08-12 11:48:45'),(188646658845374,'2019-08-12 11:48:45'),(188646794993186,'2019-08-12 11:48:45'),(188646943270043,'2019-08-12 11:48:45'),(188647055674654,'2019-08-12 11:48:46'),(188647239118155,'2019-08-12 11:48:46'),(188711983239149,'2019-08-12 11:49:51'),(188712372631359,'2019-08-12 11:49:51'),(188712538379043,'2019-08-12 11:49:51'),(188712707742612,'2019-08-12 11:49:51'),(188712859678749,'2019-08-12 11:49:51'),(188713504436899,'2019-08-12 11:49:52'),(188713656675696,'2019-08-12 11:49:52'),(188713873670069,'2019-08-12 11:49:52'),(188714297004422,'2019-08-12 11:49:53'),(188714792199225,'2019-08-12 11:49:54'),(188715629043485,'2019-08-12 11:49:54'),(188716071065508,'2019-08-12 11:49:55'),(188716398445781,'2019-08-12 11:49:55'),(188716817692024,'2019-08-12 11:49:55'),(188716998187316,'2019-08-12 11:49:56'),(188717136247362,'2019-08-12 11:49:56'),(188717826941414,'2019-08-12 11:49:56'),(188718038921097,'2019-08-12 11:49:57'),(188718551855475,'2019-08-12 11:49:57'),(188718657724799,'2019-08-12 11:49:57'),(188718797989529,'2019-08-12 11:49:57'),(188718941824928,'2019-08-12 11:49:57'),(188719220547903,'2019-08-12 11:49:58'),(188719457479607,'2019-08-12 11:49:58'),(188719671076521,'2019-08-12 11:49:58'),(188719795747650,'2019-08-12 11:49:58'),(188719948537801,'2019-08-12 11:49:59'),(188720064956863,'2019-08-12 11:49:59'),(188720640866952,'2019-08-12 11:50:00'),(188721226443956,'2019-08-12 11:50:00'),(188721369742588,'2019-08-12 11:50:00'),(188721729371198,'2019-08-12 11:50:00'),(188722051718548,'2019-08-12 11:50:01'),(188722217147162,'2019-08-12 11:50:01'),(188722376747182,'2019-08-12 11:50:01'),(188722526165034,'2019-08-12 11:50:01'),(188722860942631,'2019-08-12 11:50:01'),(188723983656311,'2019-08-12 11:50:03'),(188724440707818,'2019-08-12 11:50:03'),(188724606652413,'2019-08-12 11:50:03'),(188724896561808,'2019-08-12 11:50:03'),(188725261262358,'2019-08-12 11:50:04'),(188725444759098,'2019-08-12 11:50:04'),(188725609688138,'2019-08-12 11:50:04'),(188725716526342,'2019-08-12 11:50:04'),(188725959128015,'2019-08-12 11:50:05'),(188726655651754,'2019-08-12 11:50:05'),(188726918493784,'2019-08-12 11:50:06'),(188727136138331,'2019-08-12 11:50:06'),(188727285580979,'2019-08-12 11:50:06'),(188727484840153,'2019-08-12 11:50:06'),(188727744933438,'2019-08-12 11:50:06'),(188728143995116,'2019-08-12 11:50:07'),(188728381269957,'2019-08-12 11:50:07'),(188728602173396,'2019-08-12 11:50:07'),(188728804337750,'2019-08-12 11:50:07'),(188728956926613,'2019-08-12 11:50:08'),(188729338550283,'2019-08-12 11:50:08'),(188730147186912,'2019-08-12 11:50:09'),(188730302044273,'2019-08-12 11:50:09'),(188730523215731,'2019-08-12 11:50:09'),(188730636503530,'2019-08-12 11:50:09'),(188730752911287,'2019-08-12 11:50:09'),(188730922184424,'2019-08-12 11:50:09'),(188731248007999,'2019-08-12 11:50:10'),(188731321900652,'2019-08-12 11:50:10'),(188731530509130,'2019-08-12 11:50:10'),(188731745324709,'2019-08-12 11:50:10'),(188731904315397,'2019-08-12 11:50:10'),(188733014376757,'2019-08-12 11:50:12'),(188733405828154,'2019-08-12 11:50:12'),(188733523523133,'2019-08-12 11:50:12'),(188733602550811,'2019-08-12 11:50:12'),(188733798839167,'2019-08-12 11:50:12'),(188734023741012,'2019-08-12 11:50:13'),(188734331189424,'2019-08-12 11:50:13'),(188734682789133,'2019-08-12 11:50:13'),(188734918001139,'2019-08-12 11:50:13'),(188735050869274,'2019-08-12 11:50:14'),(188735942090394,'2019-08-12 11:50:15'),(188736325834514,'2019-08-12 11:50:15'),(188736616038183,'2019-08-12 11:50:15'),(188736885962842,'2019-08-12 11:50:15'),(188737835289385,'2019-08-12 11:50:16'),(188738045994246,'2019-08-12 11:50:17'),(188738255123447,'2019-08-12 11:50:17'),(188738513123267,'2019-08-12 11:50:17'),(188738975830886,'2019-08-12 11:50:18'),(188739075245146,'2019-08-12 11:50:18'),(188739191673689,'2019-08-12 11:50:18'),(188739296521988,'2019-08-12 11:50:18'),(188739586105749,'2019-08-12 11:50:18'),(188740086026073,'2019-08-12 11:50:19'),(188741042698889,'2019-08-12 11:50:20'),(188741446383986,'2019-08-12 11:50:20'),(188741668239530,'2019-08-12 11:50:20'),(188741779722303,'2019-08-12 11:50:20'),(188741943651833,'2019-08-12 11:50:21'),(188742075912458,'2019-08-12 11:50:21'),(188743024895864,'2019-08-12 11:50:22'),(188743394371528,'2019-08-12 11:50:22'),(188743701793320,'2019-08-12 11:50:22'),(188744093648752,'2019-08-12 11:50:23'),(188744380225960,'2019-08-12 11:50:23'),(188744601880946,'2019-08-12 11:50:23'),(188744766047864,'2019-08-12 11:50:23'),(188745034225842,'2019-08-12 11:50:24'),(188745915728995,'2019-08-12 11:50:25'),(188746216443019,'2019-08-12 11:50:25'),(188746449941892,'2019-08-12 11:50:25'),(188746595139265,'2019-08-12 11:50:25'),(188746938407412,'2019-08-12 11:50:25'),(188747093708919,'2019-08-12 11:50:26'),(188747275656619,'2019-08-12 11:50:26'),(188747483692594,'2019-08-12 11:50:26'),(188747641491965,'2019-08-12 11:50:26'),(188747768659135,'2019-08-12 11:50:26'),(188747851017177,'2019-08-12 11:50:26'),(188747983865256,'2019-08-12 11:50:27'),(188748909611598,'2019-08-12 11:50:28'),(188749461082366,'2019-08-12 11:50:28'),(188749810195150,'2019-08-12 11:50:28'),(188750070607506,'2019-08-12 11:50:29'),(188750443355554,'2019-08-12 11:50:29'),(188750698877200,'2019-08-12 11:50:29'),(188750792003042,'2019-08-12 11:50:29'),(188751072991963,'2019-08-12 11:50:30'),(188751539115274,'2019-08-12 11:50:30'),(188751810824174,'2019-08-12 11:50:30'),(188751957348880,'2019-08-12 11:50:31'),(188752094588094,'2019-08-12 11:50:31'),(188752815640129,'2019-08-12 11:50:31'),(188752965133099,'2019-08-12 11:50:32'),(188753220289365,'2019-08-12 11:50:32'),(188753375250652,'2019-08-12 11:50:32'),(188753523751040,'2019-08-12 11:50:32'),(188753585143433,'2019-08-12 11:50:32'),(188753739752831,'2019-08-12 11:50:32'),(188753904236997,'2019-08-12 11:50:32'),(188754111732923,'2019-08-12 11:50:33'),(188754361724262,'2019-08-12 11:50:33'),(188754552880146,'2019-08-12 11:50:33'),(188754756307653,'2019-08-12 11:50:33'),(188754937814853,'2019-08-12 11:50:34'),(188755929319563,'2019-08-12 11:50:35'),(188756478169579,'2019-08-12 11:50:35'),(188756817880914,'2019-08-12 11:50:35'),(188757056335768,'2019-08-12 11:50:36'),(188757602630670,'2019-08-12 11:50:36'),(188757872663266,'2019-08-12 11:50:36'),(188758306669880,'2019-08-12 11:50:37'),(188758730063671,'2019-08-12 11:50:37'),(188758905718941,'2019-08-12 11:50:37'),(188758995826196,'2019-08-12 11:50:38'),(188759214900543,'2019-08-12 11:50:38'),(188759888912874,'2019-08-12 11:50:38'),(188760288224339,'2019-08-12 11:50:39'),(188760525601283,'2019-08-12 11:50:39'),(188760700865646,'2019-08-12 11:50:39'),(188760777604406,'2019-08-12 11:50:39'),(188760913405070,'2019-08-12 11:50:40'),(188761907540741,'2019-08-12 11:50:41'),(188762238852324,'2019-08-12 11:50:41'),(188762418946134,'2019-08-12 11:50:41'),(188762680491098,'2019-08-12 11:50:41'),(188762964642643,'2019-08-12 11:50:42'),(188763066830443,'2019-08-12 11:50:42'),(188763502758043,'2019-08-12 11:50:42'),(188763638157954,'2019-08-12 11:50:42'),(188763855421440,'2019-08-12 11:50:42'),(188764101150366,'2019-08-12 11:50:43'),(188764323700208,'2019-08-12 11:50:43'),(188764401387791,'2019-08-12 11:50:43'),(188764465454540,'2019-08-12 11:50:43'),(188764632408856,'2019-08-12 11:50:43'),(188764756345577,'2019-08-12 11:50:43'),(188764965009118,'2019-08-12 11:50:44'),(188765095348393,'2019-08-12 11:50:44'),(188765927881012,'2019-08-12 11:50:45'),(188766370567066,'2019-08-12 11:50:45'),(188766634615728,'2019-08-12 11:50:45'),(188766842945977,'2019-08-12 11:50:45'),(188767122777128,'2019-08-12 11:50:46'),(188767950349755,'2019-08-12 11:50:47'),(188768314093094,'2019-08-12 11:50:47'),(188768714627601,'2019-08-12 11:50:47'),(188769570202925,'2019-08-12 11:50:48'),(188769974940771,'2019-08-12 11:50:49'),(188770291710774,'2019-08-12 11:50:49'),(188770458217662,'2019-08-12 11:50:49'),(188770805242451,'2019-08-12 11:50:49'),(188770953435438,'2019-08-12 11:50:50'),(188771062988838,'2019-08-12 11:50:50'),(188771148412507,'2019-08-12 11:50:50'),(188772256486150,'2019-08-12 11:50:51'),(188772426856159,'2019-08-12 11:50:51'),(188772675111756,'2019-08-12 11:50:51'),(188773071581855,'2019-08-12 11:50:52'),(188773189998114,'2019-08-12 11:50:52'),(188773417805139,'2019-08-12 11:50:52'),(188773753081580,'2019-08-12 11:50:52'),(188774435677812,'2019-08-12 11:50:53'),(188775212384081,'2019-08-12 11:50:54'),(188775713962841,'2019-08-12 11:50:54'),(188775977300432,'2019-08-12 11:50:55'),(188776411048873,'2019-08-12 11:50:55'),(188776702227985,'2019-08-12 11:50:55'),(188776853522699,'2019-08-12 11:50:55'),(188777142339233,'2019-08-12 11:50:56'),(188777948724503,'2019-08-12 11:50:57'),(188778269999412,'2019-08-12 11:50:57'),(188778603651330,'2019-08-12 11:50:57'),(188778933297184,'2019-08-12 11:50:57'),(188779444595734,'2019-08-12 11:50:58'),(188779645385715,'2019-08-12 11:50:58'),(188779898489357,'2019-08-12 11:50:58'),(188780077617934,'2019-08-12 11:50:59'),(188781420162248,'2019-08-12 11:51:00'),(188781609766539,'2019-08-12 11:51:00'),(188781840322672,'2019-08-12 11:51:00'),(188781961383386,'2019-08-12 11:51:01'),(188782123794871,'2019-08-12 11:51:01'),(188782392453095,'2019-08-12 11:51:01'),(188782515554764,'2019-08-12 11:51:01'),(188782625653683,'2019-08-12 11:51:01'),(188782835002040,'2019-08-12 11:51:01'),(188783033300356,'2019-08-12 11:51:02'),(188784138481218,'2019-08-12 11:51:03'),(188784543601584,'2019-08-12 11:51:03'),(188784767542572,'2019-08-12 11:51:03'),(188785021213976,'2019-08-12 11:51:04'),(188786146140362,'2019-08-12 11:51:05'),(188786644887966,'2019-08-12 11:51:05'),(188786880014279,'2019-08-12 11:51:05'),(188787223236115,'2019-08-12 11:51:06'),(188787712115515,'2019-08-12 11:51:06'),(188787923455964,'2019-08-12 11:51:06'),(188787990318497,'2019-08-12 11:51:07'),(188788199510054,'2019-08-12 11:51:07'),(188788535717450,'2019-08-12 11:51:07'),(188788703738008,'2019-08-12 11:51:07'),(188788918788422,'2019-08-12 11:51:07'),(188789047319755,'2019-08-12 11:51:08'),(188789239000008,'2019-08-12 11:51:09'),(188790742546063,'2019-08-12 11:51:09'),(188790960748527,'2019-08-12 11:51:10'),(188791164741244,'2019-08-12 11:51:10'),(188791348966558,'2019-08-12 11:51:10'),(188791796276760,'2019-08-12 11:51:10'),(188792000168469,'2019-08-12 11:51:11'),(188792181712863,'2019-08-12 11:51:11'),(188792373483550,'2019-08-12 11:51:11'),(188792692801009,'2019-08-12 11:51:11'),(188792887542513,'2019-08-12 11:51:11'),(188793025736386,'2019-08-12 11:51:12'),(188793267649232,'2019-08-12 11:51:12'),(188793464420023,'2019-08-12 11:51:12'),(188793735162231,'2019-08-12 11:51:12'),(188793976225074,'2019-08-12 11:51:13'),(188794158029830,'2019-08-12 11:51:13'),(188794948512275,'2019-08-12 11:51:14'),(188795198591496,'2019-08-12 11:51:14'),(188795453919878,'2019-08-12 11:51:14'),(188795590243452,'2019-08-12 11:51:14'),(188795794903117,'2019-08-12 11:51:14'),(188796180206487,'2019-08-12 11:51:15'),(188796458582679,'2019-08-12 11:51:15'),(188796837221310,'2019-08-12 11:51:15'),(188797200590881,'2019-08-12 11:51:16'),(188797453456405,'2019-08-12 11:51:16'),(188797641153568,'2019-08-12 11:51:16'),(188797829348115,'2019-08-12 11:51:16'),(188798199098726,'2019-08-12 11:51:17'),(188799453884506,'2019-08-12 11:51:18'),(188799854622853,'2019-08-12 11:51:18'),(188800049833664,'2019-08-12 11:51:19'),(188800830160559,'2019-08-12 11:51:19'),(188801103731735,'2019-08-12 11:51:20'),(188801326511672,'2019-08-12 11:51:20'),(188801621471128,'2019-08-12 11:51:20'),(188801754359684,'2019-08-12 11:51:20'),(188802023303430,'2019-08-12 11:51:21'),(188803090200241,'2019-08-12 11:51:22'),(188803788788273,'2019-08-12 11:51:22'),(188804144741558,'2019-08-12 11:51:23'),(188804627114843,'2019-08-12 11:51:23'),(188804827098579,'2019-08-12 11:51:23'),(188805090821243,'2019-08-12 11:51:24'),(188805744736891,'2019-08-12 11:51:25'),(188806249887049,'2019-08-12 11:51:25'),(188806420538568,'2019-08-12 11:51:25'),(188806612988966,'2019-08-12 11:51:25'),(188806722515746,'2019-08-12 11:51:25'),(188806865334496,'2019-08-12 11:51:25'),(188806954948378,'2019-08-12 11:51:26'),(188807068955633,'2019-08-12 11:51:26'),(188807158748923,'2019-08-12 11:51:26'),(188807447080835,'2019-08-12 11:51:26'),(188807723258542,'2019-08-12 11:51:26'),(188807999997082,'2019-08-12 11:51:27'),(188808276438797,'2019-08-12 11:51:27'),(188809475085355,'2019-08-12 11:51:28'),(188809657858262,'2019-08-12 11:51:28'),(188809806814829,'2019-08-12 11:51:28'),(188810055063498,'2019-08-12 11:51:29'),(188810176452763,'2019-08-12 11:51:29'),(188810549323334,'2019-08-12 11:51:29'),(188810679793154,'2019-08-12 11:51:29'),(188810867883047,'2019-08-12 11:51:29'),(188811171723595,'2019-08-12 11:51:30'),(188811590872111,'2019-08-12 11:51:30'),(188811827106966,'2019-08-12 11:51:30'),(188812056160006,'2019-08-12 11:51:31'),(188812224128418,'2019-08-12 11:51:31'),(188812740985719,'2019-08-12 11:51:31'),(188813182702893,'2019-08-12 11:51:32'),(188813588392115,'2019-08-12 11:51:32'),(188813998911514,'2019-08-12 11:51:33'),(188815383915870,'2019-08-12 11:51:34'),(188815761838325,'2019-08-12 11:51:34'),(188816069595232,'2019-08-12 11:51:35'),(188816383053469,'2019-08-12 11:51:35'),(188816702739956,'2019-08-12 11:51:35'),(188816865993787,'2019-08-12 11:51:35'),(188817117105336,'2019-08-12 11:51:36'),(188817429243533,'2019-08-12 11:51:36'),(188817715887108,'2019-08-12 11:51:36'),(188817983099123,'2019-08-12 11:51:37'),(188818128091927,'2019-08-12 11:51:37'),(188818880793175,'2019-08-12 11:51:38'),(188819515864718,'2019-08-12 11:51:38'),(188819645779904,'2019-08-12 11:51:38'),(188819930039021,'2019-08-12 11:51:38'),(188820142012870,'2019-08-12 11:51:39'),(188820404490612,'2019-08-12 11:51:39'),(188820685393110,'2019-08-12 11:51:39'),(188820917679152,'2019-08-12 11:51:40'),(188821878389027,'2019-08-12 11:51:41'),(188822534455755,'2019-08-12 11:51:41'),(188822767387230,'2019-08-12 11:51:41'),(188822952712333,'2019-08-12 11:51:42'),(188823959674263,'2019-08-12 11:51:43'),(188825409206652,'2019-08-12 11:51:44'),(188825574954701,'2019-08-12 11:51:44'),(188825774771791,'2019-08-12 11:51:44'),(188825910550941,'2019-08-12 11:51:44'),(188826172994771,'2019-08-12 11:51:45'),(188826464823692,'2019-08-12 11:51:46'),(188827317384440,'2019-08-12 11:51:46'),(188827592973234,'2019-08-12 11:51:46'),(188827921195124,'2019-08-12 11:51:46'),(188828063594889,'2019-08-12 11:51:47'),(188828333394837,'2019-08-12 11:51:47'),(188829166438333,'2019-08-12 11:51:48'); 84 | 85 | /*Table structure for table `local_try_log` */ 86 | 87 | DROP TABLE IF EXISTS `local_try_log`; 88 | 89 | CREATE TABLE `local_try_log` ( 90 | `tx_no` varchar(64) NOT NULL COMMENT '事务id', 91 | `create_time` datetime DEFAULT NULL, 92 | PRIMARY KEY (`tx_no`) 93 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 94 | 95 | /*Data for the table `local_try_log` */ 96 | 97 | /*Table structure for table `undo_log` */ 98 | 99 | DROP TABLE IF EXISTS `undo_log`; 100 | 101 | CREATE TABLE `undo_log` ( 102 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 103 | `branch_id` bigint(20) NOT NULL, 104 | `xid` varchar(100) NOT NULL, 105 | `context` varchar(128) NOT NULL, 106 | `rollback_info` longblob NOT NULL, 107 | `log_status` int(11) NOT NULL, 108 | `log_created` datetime NOT NULL, 109 | `log_modified` datetime NOT NULL, 110 | `ext` varchar(100) DEFAULT NULL, 111 | PRIMARY KEY (`id`), 112 | UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) 113 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 114 | 115 | /*Data for the table `undo_log` */ 116 | 117 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 118 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 119 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 120 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 121 | --------------------------------------------------------------------------------