阅读seata源码收获

阅读seata源码收获

Posted by irving.gx on February 13, 2021

前言

seata是一个阿里研发的开源的分布式事务解决方案,用于在微服务架构下提供高可用以及简单易用的分布式事务服务。

在高并发情况下保证获取到list的最后一个元素

在高并发访问的情况下需要获取到list当中的最后一个元素,看到这个代码中有一个地方是如下这种方式获取的。这种方式是在一个while循环当中去获取最后一个元素,假如此时有多个线程对这个list进行操作(比如删除元素操作)的话,那么可能会抛出IndexOutOfBoundsException,捕捉到这个exception之后再继续while循环,直到拿到最后一个元素为止

public static <T> T getLast(List<T> list) {
    if (isEmpty(list)) {
        return null;
    }

    int size;
    while (true) {
        size = list.size();
        if (size == 0) {
            return null;
        }

        try {
            return list.get(size - 1);
        } catch (IndexOutOfBoundsException ex) {
            // catch the exception and continue to retry
        }
    }
}

netty NIO 边缘触发(ET)与水平触发(LT)

LT(level trigger)水平触发与ET(edge trigger),之前在学通信的时候是电平的触发方式,netty这里感觉借用了通信这里的概念。selector获取文件描述符(fd),边缘触发是fd状态发生改变的时候会触发,但是水平触发是只要文件没有被读取完,那么下一次selector的时候该fd仍然会被筛选出来

etcd

etcd是一个类似zookeeper的分布式协调系统,不过数据存储不像zookeeper那样采用的树状文件结构,而是采用的key-value型的数据结构。这个框架用go语言编写,被用在了kubernetes,采用的是raft的这个分布式协议。另外一个比较有名的分布式协议是paxos。

Blob vs Text

前者主要用于存储大规模的二进制数据,而后者主要是存储文本等非二进制数据

关于seata的回滚

seata当中会涉及到回滚操作,看了代码,大致思想是是在操作之前记录表中的一个快照,操作之后记录表中的快照,这样回滚的时候只用把表中的数据恢复到操作之前的快照就可以了。具体分为update,delete,insert的回滚。delete的回滚就是重新向表中插入删除的数据,insert的回滚就是delete插入的数据,update的回滚就是update

Kryo

Kryo 是一个快速序列化/反序列化工具,其使用了字节码生成机制(底层依赖了 ASM 库),因此具有比较好的运行速度。Kryo相对于java序列化来说,速度能够快10倍。然而Kryo并不是支持所有类型的序列化。

@BeforeEach注解

Test当中有一个@BeforeEach注解,这个注解的含义是放在各个test之前进行设置。在测试当中有时候会看到如下的断言

Assertions.assertIterableEquals(Iterable<?> expected, Iterable<?> actual)

这个含义是断言预期和实际的一样,也就说返回的元素顺序以及元素的值都一样

Class.forName()与ClassLoader.loadClass()区别

两者的定义如下

public static Class<?> forName(String name, boolean initialize,ClassLoader loader)

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException

通过传入的参数可以知道,Class.forName 执行之后已经对 被加载类的静态变量分配完毕了存储空间,而classLoader.loadClass 并没有一定执行完 链接这一步.

FastThreadLocal

FastThreadLocal的吞吐量是threadlocal的三倍,但是并不是使用普通的线程,使用FastThreadLocalThread线程操作FastThreadLocal才会快,如果是普通线程还更慢!在使用FastThreadlocal的时候,不用像Threadlocal在finally当中主动remove,这是因为在构造FastThreadlocal的时候,就已经实现了removeAll()的方法

Threadlocal

ThreadlocalMap是Threadlocal的一个内部类,在具体实现的时候,ThreadlocalMap当中entry的key为Threadlocal对象,value为存入的对象,entry的key指向的Threadlocal引用为弱引用,会被回收,但是Threadlocalmap当中的entry指向的引用为强引用,因此这个时候会出现存进去的对象没有被回收的情况。在使用的时候最佳的实践是在用完Threadlocal的时候在finally当中remove一下主动回收


如果对你有帮助,请作者喝一杯牛奶吧