分布式事务解决方案-Seata

参考官方 README

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

要理解 Seata 是做什么的,我们先要理解分布式事务

微服务系统中的分布式事务问题

我们先想象以下一个传统的单体应用,业务逻辑分为三块,它们都是单独使用在本地数据源;

正常情况下,数据的一致性往往由本地事务来确保,如下图:

EffectiveJava第10条:当重写 equals 遵守通用约定

当重写 equals 遵守通用约定

重写 equals方法看起来比较简单,但是总是非常容易犯错,而且犯错后的结果有可能非常严重.
一般来说不用重写equals方法可以避免这种错误,这样的话这个实力只能跟自己相同.默认的 equals方法实现了:

  • 类的每个实例本质上都是独一无二的。这一点对于那些代表活动实体而不是值的类来说的确如此。Object类提供的equals方法实现正是这些类的正确行为。
  • 对于一个类来说不需要提供一个逻辑相等的测试例如,java.util.regex.Pattern本可以通过覆盖equals方法来校验两个Pattern实例是否表示相同正则表达式,但设计者们并不认为客户端需要这个功能。在这种情况下,equals方法直接继承自Object类就已经足够了。
  • 父类已经重写了equals方法,而且对于其子类来说是通用的,例如,大多数Setequals方法的实现都是继承自AbstractSet,类似地,List继承自AbstractListMap继承自AbstractMap
  • 如果一个类是私有的或者是包私有的,那么我们可以确定它的equals方法将永远不会被调用。如果你很害怕风险,那么你也可以覆盖equals方法来保证它不会被意外调用:

EffectiveJava第11条:重写 equals 方法时要覆盖 hashCode 方法

在每个覆盖了equals方法的类里,我们也必须覆盖hashCode方法
不这么做的后果是

  • 这个类将会违反hashCode的通用约定
  • 会影响 Collections 中的功能,如 HashMap 或者 HashSet

通用协议包括:

EffectiveJava第9条:优先使用 try-with-resource 而不是 try-finally

优先使用 try-with-resource 而不是 try-finally

Java类库里包含了必须通过调用close方法来手动关闭的资源。比如InputStream,OutputStream还有java.sql.Connection。
我们通常使用这种方式来关闭这些资源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// try-finally - No longer the best way to close resources!
//使用 try finally 来关闭资源已经不是最好的方式了
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
}

// try-finally is ugly when used with more than one resource!
// 如果有多个资源需要关闭,代码会很丑.可读性很差
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dst);
try {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally {
out.close();
}
} finally {
in.close();
}
}

上面的代码显示了两个问题:

  • 当出现多个资源需要关闭的时候,代码会很丑
  • 如果br.readLine();报错,那么 finally 块的 close方法也会报错,那么这个时候第二个报错就会覆盖掉第一个报错,在错误栈内就没有第一种异常的记录

EffectiveJava第8条:避免使用中介器或者清理方法

本章作者的中心思想是:

  • 终结方法(Finalizer)是不可预知的,很多时候是危险的,而且一般情况下是不必要的。
  • Java 9 中终结方法已经被遗弃了,但它们仍被Java类库使用,清理方法替代了终结方法
  • 比起终结方法,清理方法相对安全点,但仍是不可以预知的,运行慢的,而且一般情况下是不必要的。

终结方法(finalizer)和清理方法(cleaner)

1
2
3
System.gc();
System.runFinalization();
System.runFinalizersOnExit();

缺点

  1. 终结方法和清理方法无法保证立刻会执行,而且不保证它们最终会运行

EffectiveJava第7条:消除过期的对象引用

中心思想

在对象过期时及时清空引用。

栈的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INTIAL_CAPACITY = 16;

public Stack(){
elements = new Object[DEFAULT_INTIAL_CAPACITY];
}

public void push(Object e){
ensureCapacity();
elements[size++] = e;
}

public Object pop(){
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}

//确保有足够的空间添加一个新的元素
private void ensureCapacity(){
if (elements.length == size)
elements = Arrays.copyOf(elements,2 * size + 1);
}
}

栈主键增长,当pop时,主键收缩,那么,从栈中弹出来的对象并不会被当成垃圾回收,即使使用栈的程序不在引用这些对象,他们也不会被回收。

1
2
3
4
5
public Object pop(){
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}

被弹出的对象的对象的引用,是永远不会再被解除的引用,即“过期引用”,

这段程序有一个“内存泄露”,随着垃圾回收器活动的增加,或者由于内存占用的不断增加,程序性能的降低会逐渐展现出来。在极端条件下,这种内存泄露会导致磁盘交换(Disk Paging) ,甚至导致程序失败(OutOfMenoryError

垃圾回收站不会处理这个对象,而且不会处理这个对象所引用的所有其他对象。

EffectiveJava第6条:避免创建不必要的对象

拒绝重复创建不可变对象

一般来说,最好能重用对象而不是每次需要的时候就创建一个功能相同的对象:

例如:
String s = new String ("hello");

该语句每次执行都会创建个新的String实例,但没有必要创建这些对象

改为:
String s = "hello";
对于所有在同一台虚拟机中运行的代码,只要他们包含相同的字符串字面常量,该对象就会被重用。

EffectiveJava第5条:使用依赖注入而不是硬链接资源

1 总体思想

1.1本条作者的中心思想是:

当一个类需要以来底层的资源时,而且这些资源的行为会影响到这个类时,不要使用 Singleton 或者静态工厂类实现,也不要让类自己去创建这些资源。
推荐的做法:
将这些资源或者创建资源的工厂传入构造器(也可以是静态工厂或者Builder)。

1.2 为什么要这么做:

  • 提高类的灵活性
  • 提高类的复用性
  • 提高类的可测试性

EffectiveJava第4条:通过私有构造器强化不可实例化的能力

有一些类不希望被实例化,如一些工具类,实例对它没有任何意义,

提供一个私有构造方法

1
2
3
4
5
public class OfficeUtils{
private OfficeUtils(){
throw new AssertionError();
}
}

由于显式的构造器是私有的,所以不可能在该类的外部访问它。AssertionError不是必须的,但是它可以避免不小心在类的内部调用构造器。

EffectiveJava第3条:用私有构造器或者枚举类型强化Singleton属性

Singleton的类

Singleton 指仅仅被实例化一次的类,通常被用来代表那些本质上唯一的系统组件。

本文介绍三种实现方式

  • final 修饰公有静态成员
  • 静态工厂方法实现Singleton
  • 使用枚举实现Singleton
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×