分布式事务(Seata)

前言

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:61944c4f-37bc-45f6-84c5-d7b7ba04884d

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:7511af7b-5600-460b-8c61-81bf48cc4608

在后端每个微服务都是分散和独立的,可能使用不同编程语言,使用不同的数据库,通过RPC调用完成前端用户发送的请求(任务);

假设1个用户在1个分布式微服务架构的电商网站购物,购买了1件商品点击了下单,后台需要一组微服务协作完成下单操作;

即:订单服务创建订单—>库存服务减少库存—->用户服务减少余额;

在这3个环节执行过程中,如果其中1个微服务不可用,都无法满足当前用户下单的需求;

分布式事务(Seata)

那如何保证用户的1次操作具备数据库事务的ACID特性呢?

这就需要分布式事务;

2000年加州理工大学伯克利分校的EricBrewer教授提出在分布式架构中应当具备3个理想的指标

  • Consistency(一致性)
  • Availability(可用性)
  • Partition tolerance (分区容错性)

称为CAP理论;

1.一致性

指分布式架构中数据的强一致性, 即使数据分布在不同节点上,1个节点写操作之后,在另1个节点的读操作,也可以读到最新状态的数据(MySQL主从之间数据同步)。

2.可用性

指服务处在100%可用的状态,用户访问分布式集群中任意1个服务 ,即使该服务故障,用户依然能得到响应,而不是超时或拒绝。

3.分区容错

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:e5ae83e7-f485-43f0-b1af-1d5346159595

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:b80fd131-1511-4a6d-a241-3eb86948ed22

二、BASE理论

在分布式微服务架构中,各个微服务之间通过网络进行RPC调用,CAP理论中的可用性和一致性就是相互矛盾的,无法同时成立;

1.CAP理论的问题

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:f7a3098e-4d4d-416a-a265-75cfb2f0d933

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:34256df5-20f1-407a-a70d-8223d3dee15c

分布式事务(Seata)

假设G1和G2两个节点要想实现数据一致性,就需要通过网络传输同步数据,但网络传输数据是需要时间的;

忠和孝无法两全,如果G1更新了数据,在G1和G2节点通过网络传输同步数据的这1段时间里,G2节点是对外提供查询服务呢?还是不提供服务呢?

  • G2提供服务就不满足一致性指标;
  • G2阻塞用户请求,不提供服务就无法满足100%可用性指标;

以上是CAP理论存在的问题;

2.BASE理论

BASE理论是针对CAP理论存问题的1种解决方案,包含3个思想:

2.1.Basically Available (基本可用)

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:57048935-dcb3-4fb2-a0c9-02777403d2f7

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:f64537c8-3460-4569-8e49-3b8cfed76f6e

2.2.Soft State(软状态)

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:c406c2fc-c8a7-45ee-89ed-ce4be726dcab

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:44b07c44-6eab-4705-af21-726f27ccec4a

2.3.Eventually Consistent(最终一致性)

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:c60f4169-47fb-461f-a54f-35c88d22827c

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:dd678057-2f41-4469-9004-ad702bfa2611

三、分布式事务解决思路

分布式事务在设计之初借鉴CAP、BASE理论,有两种解决思路:

  • AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。
  • CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。

但不管是哪一种模式,想要在分布式架构中控制多个事物都需要1个事务协调者(TC):

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:08f92ee3-df0f-4179-a0f9-89a3ed4b5616

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:3af1d759-87d0-4d6b-8912-84bf562bfe04

分布式事务(Seata)

四、初识Seata

Seata是 2019 年1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:8b5040c3-71be-49d5-b259-4d82254fa58d

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:28b95e98-9c9f-4ecd-ac81-011fea1845a1

官网地址:http://seata.io/,其中的文档、播客中提供了大量的使用说明、源码分析。

1.Seata的架构

Seata事务管理中有3个重要的角色:

  • TC (Transaction Coordinator) -事务协调者:搭建好的Seata服务器,所有的RM和TM都要想TC上报,当前分支事务执行的状态,以便于TC作出全局事务的回滚/提交操作(CEO);
  • TM (Transaction Manager) -事务管理器:代表整个业务逻辑,决定全局事务的范围和边界,从哪个环节开始全局事务?在哪个环节提交或回滚全局事务?从哪个环节结束全局事务?(经理)
  • RM (Resource Manager) -资源管理器:具体执行分支事务的微服务。(员工)

分布式事务(Seata)

Seata基于上述架构提供了四种不同的分布式事务解决方案:

  • XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
  • TCC模式:最终一致的分阶段事务模式,有业务侵入
  • AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
  • SAGA模式:长事务模式,有业务侵入

无论采用哪1种分布式事务解决方案,都需要先搭建Seata服务器,也就是事务的协调者(TC)。

2.安装Seata

2.1.Seata配置文件

使Seata服务注册到Nacos中,并指定读取Nacos中的配置文件;

分布式事务(Seata)分布式事务(Seata)
registry {
  # tc服务的注册中心类,这里选择nacos,也可以是eureka、zookeeper等
  type = "nacos"

  nacos {
    # seata tc 服务注册到 nacos的服务名称,可以自定义
    application = "seata-tc-server"
    serverAddr = "127.0.0.1:8848"
    group = "DEFAULT_GROUP"
    namespace = ""
    cluster = "SH"
    username = "nacos"
    password = "nacos"
  }
}

config {
  # 读取tc服务端的配置文件的方式,这里是从nacos配置中心读取,这样如果tc是集群,可以共享配置
  type = "nacos"
  # 配置nacos地址等信息
  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    group = "DEFAULT_GROUP"
    username = "nacos"
    password = "nacos"
    dataId = "seataServer.properties"
  }
}

registry.conf

2.2. nacos添加配置

特别注意,为了让tc服务的集群可以共享配置,我们选择了nacos作为统一配置中心。

因此服务端配置文件 seataServer.properties文件需要在nacos中配好。

配置内容如下

分布式事务(Seata)分布式事务(Seata)
registry {
  # tc服务的注册中心类,这里选择nacos,也可以是eureka、zookeeper等
  type = "nacos"

  nacos {
    # seata tc 服务注册到 nacos的服务名称,可以自定义
    application = "seata-tc-server"
    serverAddr = "127.0.0.1:8848"
    group = "DEFAULT_GROUP"
    namespace = ""
    cluster = "SH"
    username = "nacos"
    password = "nacos"
  }
}

config {
  # 读取tc服务端的配置文件的方式,这里是从nacos配置中心读取,这样如果tc是集群,可以共享配置
  type = "nacos"
  # 配置nacos地址等信息
  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    group = "DEFAULT_GROUP"
    username = "nacos"
    password = "nacos"
    dataId = "seataServer.properties"
  }
}

seataServer.properties

2.3.创建数据库表

TC服务在管理分布式事务时,需要记录事务相关数据到数据库中,你需要提前创建好这些表。

新建一个名为seata的数据库,seata数据库中创建branch_table和global_table两张表;

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:1fc2d458-db5a-40ea-9403-1ce8f9cb8cd6

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:71bb2474-7cd0-48f9-8adf-bfa8fe08f63e

分布式事务(Seata)分布式事务(Seata)
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- 分支事务表
-- ----------------------------
DROP TABLE IF EXISTS branch_table;
CREATE TABLE branch_table  (
  branch_id bigint(20) NOT NULL,
  xid varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  transaction_id bigint(20) NULL DEFAULT NULL,
  resource_group_id varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  resource_id varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  branch_type varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  status tinyint(4) NULL DEFAULT NULL,
  client_id varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  application_data varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  gmt_create datetime(6) NULL DEFAULT NULL,
  gmt_modified datetime(6) NULL DEFAULT NULL,
  PRIMARY KEY (branch_id) USING BTREE,
  INDEX idx_xid(xid) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- 全局事务表
-- ----------------------------
DROP TABLE IF EXISTS global_table;
CREATE TABLE global_table  (
  xid varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  transaction_id bigint(20) NULL DEFAULT NULL,
  status tinyint(4) NOT NULL,
  application_id varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  transaction_service_group varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  transaction_name varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  timeout int(11) NULL DEFAULT NULL,
  begin_time bigint(20) NULL DEFAULT NULL,
  application_data varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  gmt_create datetime NULL DEFAULT NULL,
  gmt_modified datetime NULL DEFAULT NULL,
  PRIMARY KEY (xid) USING BTREE,
  INDEX idx_gmt_modified_status(gmt_modified, status) USING BTREE,
  INDEX idx_transaction_id(transaction_id) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

table.sql

2.4. 启动TC服务

进入bin目录,运行其中的seata-server.bat即可

2.5.测试

打开浏览器,访问nacos地址:http://localhost:8848,然后进入服务列表页面,可以看到seata-tc-server的信息:

分布式事务(Seata)

五、微服务集成Seata

此时Seata已经注册到Nacos并可以从Nacos中读取配置信息;

我们就可以在微服务中集成使用Seata服务了;

1.引入依赖

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-seataartifactId>
    <exclusions>

        <exclusion>
            <artifactId>seata-spring-boot-starterartifactId>
            <groupId>io.seatagroupId>
        exclusion>
    exclusions>
dependency>
<dependency>
    <groupId>io.seatagroupId>
    <artifactId>seata-spring-boot-starterartifactId>

    <version>${seata.version}version>
dependency>

2.配置TC地址

微服务通过application.yml中配置的Nacos获取TC地址;

seata:
  registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
    type: nacos # 注册中心类型 nacos
    nacos:
      server-addr: 127.0.0.1:8848 # nacos地址
      namespace: "" # namespace,默认为空
      group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
      application: seata-tc-server # seata服务名称
      username: nacos
      password: nacos
  tx-service-group: seata-demo # 事务组名称
  service:
    vgroup-mapping: # 事务组与cluster的映射关系
      seata-demo: SH

六、Seata的事务模式

Seata提供4种事务模式,帮我们实现分布式事务;

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:cfd0a970-361d-42e1-9602-dbbb59e6fc80

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:a3dba78b-7c9f-4b5c-bcc6-a0169ba1b094

1.两阶段提交

XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。

正常情况:

异常情况:

一阶段(事务预提交):

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:9902c793-278b-4c22-91de-4eec139dee4f

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:60dc7c6b-a880-495a-9222-8f94f1feadb0

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:4cbcd95f-7c14-4d85-8cab-22daf4edba28

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:69946749-cdf3-48e3-acc2-0ac6cbcfc635

二阶段:

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:0c1e4ed9-0700-441d-8f78-a4e74ab454fc

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:0a9436bf-a0e9-4b56-9f3e-334555535e27

– 如果一阶段的分支事务全部预提交成功,则通知所有事务参与者去数据库正真提交事务
– 如果一阶1个事务参与者的预提交结果失败,则通知所有事务参与者回滚事务

2.XA模式

几乎所有主流的数据库都XA 规范提供了支持;

Seata的XA模式是利用数据库底层事务二阶段提交的特性,封装了二阶段提交操作方法;

2.2.Seata的XA模型

Seata对原始的XA模式做了简单的封装和改造,以适应自己的事务模型,基本架构如图:

RM一阶段的工作:

① 注册分支事务到TC

② 执行分支业务sql但不提交

③ 报告执行状态到TC

TC二阶段的工作:

  • TC检测各分支事务执行状态 a.如果都成功,通知所有RM提交事务 b.如果有失败,通知所有RM回滚事务

RM二阶段的工作:

  • 接收TC指令,提交或回滚事务

2.3.优缺点

XA模式的优点是什么?

  • 事务的强一致性,满足ACID原则。
    [TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:d02e5fc7-adb2-46ca-849c-cce7b2105442
    [En]

    [TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:7fe846f0-117f-49f3-92d7-473ccf1e7b7e

XA模式的缺点是什么?

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:c42c19df-0f67-451a-a810-03a086eae5cc

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:4310657f-6689-4832-abea-f1b80f2ab94a

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:c3f2b988-228e-4323-88d8-87393a471005

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:cc2108b9-917b-4153-a5fc-f69eb005e2fc

2.4.实现XA模式

Seata的starter已经完成了XA模式的自动装配,实现非常简单,步骤如下:

2.4.1.修改application.yml文件

每个参与事务的微服务都需要开启XA模式:

seata:
  data-source-proxy-mode: XA

2.4.2.添加注解

给发起全局事务的入口方法添加@GlobalTransactional注解

@Override
    @Transactional
    //给发起全局事务的入口方法添加@GlobalTransactional注解:
    @GlobalTransactional
    public Long create(Order order) {
        // 创建订单
        orderMapper.insert(order);
        try {
            // 扣用户余额
            accountClient.deduct(order.getUserId(), order.getMoney());
            // 扣库存
            storageClient.deduct(order.getCommodityCode(), order.getCount());

        } catch (FeignException e) {
            log.error("下单失败,原因:{}", e.contentUTF8(), e);
            throw new RuntimeException(e.contentUTF8(), e);
        }
        return order.getId();
    }

2.4.3. 重启服务并测试

重启order-service,再次测试,发现无论怎样,3个微服务都能成功回滚。

3.AT模式

AT模式同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷。

AT模式就是模仿了数据库底层XA二阶段提交机制,把改功能抽离出来在Seata中再实现,这样可以使Seata支持更多数据库的分布式事务操作;

阶段一RM的工作:

  • 注册分支事务
  • 记录undo-log(数据快照以保证事务提交失败之后可以回滚)
  • 执行业务sql并提交
  • 报告事务状态

阶段二提交时RM的工作:

  • 删除undo-log即可

阶段二回滚时RM的工作:

  • 根据undo-log恢复数据到更新前

3.1.AT与XA的区别

简述AT模式与XA模式最大的区别是什么?

  • XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
  • XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
  • XA模式强一致;AT模式最终一致

3.2.脏写问题

在多线程并发访问AT模式的分布式事务时,有可能出现脏写问题,如图:

分布式事务(Seata)

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:74378926-707a-4707-a69b-67acb09388cc

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:9f721091-f337-46a2-b4f5-3cd2a2a5212f

在释放DB锁之前,先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。

分布式事务(Seata)

3.3. 优缺点

AT模式的优点:

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:e6fecfa5-3f1f-44bf-96ca-a8e632f859c2

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:9fffc7c5-be30-45dd-9d40-1e8530afb237

* 利用全局锁实现读写隔离
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:56a9e4f9-54c1-4217-af2a-f8d276453043

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:adb0aed3-1161-4c56-b8c3-4b561cd8b4f7

AT模式的缺点:

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:753b7897-4107-4d74-9ac7-c69c400938a3

[En]

[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:60a10eae-ec39-42c3-a504-b037190a24a0

* 框架的快照功能会影响性能,但比XA模式要好很多

3.4. 实现AT模式

3.4.1.导入数据库表,记录全局锁

分布式事务(Seata)分布式事务(Seata)
CREATE TABLE lock_table  (
  row_key varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  xid varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  transaction_id bigint(20) NULL DEFAULT NULL,
  branch_id bigint(20) NOT NULL,
  resource_id varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  table_name varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  pk varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  gmt_create datetime NULL DEFAULT NULL,
  gmt_modified datetime NULL DEFAULT NULL,
  PRIMARY KEY (row_key) USING BTREE,
  INDEX idx_branch_id(branch_id) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

lock_table.sql

Original: https://www.cnblogs.com/sss4/p/16458980.html
Author: Martin8866
Title: 分布式事务(Seata)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/562573/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球