分散式事務(Seata)

来源:https://www.cnblogs.com/sss4/archive/2022/07/08/16458980.html
-Advertisement-
Play Games

前言 在分散式的微服務架構中,鑒於服務單一職責性,各個微服務都分佈在不同的伺服器節點,且每1個微服務是獨立的; 在後端每個微服務都是分散和獨立的,可能使用不同編程語言,使用不同的資料庫,通過RPC調用完成前端用戶發送的請求(任務); 假設1個用戶在1個分散式微服務架構的電商網站購物,購買了1件商品點 ...


前言

在分散式的微服務架構中,鑒於服務單一職責性,各個微服務都分佈在不同的伺服器節點,且每1個微服務是獨立的;

在後端每個微服務都是分散和獨立的,可能使用不同編程語言,使用不同的資料庫,通過RPC調用完成前端用戶發送的請求(任務);

假設1個用戶在1個分散式微服務架構的電商網站購物,購買了1件商品點擊了下單,後臺需要一組微服務協作完成下單操作;

即:訂單服務創建訂單--->庫存服務減少庫存---->用戶服務減少餘額;

在這3個環節執行過程中,如果其中1個微服務不可用,都無法滿足當前用戶下單的需求; 

那如何保證用戶的1次操作具備資料庫事務的ACID特性呢?

這就需要分散式事務;

 

 一、CAP理論

2000年加州理工大學伯克利分校的EricBrewer教授提出在分散式架構中應當具備3個理想的指標

  • Consistency(一致性)
  • Availability(可用性)
  • Partition tolerance (分區容錯性)

稱為CAP理論;

1.一致性

指分散式架構中數據的強一致性, 即使數據分佈在不同節點上,1個節點寫操作之後,在另1個節點的讀操作,也可以讀到最新狀態的數據(MySQL主從之間數據同步)。

2.可用性

指服務處在100%可用的狀態,用戶訪問分散式集群中任意1個服務 ,即使該服務故障,用戶依然能得到響應,而不是超時或拒絕

3.分區容錯

指分散式架構中物理節點, 即使遇到網路故障或其它原因導致分散式系統中的部分節點與其它節點失去連接無法通信,故障節點可以形成獨立分區,不影響全局。

 

二、BASE理論

在分散式微服務架構中,各個微服務之間通過網路進行RPC調用,CAP理論中的可用性和一致性就是相互矛盾的,無法同時成立;

1.CAP理論的問題

在分散式微架構中,如果想要實現一致性就需要在2個節點之間通過網路同步數據;

假設G1和G2兩個節點要想實現數據一致性,就需要通過網路傳輸同步數據,但網路傳輸數據是需要時間的

忠和孝無法兩全,如果G1更新了數據,在G1和G2節點通過網路傳輸同步數據的這1段時間里,G2節點是對外提供查詢服務呢?還是不提供服務呢?

  • G2提供服務就不滿足一致性指標;
  • G2阻塞用戶請求,不提供服務就無法滿足100%可用性指標;

以上是CAP理論存在的問題;

2.BASE理論

BASE理論是針對CAP理論存問題的1種解決方案,包含3個思想:

2.1.Basically Available (基本可用)

分散式系統在出現故障時,允許損失部分可用性,即保證核心可用。

2.2.Soft State(軟狀態)

在一定時間內,允許出現中間狀態,比如臨時的不一致狀態。

2.3.Eventually Consistent(最終一致性)

雖然無法保證強一致性,但是在軟狀態結束後,最終達到數據一致。

 

三、分散式事務解決思路

分散式事務在設計之初借鑒CAP、BASE理論,有兩種解決思路:

  • AP模式:各子事務分別執行和提交,允許出現結果不一致,然後採用彌補措施恢複數據即可,實現最終一致。

  • CP模式:各個子事務執行後互相等待,同時提交,同時回滾,達成強一致。但事務等待過程中,處於弱可用狀態。

但不管是哪一種模式,想要在分散式架構中控制多個事物都需要1個事務協調者(TC)

以下下單、扣款、商品出庫環節稱為分支事務,整個環節稱為全局事務

四、初識Seata

Seata是 2019 年1 月份螞蟻金服和阿裡巴巴共同開源的分散式事務解決方案。

致力於提供高性能和簡單易用的分散式事務服務,為用戶打造一站式的分散式事務解決方案。

官網地址:http://seata.io/,其中的文檔、播客中提供了大量的使用說明、源碼分析。

1.Seata的架構

Seata事務管理中有3個重要的角色:

  • TC (Transaction Coordinator) - 事務協調者:搭建好的Seata伺服器,所有的RM和TM都要想TC上報,當前分支事務執行的狀態,以便於TC作出全局事務的回滾/提交操作(CEO);

  • TM (Transaction Manager) - 事務管理器:代表整個業務邏輯,決定全局事務的範圍和邊界,從哪個環節開始全局事務?在哪個環節提交或回滾全局事務?從哪個環節結束全局事務?(經理)

  • RM (Resource Manager) - 資源管理器:具體執行分支事務的微服務。(員工)

 

Seata基於上述架構提供了四種不同的分散式事務解決方案:

  • XA模式:強一致性分階段事務模式,犧牲了一定的可用性,無業務侵入

  • TCC模式:最終一致的分階段事務模式,有業務侵入

  • AT模式:最終一致的分階段事務模式,無業務侵入,也是Seata的預設模式

  • SAGA模式:長事務模式,有業務侵入

無論採用哪1種分散式事務解決方案,都需要先搭建Seata伺服器,也就是事務的協調者(TC)。

 

2.安裝Seata

2.1.Seata配置文件

使Seata服務註冊到Nacos中,並指定讀取Nacos中的配置文件;

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中配好。

配置內容如下

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兩張表;

 這些表主要記錄全局事務、分支事務、全局鎖信息:

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已經註冊到Nacos並可以從Nacos中讀取配置信息;

我們就可以在微服務中集成使用Seata服務了;

1.引入依賴

<!--seata-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
        <!--版本較低,1.3.0,因此排除--> 
        <exclusion>
            <artifactId>seata-spring-boot-starter</artifactId>
            <groupId>io.seata</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <!--seata starter 採用1.4.2版本-->
    <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種事務模式,幫我們實現分散式事務;

分散式事務都是基於兩階段提交原理的;

 

1.兩階段提交

XA是規範,目前主流資料庫都實現了這種規範,實現的原理都是基於兩階段提交。

正常情況:

 異常情況:

一階段(事務預提交):

  • 事務協調者通知每個事物參與者,去資料庫執行事務的預提交;

  • 事務參與者預提交完成之後,向事務協調者報告事務預提交狀態;(此時事務不是真正的提交,繼續持有資料庫鎖)

二階段:

  • 事務協調者基於一階段的報告來判斷下一步操作

    • 如果一階段的分支事務全部預提交成功,則通知所有事務參與者去資料庫正真提交事務

    • 如果一階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原則。

  • 常用資料庫都支持,實現簡單,並且沒有代碼侵入

XA模式的缺點是什麼?

  • 因為一階段需要鎖定資料庫資源,等待二階段結束才釋放,性能較差

  • 依賴關係型資料庫實現事務

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模式的分散式事務時,有可能出現臟寫問題,如圖:

 

 解決臟寫問題的思路就是引入了全局鎖的概念。

在釋放DB鎖之前,先拿到全局鎖。避免同一時刻有另外一個事務來操作當前數據。

3.3.優缺點

AT模式的優點:

  • 一階段完成直接提交事務,釋放資料庫資源,性能比較好

  • 利用全局鎖實現讀寫隔離

  • 沒有代碼侵入,框架自動完成回滾和提交

AT模式的缺點:

  • 兩階段之間屬於軟狀態,屬於最終一致

  • 框架的快照功能會影響性能,但比XA模式要好很多

3.4.實現AT模式

3.4.1.導入資料庫表,記錄全局鎖

 

 

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

------------------------------------------

DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log`  (
  `branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',
  `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'global transaction id',
  `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'undo_log context,such as serialization',
  `rollback_info` longblob NOT NULL COMMENT 'rollback info',
  `log_status` int(11) NOT NULL COMMENT '0:normal status,1:defense status',
  `log_created` datetime(6) NOT NULL COMMENT 'create datetime',
  `log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',
  UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Compact;
undo_log.sql

 

3.4.2.修改application.yml文件

將事務模式修改為AT模式即可

seata:
  data-source-proxy-mode: AT # 預設就是AT

2.4.3.重啟服務並測試

4.TCC模式

TCC是Try、Confirm、Cancel三個單詞的縮寫,屬於二階段提交事務;

TCC要求每1個分支事務實現3個操作或者3個階段:Try預處理、Confirm確認、Cancel撤銷;

Try操作做業務檢查以及資源預留

Confirm做業務確認

Cancel實現1個與Try相反的操作既回滾操作

過人工編碼來實現數據恢復1個業務至少需要實現3個方介面:

  • Try:資源的檢測和預留;

  • Confirm:完成資源操作業務;要求 Try 成功 Confirm 一定要能成功。

  • Cancel:預留資源釋放,可以理解為try的反向操作。 

TCC模式的出現的空回歸和業務懸掛問題都是因為TM(全局事務管理器)會通過單獨的線程非同步調用Try、Cancel、Confirm這3個操作

且會出現重覆調用現象,所以TCC模式中的Try、Cancel、Confirm這3個操作都需要實現冪等性、並且避免空回歸和業務懸掛;

1.TCC執行流程

  • TM(業務邏輯方法)開始執行之後,立即自動向TC(Seat伺服器)開啟1個發起全局事務的通知;
  • TC為當前全局事務分配1個全局事務編號;
  • TM(業務邏輯方法)方法依次向下調用TM業務邏輯方法里包含的RM分支事務,RM向TC上報分支事務的執行狀態,TC為RM分配分支事務編號;
  • TM業務邏輯方法調用完了所有RM之後,TM向TC上報執行成功/失敗通知,TC向所有RM下達分支事務的Commit/Rollback操作;

 

2.事務懸掛和空回滾

1.空回滾

空回滾是針對Cancel操作的。

在未執行第1階段的Try操作時,先執行了第二階段的Cancel回滾操作,說白了就是還沒有執行Try操作就執行了Cancel回滾操作,就是空回滾

2.空回滾解決方案

在執行Cancel操作之前,應當判斷Try中分支事務是否已經執行,如果尚未執行,則應該空回滾。

3.事務懸掛

事務懸掛是針對Try操作的;

對於已經空回滾的業務,之前被阻塞的try操作恢復,繼續執行try,就永遠不可能confirm或cancel ,事務一直處於中間狀態,這就是業務懸掛

4.事務懸掛解決方案

在執行第1階段的Try操作時,應當判斷第2階段的Confirm/Cancel操作是否已經執行過了?那目前就是分支事務就處於空回滾狀態,此時Try操作無需執行;

如果第2階段的Cancel操作已經提前執行,那目前就是分支事務就處於空回滾狀態,此時第1階段的Try操作,應當阻止空回滾之後的Try操作,避免業務懸掛,一錯再錯;

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • const person = { name: 'Lydia' } Object.defineProperty(person, 'age', { value: 21, }) console.log(person) console.log(Object.keys(person)) 輸出結果 原因: de ...
  • 1. 前言 最近在處理前端直播的業務,根據業務需要,使用 flv.js 的方案播放實時的flv視頻流。不得不承認,flv.js 是一個偉大的庫。 在使用flv.js開發的過程中,遇到了一些問題,也無外乎是視頻延遲,視頻卡頓等問題,經過在github issues里摸爬滾打,加上長時間的試錯,將這些問 ...
  • 介紹: 有時候請求某些第三方api用nginx做反向代理解決跨域不能滿足需求,例如請求百度或者騰訊地圖的ip定位介面,該介面會根據請求來源的ip返回該ip地址對應的位置信息,但是若是用ng做了代理或者是後端做介面轉發的話實際獲取到的ip位置信息是伺服器的ip地址,想要直接解析客戶端的ip位置信息就必 ...
  • # 切換到要覆蓋的分支,這裡我們用develop分支git checkout develop# 執行覆蓋的命令,這裡是將master分支的內容覆蓋到develop分支git reset --hard origin/master# 覆蓋成功之後,將本地分支強行推到遠程分支git push -f 本人試 ...
  • 之前很多項目使用地圖時技術選型不一樣;一會兒使用騰訊地圖、一會兒使用高德地圖,一會兒使用百度地圖;每次使用都去查相關api封裝請求很麻煩,於是自己簡單封裝了一下; 插件介紹:基於h5瀏覽器gps定位、百度地圖、高德地圖、騰訊地圖api封裝的獲取位置信息相關插件,支持高精度定位;選擇使用哪個地圖傳入對 ...
  • 一、什麼是設計原則? 答:如果說設計模式是編寫代碼的一種套路,那麼設計原則就是用來約束我們使用這種套路應該要遵循的規則,只有遵循了這些規則的設計模式編寫出來的應用程式才具有更好的擴展性和維護性。作為一個程式員,不應該只站在客戶的角度去判定某一程式只要實現了了功能、擁有了漂亮的外觀、良好的用戶體驗,就 ...
  • 一、什麼是設計模式? 答:程式都是通過寫代碼來實現的,老前輩們在開發程式的過程中,為瞭解決某一類問題,日積月累總結出了一套套的代碼編寫經驗,通過這些經驗,按照套路出牌,可以讓開發出來的代碼復用性強、可靠性高、閱讀性好。復用性強意味著我們能減少代碼開發,更方便後期代碼維護;這些經驗都是老前輩們經過千錘 ...
  • 何為狀態機? 從字面上簡單粗暴地理解,狀態機是一個跟狀態有關的機器,但其實狀態機並不是一種物理機器,而是一種模型,一種表達事物狀態及狀態變化過程的數學模型。 狀態機全稱是有限狀態機(finite-state machine,縮寫:FSM)或者有限狀態自動機(finite-state automato ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...