TCC和两阶段分布式事务处理的区别

经常在网络上看见有人介绍TCC时,都提一句,”TCC是两阶段提交的一种”。其理由是TCC将业务逻辑分成try、confirm/cancel在两个不同的阶段中执行。其实这个说法,是不正确的。可能是因为既不太了解两阶段提交机制、也不太了解TCC机制的缘故,于是将两阶段提交机制的prepare、commit两个事务提交阶段和TCC机制的try、confirm/cancel两个业务执行阶段互相混淆,才有了这种说法。
两阶段提交(Two Phase Commit,下文简称2PC),简单的说,是将事务的提交操作分成了prepare、commit两个阶段。其事务处理方式为:
1、 在全局事务决定提交时,a)逐个向RM发送prepare请求;b)若所有RM都返回OK,则逐个发送commit请求最终提交事务;否则,逐个发送rollback请求来回滚事务;
2、 在全局事务决定回滚时,直接逐个发送rollback请求即可,不必分阶段。
* 需要注意的是:2PC机制需要RM提供底层支持(一般是兼容XA),而TCC机制则不需要。
TCC(Try-Confirm-Cancel),则是将业务逻辑分成try、confirm/cancel两个阶段执行,具体介绍见TCC事务机制简介。其事务处理方式为:
1、 在全局事务决定提交时,调用与try业务逻辑相对应的confirm业务逻辑;
2、 在全局事务决定回滚时,调用与try业务逻辑相对应的cancel业务逻辑。
可见,TCC在事务处理方式上,是很简单的:要么调用confirm业务逻辑,要么调用cancel逻辑。这里为什么没有提到try业务逻辑呢?因为try逻辑与全局事务处理无关。
当讨论2PC时,我们只专注于事务处理阶段,因而只讨论prepare和commit,所以,可能很多人都忘了,使用2PC事务管理机制时也是有业务逻辑阶段的。正是因为业务逻辑的执行,发起了全局事务,这才有其后的事务处理阶段。实际上,使用2PC机制时————以提交为例————一个完整的事务生命周期是:begin -> 业务逻辑 -> prepare -> commit。
再看TCC,也不外乎如此。我们要发起全局事务,同样也必须通过执行一段业务逻辑来实现。该业务逻辑一来通过执行触发TCC全局事务的创建;二来也需要执行部分数据写操作;此外,还要通过执行来向TCC全局事务注册自己,以便后续TCC全局事务commit/rollback时回调其相应的confirm/cancel业务逻辑。所以,使用TCC机制时————以提交为例————一个完整的事务生命周期是:begin -> 业务逻辑(try业务) -> commit(comfirm业务)。
综上,我们可以从执行的阶段上将二者一一对应起来:
1、 2PC机制的业务阶段 等价于 TCC机制的try业务阶段;
2、 2PC机制的提交阶段(prepare & commit) 等价于 TCC机制的提交阶段(confirm);
3、 2PC机制的回滚阶段(rollback) 等价于 TCC机制的回滚阶段(cancel)。

CAP理论

分布式领域CAP理论
Consistency(一致性), 数据一致更新,所有数据变动都是同步的
Availability(可用性), 好的响应性能
Partition tolerance(分区容忍性) 可靠性
定理:任何分布式系统只可同时满足二点,没法三者兼顾。
忠告:架构师不要将精力浪费在如何设计能满足三者的完美分布式系统,而是应该进行取舍。
分布式系统的CAP理论:理论首先把分布式系统中的三个特性进行了如下归纳:
一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
分区容错性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
CAP理论就是说在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡,没有NoSQL系统能同时保证这三点。

acid

ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的数据库,必须要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。
原子性
整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性
一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
隔离性
隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。
持久性
在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

数据空洞

数据空洞的产生原理都是相通的,类似的。
文件空洞的概念:
在UNIX文件操作中,文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被设为 0。
如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重复的 0 表示。空洞是否占用硬盘空间是由文件系统(file system)决定的。
文件空洞的特点:
用ls查看的文件大小是将空洞算在内的。
cp命令拷贝的文件,空洞部分不拷贝,所以生成的同样文件占用磁盘空间小。
用read读取空洞部分读出的数据是0,所以如果用read和write拷贝一个有空洞的文件,那么最终得到的文件没有了空洞,空洞部分都被0给填充了,文件占用的磁盘空间就大了。不过文件大小不变。
空洞文件作用很大,例如迅雷下载文件,在未下载完成时就已经占据了全部文件大小的空间,这时候就是空洞文件。下载时如果没有空洞文件,多线程下载时文件就都只能从一个地方写入,这就不是多线程了。如果有了空洞文件,可以从不同的地址写入,就完成了多线程的优势任务。
hbase空洞:
在我们的大规模的应用测试中,发现了个别异常的Region。
首先,介绍发现这个问题的来由。在线上读写请求出现个别操作失败,并且失败的请求指向同一个Region A,因此,检查该Region A的位置,指向了host1,然而进入host1的onlineRegion列表中,却没有发现该Region,因此,此时出现Region不匹配的问题。更名为Region空洞。
在互联网应用中,有一个共性是,找问题比解决问题要难。只要定位到了问题,根据上面对于AM、RS、HMaster之间Region迁移的理解,很容易发现是Region迁移过程中出现了一次事故,造成了空洞现象。
我的解决方法就是增加一个定时触发的监控程序,去检查.META.表中记录的Region位置(RS)是否与RS对应上,如果RS上onlineRegion,不存在该Region,则就报警,并尝试进行unassign操作。
将该程序放入crontab中,定时检查监控,并有Region重新部署功能。
http://blog.sina.com.cn/s/blog_4a1f59bf0101b1hv.html
MongoDB空洞:
很多时候,我们项目上线时间比较久了,我们积累了一些无用的数据,而由于MongoDB顺序写的原因,在我们删除部分无用数据后,它的storageSize和fileSize并不会变小,这就造成了大量的数据空洞。
这些数据空洞除了占用磁盘之外,也会加载到内存中,这会降低内存效率。
所以这个时候,我们一般要对这些数据空洞进行处理,一般有下面几种处理方式。 一种是使用MongoDB自带的compact命令:
db.collectionName.runCommand(“compact”)
这种方式是collection级别的压缩,只能去除collection内的碎片,但是MongoDB的数据分配是DB级别的,效果并不一定多好,其次呢,这个压缩是线上压缩,肯定会影响服务的,磁盘IO会比较高,这么干容易出事。
还有一种方式,也就是我们下面要详细说明的方式,过程大概类似于下面:
先预热从库
提升从库为主库,原主库降为从库
移除原主库的DB数据,直接remove掉
重新同步
完成后,预热,然后将此库提升为主库,原从库依然降为从库
这样做的好处是:
DB级别,不会有碎片,毕竟是新写的,收缩效率高
基本不会影响线上服务(当然,你不能只有一个从,你也不能挑服务高负荷的时候来干这个事情)
Mysql空洞:
现发现对一个几亿条记录的表进行删除记录及进行optimize操作时,会极其的耗时间和空间。
删除记录时,MyISAM表会留下空洞碎片,碎片多了会持续降低MySQL性能。如果使用optimize操作的话,MySQL会先生成一个TMD文件;完成操作后才会把这个文件删除。这个过程相当漫长……
所以再设计表和存储记录时,就应当想好这个表的记录会不会有大量记录;如果是的话应该要先设计好应对方案,水平切分或垂直切分。

bootstrap table 导出数据格式,前端日期排序

先看插件说明,再看options的设置即可.
排序主要看:

sorter:numberSort

导出文件格式化主要看:

showExport:true,
            exportOptions:{
            	fileName:"例子后端常规监控",
            	worksheetName:"例子后端常规监控",
            	onCellData:function(cell, row, col, data){
            		if(row == 0){
            			return data;
            		}else{
            			return data.replace(/\([^\)]*\)/g,"");
            		}
                }
            },

https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/export
https://github.com/hhurz/tableExport.jquery.plugin#options

//数据排序算法
function numberSort(a,b){
    	a = a.replace(/\([^\)]*\)/g,"");//正则 去掉小括号及里边的内容
    	b = b.replace(/\([^\)]*\)/g,"");
    	var numa = parseFloat(a);
    	var numb = parseFloat(b);
    	return a - b;
}
//日期排序算法
sorter:function(a, b){
              var d1 = new Date(a.replace(/\-/g, "\/"));
              var d2 = new Date(b.replace(/\-/g, "\/"));
              if(a != "" && b != ""){
              	    return d1 - d2;
               }
}
//bootstrap table初始化函数
        $('#table').bootstrapTable({
            showToggle:false,
            showPaginationSwitch:true,  //
            showColumns:true,        //可选列按钮
            iconsPrefix:"glyphicon",   //图标样式
            iconSize:"sm",           //图标大小
            striped:true,
            classes:"table table-striped table-bordered table-hover",
            pagination:true,        //底部分页
            sidePagination:"client",
            showExport:true,
            exportOptions:{
            	fileName:"例子后端常规监控",
            	worksheetName:"例子后端常规监控",
            	onCellData:function(cell, row, col, data){
            		if(row == 0){
            			return data;
            		}else{
            			return data.replace(/\([^\)]*\)/g,"");
            		}
                }
            },
            search:true,
            undefinedText:"无",
            pageSize: 20, //每页的记录行数(*)
            pageList: [20, 50, 100, 150], //可供选择的每页的行数(*)
            //sortable: true, //是否启用排序
            //sortName:"stat_dt",
            //sortOrder:"desc",
            columns:[
                 {
                    field:"stat_dt",
                    title:"统计日期",
                    sortable:true,
                    sorter:function(a, b){
                    	var d1 = new Date(a.replace(/\-/g, "\/"));
                    	var d2 = new Date(b.replace(/\-/g, "\/"));
                    	if(a != "" && b != ""){
                    	    return d1 - d2;
                    	}
                    }
                 },
                {
                 field:"platform",
                 title:"平台",
                 sortable:true
                },
                {
                    field:"app_name",
                    sortable:true,
                    title:"APP名称",
                    formatter:function(value,row,index){
                        if(value == "other"){
                            return "无";
                        }
                        return value;
                    }
                    },
                 {
                  field:"order_num",
                  sortable:true,
                  title:"例子订单量",
                  sorter:numberSort
                  },
                  ......

superset能否连接ElasticSearch

找到一个组件,还没来得及看呢
https://pypi.python.org/pypi/sqlalchemy-elasticquery/

修改bootstrap table 单元格背景色

         cellStyle:function(value,row,index){
                       var allTableData = $('#table').bootstrapTable('getData');
               		 var tmp = allTableData[index];
               		 //console.log(tmp[3]);
                        console.log(tmp[6]+","+tmp[3]);
                       // console.log(value+","+row+","+index);
                        if (value==1){
                   		 return {css:{"background-color":"red"}}
                        }else{
                            return {css:{"background-color":"green"}}
                        }
               	}

maven项目出现数组越界异常

解决方案:3.5的会出现这个问题,更换maven版本位3.3.9就ok了

[ERROR] 44410
java.lang.ArrayIndexOutOfBoundsException: 44410
	at org.codehaus.plexus.util.xml.pull.MXParser.parsePI(MXParser.java:2502)
	at org.codehaus.plexus.util.xml.pull.MXParser.parseEpilog(MXParser.java:1604)
	at org.codehaus.plexus.util.xml.pull.MXParser.nextImpl(MXParser.java:1434)
	at org.codehaus.plexus.util.xml.pull.MXParser.next(MXParser.java:1131)
	at org.apache.maven.model.io.xpp3.MavenXpp3Reader.read(MavenXpp3Reader.java:3856)
	at org.apache.maven.model.io.xpp3.MavenXpp3Reader.read(MavenXpp3Reader.java:595)
	at org.apache.maven.model.io.DefaultModelReader.read(DefaultModelReader.java:109)
	at org.apache.maven.model.io.DefaultModelReader.read(DefaultModelReader.java:82)
	at org.apache.maven.model.building.DefaultModelProcessor.read(DefaultModelProcessor.java:81)
	at org.apache.maven.model.building.DefaultModelBuilder.readModel(DefaultModelBuilder.java:535)
	at org.apache.maven.model.building.DefaultModelBuilder.readParentExternally(DefaultModelBuilder.java:1097)
	at org.apache.maven.model.building.DefaultModelBuilder.readParent(DefaultModelBuilder.java:829)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:331)
	at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom(DefaultArtifactDescriptorReader.java:321)
	at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor(DefaultArtifactDescriptorReader.java:199)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.resolveCachedArtifactDescriptor(DefaultDependencyCollector.java:544)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.getArtifactDescriptorResult(DefaultDependencyCollector.java:528)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:418)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:372)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.process(DefaultDependencyCollector.java:360)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.doRecurse(DefaultDependencyCollector.java:513)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:467)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:372)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.process(DefaultDependencyCollector.java:360)
	at org.eclipse.aether.internal.impl.DefaultDependencyCollector.collectDependencies(DefaultDependencyCollector.java:263)
	at org.eclipse.aether.internal.impl.DefaultRepositorySystem.collectDependencies(DefaultRepositorySystem.java:325)
	at org.apache.maven.project.DefaultProjectDependenciesResolver.resolve(DefaultProjectDependenciesResolver.java:169)
	at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.getDependencies(LifecycleDependencyResolver.java:195)
	at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.resolveProjectDependencies(LifecycleDependencyResolver.java:127)
	at org.apache.maven.lifecycle.internal.MojoExecutor.ensureDependenciesAreResolved(MojoExecutor.java:246)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:200)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
	at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
	at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:309)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:194)
	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:107)
	at org.apache.maven.cli.MavenCli.execute(MavenCli.java:993)
	at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:345)
	at org.apache.maven.cli.MavenCli.main(MavenCli.java:191)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
	at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
	at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
[ERROR]

感觉是maven自己的plexus-utils包有问题
我也有如上问题,我是再pom中添加了activiti的jar就会报数组越界,去掉activiti的jar就正常。 但是我必须用activiti,也不知道究竟是什么原因。

[WARNING] The POM for org.slf4j:slf4j-api:jar:1.7.6 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model for org.slf4j:slf4j-api:[unknown-version]
[FATAL] Non-parseable POM D:\maven\repository\org\slf4j\slf4j-parent\1.7.6\slf4j-parent-1.7.6.pom: end tag not allowed in epilog but got / (position: END_TAG seen ...\r\n\r\n\r\n </... @398:16) @ D:\maven\repository\org\slf4j\slf4j-parent\1.7.6\slf4j-parent-1.7.6.pom, line 398, column 16
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.709 s
[INFO] Finished at: 2017-07-04T15:23:48+08:00
[INFO] Final Memory: 12M/219M
[INFO] ------------------------------------------------------------------------
[ERROR] 17166
java.lang.ArrayIndexOutOfBoundsException: 17166
at org.codehaus.plexus.util.xml.pull.MXParser.parsePI(MXParser.java:2502)
at org.codehaus.plexus.util.xml.pull.MXParser.parseEpilog(MXParser.java:1604)
at org.codehaus.plexus.util.xml.pull.MXParser.nextImpl(MXParser.java:1434)
at org.codehaus.plexus.util.xml.pull.MXParser.next(MXParser.java:1131)
at org.apache.maven.model.io.xpp3.MavenXpp3Reader.read(MavenXpp3Reader.java:3856)
at org.apache.maven.model.io.xpp3.MavenXpp3Reader.read(MavenXpp3Reader.java:595)
at org.apache.maven.model.io.DefaultModelReader.read(DefaultModelReader.java:109)
at org.apache.maven.model.io.DefaultModelReader.read(DefaultModelReader.java:82)

linux导出sql导入windows,out of memory

导入sql文件,这个可以用于大文件3.9G的文件,用navcat客户端导入有问题 out of memory。
例如:我的用户名是root 密码是123 sql脚本存在C盘 名字为test.sql 数据库为test
有两种方法可以执行脚本
1:打开CMD输入以下命令(不需要转换目录)

>mysql -u root -p123

进入MYSQL后

mysql>use test;
mysql> source c:/test.sql

ok执行完了,你可以用show tables;查看有哪写表(记得语句后有个分号)
还可以用desc tableName;查看你的表结构
 
2:打开CMD输入以下命令(进入mysql的bin目录)

d:\mysql\bin>mysql -u root -p123 test < c:/test.sql 

在window的服务里找到mysql服务就可以看到mysql完成安装路径 今天想把远程MySQL服务器上的一张表导入到本地数据库,于是先使用mysqldump导出这张表,这是很容易的,轻松搞定。但是导入的时候就不行了,总是提示Unknown command ‘\\’。一开始还以为这是mysql的bug,自己导出的东西自己不能导入,后来想想MySQL不应该这么弱的,就上网搜了一下,结果发现是默认字符集的问题。远程的数据库服务器操作系统是Linux,OS的默认字符集也是UTF-8,但是我本机用的是Windows 7,默认的字符集是GBK,在导入的时候加上–default-character-set=utf8就好了。最后附上完整的导入导出语句

 mysqldump -udbuser -p database table > exp.sql;
mysql -udbuser -p --default-character-set=utf8 database < exp.sql  

linux导出的sql文件导入到window系统里的mysql一定要指定编码 导入命令:

 mysql> source d:/rew.sql