0.0.0
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7391b20
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
+.idea/
+vendor/
+root.data
+root.data.1
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e46a022
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+# seata-golang
+
+### 一个朴素的想法
+作为一个刚入 Golang 坑的微服务普通开发者来讲,很容易产生一个朴素的想法,希望 Golang 微服务也有分布式事务解决方案。我们注意到阿里开源了 Java 版的分布式事务解决方案 Seata,本项目尝试将 Java 版的 Seata 改写一个 Golang 的版本。
+在 Seata 没有 Golang 版本 client sdk 的情况下,Golang 版本的 TC Server 使用了和 Java 版 Seata 一样的通信协议,方便调试。
+目前,基于内存的 TC Server 已实现。希望有同样朴素想法的开发者加入我们一起完善 Golang 版本的分布式事务解决方案。
+
+### todo list
+- [X] Memory Session Manager
+- [ ] DB Session Manager  
+- [ ] ETCD Session Manager  
+- [ ] TC
+- [ ] RM
\ No newline at end of file
diff --git a/common/xid.go b/common/xid.go
new file mode 100644
index 0000000..8603ca3
--- /dev/null
+++ b/common/xid.go
@@ -0,0 +1,26 @@
+package common
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+type XId struct {
+	Port int
+	IpAddress string
+}
+
+var XID = &XId{}
+
+func (xId *XId) GenerateXID(tranId int64) string {
+	return fmt.Sprintf("%s:%d:%d",xId.IpAddress,xId.Port,tranId)
+}
+
+func (xId *XId) GetTransactionId(xid string) int64 {
+	if xid == "" { return -1 }
+
+	idx := strings.LastIndex(xid,":")
+	tranId,_ := strconv.ParseInt(xid[idx:],10,64)
+	return tranId
+}
diff --git a/docs/seata-golang.svg b/docs/seata-golang.svg
new file mode 100644
index 0000000..0e5b662
--- /dev/null
+++ b/docs/seata-golang.svg
@@ -0,0 +1 @@
+<svg id="kity_svg_6" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="729" height="1334" style="background: rgb(251, 251, 251); visibility: visible;" viewBox="0 0 729 1334"><defs id="kity_defs_7"><linearGradient id="kity_linearGradient_17" x1="0" y1="0" x2="0" y2="1"><stop id="kity_stop_18" offset="0" stop-color="rgb(255, 255, 255)"></stop><stop id="kity_stop_19" offset="1" stop-color="rgb(204, 204, 204)"></stop></linearGradient><marker id="kity_marker_2" orient="auto" refX="6" refY="0" viewBox="-7 -7 14 14" markerWidth="7" markerHeight="7" markerUnits="userSpaceOnUse"><path id="kity_path_3" fill="rgb(115, 161, 191)" stroke="none" d="M6,0A6,6,0,1,1,-6,0A6,6,0,1,1,6,0"></path></marker></defs><g id="kity_g_8"><g id="minder1" text-rendering="optimize-speed"><g id="minder_connect_group1"><path id="kity_path_31" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M97,667.5A194.5,634,0,0,1,291.5,33.5"></path><path id="kity_path_33" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M370.5,33.5C390.5,33.5,390.5,33.5,410.5,33.5"></path><path id="kity_path_35" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M97,667.5A194.5,568,0,0,1,291.5,99.5"></path><path id="kity_path_37" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M377.5,99.5C397.5,99.5,397.5,99.5,417.5,99.5"></path><path id="kity_path_39" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M97,667.5A194.5,172,0,0,1,291.5,495.5"></path><path id="kity_path_45" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M347.5,495.5C367.5,495.5,367.5,190.5,387.5,190.5"></path><path id="kity_path_47" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M446.5,190.5C466.5,190.5,466.5,164.5,486.5,164.5"></path><path id="kity_path_49" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M446.5,190.5C466.5,190.5,466.5,216.5,486.5,216.5"></path><path id="kity_path_51" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M347.5,495.5C367.5,495.5,367.5,294.5,387.5,294.5"></path><path id="kity_path_53" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M444.5,294.5C464.5,294.5,464.5,294.5,484.5,294.5"></path><path id="kity_path_55" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M556.5,294.5C576.5,294.5,576.5,268.5,596.5,268.5"></path><path id="kity_path_57" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M556.5,294.5C576.5,294.5,576.5,320.5,596.5,320.5"></path><path id="kity_path_59" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M347.5,495.5C367.5,495.5,367.5,398.5,387.5,398.5"></path><path id="kity_path_61" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M473.5,398.5C493.5,398.5,493.5,372.5,513.5,372.5"></path><path id="kity_path_63" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M473.5,398.5C493.5,398.5,493.5,424.5,513.5,424.5"></path><path id="kity_path_65" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M347.5,495.5C367.5,495.5,367.5,528.5,387.5,528.5"></path><path id="kity_path_67" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M431.5,528.5C451.5,528.5,451.5,528.5,471.5,528.5"></path><path id="kity_path_71" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M544.5,528.5C564.5,528.5,564.5,476.5,584.5,476.5"></path><path id="kity_path_73" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M544.5,528.5C564.5,528.5,564.5,528.5,584.5,528.5"></path><path id="kity_path_75" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M544.5,528.5C564.5,528.5,564.5,580.5,584.5,580.5"></path><path id="kity_path_77" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M347.5,495.5C367.5,495.5,367.5,632.5,387.5,632.5"></path><path id="kity_path_79" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M445.5,632.5C465.5,632.5,465.5,632.5,485.5,632.5"></path><path id="kity_path_81" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M347.5,495.5C367.5,495.5,367.5,801.5,387.5,801.5"></path><path id="kity_path_83" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M444.5,801.5C464.5,801.5,464.5,736.5,484.5,736.5"></path><path id="kity_path_87" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M557.5,736.5C577.5,736.5,577.5,684.5,597.5,684.5"></path><path id="kity_path_89" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M557.5,736.5C577.5,736.5,577.5,736.5,597.5,736.5"></path><path id="kity_path_91" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M557.5,736.5C577.5,736.5,577.5,788.5,597.5,788.5"></path><path id="kity_path_93" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M444.5,801.5C464.5,801.5,464.5,866.5,484.5,866.5"></path><path id="kity_path_95" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M601.5,866.5C621.5,866.5,621.5,840.5,641.5,840.5"></path><path id="kity_path_97" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M601.5,866.5C621.5,866.5,621.5,892.5,641.5,892.5"></path><path id="kity_path_99" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M97,667.5A194.5,338,0,0,0,291.5,1005.5"></path><path id="kity_path_101" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M350.5,1005.5C370.5,1005.5,370.5,953.5,390.5,953.5"></path><path id="kity_path_103" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M350.5,1005.5C370.5,1005.5,370.5,1005.5,390.5,1005.5"></path><path id="kity_path_105" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M350.5,1005.5C370.5,1005.5,370.5,1057.5,390.5,1057.5"></path><path id="kity_path_107" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M97,667.5A194.5,454,0,0,0,291.5,1121.5"></path><path id="kity_path_109" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M97,667.5A194.5,544,0,0,0,291.5,1211.5"></path><path id="kity_path_111" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M385.5,1211.5C405.5,1211.5,405.5,1211.5,425.5,1211.5"></path><path id="kity_path_113" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M498.5,1211.5C518.5,1211.5,518.5,1185.5,538.5,1185.5"></path><path id="kity_path_115" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M498.5,1211.5C518.5,1211.5,518.5,1237.5,538.5,1237.5"></path><path id="kity_path_117" fill="none" stroke="rgb(115, 161, 191)" stroke-width="1" d="M97,667.5A194.5,634,0,0,0,291.5,1301.5"></path></g><g id="minder_node1"><path id="node_outline1" fill="rgb(115, 161, 191)" stroke="rgb(115, 161, 191)" d="M25.5,647.5h143a5,5,0,0,1,5,5v30a5,5,0,0,1,-5,5h-143a5,5,0,0,1,-5,-5v-30a5,5,0,0,1,5,-5z" stroke-width="3"></path><g id="node_text1" fill="white"><text id="kity_text_22" text-rendering="inherit" font-size="16" dy=".8em" y="659.5" x="44.5">seata-golang</text></g></g><g id="kity_g_12"><path id="kity_path_13" fill="none" stroke="none" d="M44.5,667.5h0v0h0z"></path></g><g id="kity_g_14"><path id="kity_path_15" fill="none" stroke="none" d="M44.5,667.5h0v0h0z"></path><path id="kity_path_16" fill="none" stroke="none"></path></g><g id="minder_node2"><g id="node_expander2" style="cursor: pointer;"><path id="kity_path_254" fill="white" stroke="gray" d="M292.5,33.5A6,6,0,1,1,280.5,33.5A6,6,0,1,1,292.5,33.5"></path><path id="kity_path_255" fill="none" stroke="gray" d="M282,33.5L291,33.5"></path></g><path id="node_outline3" fill="rgb(238, 243, 246)" stroke="rgb(115, 161, 191)" d="M296.5,20.5h71a3,3,0,0,1,3,3v20a3,3,0,0,1,-3,3h-71a3,3,0,0,1,-3,-3v-20a3,3,0,0,1,3,-3z" stroke-width="1"></path><g id="node_text3" fill="black"><text id="kity_text_121" text-rendering="inherit" font-size="14" dy=".8em" y="26.5" x="313.5">meta</text></g></g><g id="minder_node3"><g id="node_expander1" style="cursor: pointer;" display="none"><path id="kity_path_251" fill="white" stroke="gray" d="M410.5,33.5A6,6,0,1,1,398.5,33.5A6,6,0,1,1,410.5,33.5"></path><path id="kity_path_252" fill="none" stroke="gray"></path></g><path id="node_outline2" fill="none" stroke="none" d="M415.5,22.5h46a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-46a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text2" fill="black"><text id="kity_text_119" text-rendering="inherit" font-size="12" dy=".8em" y="27.5" x="420.5">枚举等</text></g></g><g id="minder_node4"><g id="node_expander4" style="cursor: pointer;"><path id="kity_path_260" fill="white" stroke="gray" d="M292.5,99.5A6,6,0,1,1,280.5,99.5A6,6,0,1,1,292.5,99.5"></path><path id="kity_path_261" fill="none" stroke="gray" d="M282,99.5L291,99.5"></path></g><path id="node_outline5" fill="rgb(238, 243, 246)" stroke="rgb(115, 161, 191)" d="M296.5,86.5h78a3,3,0,0,1,3,3v20a3,3,0,0,1,-3,3h-78a3,3,0,0,1,-3,-3v-20a3,3,0,0,1,3,-3z" stroke-width="1"></path><g id="node_text5" fill="black"><text id="kity_text_125" text-rendering="inherit" font-size="14" dy=".8em" y="92.5" x="313.5">model</text></g></g><g id="minder_node5"><g id="node_expander3" style="cursor: pointer;" display="none"><path id="kity_path_257" fill="white" stroke="gray" d="M417.5,99.5A6,6,0,1,1,405.5,99.5A6,6,0,1,1,417.5,99.5"></path><path id="kity_path_258" fill="none" stroke="gray"></path></g><path id="node_outline4" fill="none" stroke="none" d="M422.5,88.5h60a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-60a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text4" fill="black"><text id="kity_text_123" text-rendering="inherit" font-size="12" dy=".8em" y="93.5" x="427.5">resource</text></g></g><g id="minder_node6"><g id="node_expander34" style="cursor: pointer;"><path id="kity_path_350" fill="white" stroke="gray" d="M292.5,495.5A6,6,0,1,1,280.5,495.5A6,6,0,1,1,292.5,495.5"></path><path id="kity_path_351" fill="none" stroke="gray" d="M282,495.5L291,495.5"></path></g><path id="node_outline35" fill="rgb(238, 243, 246)" stroke="rgb(115, 161, 191)" d="M296.5,482.5h48a3,3,0,0,1,3,3v20a3,3,0,0,1,-3,3h-48a3,3,0,0,1,-3,-3v-20a3,3,0,0,1,3,-3z" stroke-width="1"></path><g id="node_text35" fill="black"><text id="kity_text_185" text-rendering="inherit" font-size="14" dy=".8em" y="488.5" x="313.5">tc</text></g></g><g id="minder_node9"><g id="node_expander9" style="cursor: pointer;"><path id="kity_path_275" fill="white" stroke="gray" d="M387.5,190.5A6,6,0,1,1,375.5,190.5A6,6,0,1,1,387.5,190.5"></path><path id="kity_path_276" fill="none" stroke="gray" d="M377,190.5L386,190.5"></path></g><path id="node_outline10" fill="none" stroke="none" d="M392.5,179.5h49a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-49a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z" stroke-width="3"></path><g id="node_text10" fill="black"><text id="kity_text_135" text-rendering="inherit" font-size="12" dy=".8em" y="184.5" x="397.5">session</text></g></g><g id="minder_node10"><g id="node_expander7" style="cursor: pointer;" display="none"><path id="kity_path_269" fill="white" stroke="gray" d="M486.5,164.5A6,6,0,1,1,474.5,164.5A6,6,0,1,1,486.5,164.5"></path><path id="kity_path_270" fill="none" stroke="gray"></path></g><path id="node_outline8" fill="none" stroke="none" d="M491.5,153.5h95a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-95a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text8" fill="black"><text id="kity_text_131" text-rendering="inherit" font-size="12" dy=".8em" y="158.5" x="496.5">branch session</text></g></g><g id="minder_node11"><g id="node_expander8" style="cursor: pointer;" display="none"><path id="kity_path_272" fill="white" stroke="gray" d="M486.5,216.5A6,6,0,1,1,474.5,216.5A6,6,0,1,1,486.5,216.5"></path><path id="kity_path_273" fill="none" stroke="gray"></path></g><path id="node_outline9" fill="none" stroke="none" d="M491.5,205.5h89a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-89a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text9" fill="black"><text id="kity_text_133" text-rendering="inherit" font-size="12" dy=".8em" y="210.5" x="496.5">global session</text></g></g><g id="minder_node12"><g id="node_expander13" style="cursor: pointer;"><path id="kity_path_287" fill="white" stroke="gray" d="M387.5,294.5A6,6,0,1,1,375.5,294.5A6,6,0,1,1,387.5,294.5"></path><path id="kity_path_288" fill="none" stroke="gray" d="M377,294.5L386,294.5"></path></g><path id="node_outline14" fill="none" stroke="none" d="M392.5,283.5h47a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-47a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text14" fill="black"><text id="kity_text_143" text-rendering="inherit" font-size="12" dy=".8em" y="288.5" x="397.5">config</text></g></g><g id="minder_node13"><g id="node_expander12" style="cursor: pointer;"><path id="kity_path_284" fill="white" stroke="gray" d="M484.5,294.5A6,6,0,1,1,472.5,294.5A6,6,0,1,1,484.5,294.5"></path><path id="kity_path_285" fill="none" stroke="gray" d="M474,294.5L483,294.5"></path></g><path id="node_outline13" fill="none" stroke="none" d="M489.5,283.5h62a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-62a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text13" fill="black"><text id="kity_text_141" text-rendering="inherit" font-size="12" dy=".8em" y="288.5" x="494.5">tc config</text></g></g><g id="minder_node14"><g id="node_expander10" style="cursor: pointer;" display="none"><path id="kity_path_278" fill="white" stroke="gray" d="M596.5,268.5A6,6,0,1,1,584.5,268.5A6,6,0,1,1,596.5,268.5"></path><path id="kity_path_279" fill="none" stroke="gray"></path></g><path id="node_outline11" fill="none" stroke="none" d="M601.5,257.5h74a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-74a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text11" fill="black"><text id="kity_text_137" text-rendering="inherit" font-size="12" dy=".8em" y="262.5" x="606.5">lock config</text></g></g><g id="minder_node15"><g id="node_expander11" style="cursor: pointer;" display="none"><path id="kity_path_281" fill="white" stroke="gray" d="M596.5,320.5A6,6,0,1,1,584.5,320.5A6,6,0,1,1,596.5,320.5"></path><path id="kity_path_282" fill="none" stroke="gray"></path></g><path id="node_outline12" fill="none" stroke="none" d="M601.5,309.5h78a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-78a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text12" fill="black"><text id="kity_text_139" text-rendering="inherit" font-size="12" dy=".8em" y="314.5" x="606.5">store config</text></g></g><g id="minder_node16"><g id="node_expander16" style="cursor: pointer;"><path id="kity_path_296" fill="white" stroke="gray" d="M387.5,398.5A6,6,0,1,1,375.5,398.5A6,6,0,1,1,387.5,398.5"></path><path id="kity_path_297" fill="none" stroke="gray" d="M377,398.5L386,398.5"></path></g><path id="node_outline17" fill="none" stroke="none" d="M392.5,387.5h76a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-76a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text17" fill="black"><text id="kity_text_149" text-rendering="inherit" font-size="12" dy=".8em" y="392.5" x="397.5">constructor</text></g></g><g id="minder_node17"><g id="node_expander14" style="cursor: pointer;" display="none"><path id="kity_path_290" fill="white" stroke="gray" d="M513.5,372.5A6,6,0,1,1,501.5,372.5A6,6,0,1,1,513.5,372.5"></path><path id="kity_path_291" fill="none" stroke="gray"></path></g><path id="node_outline15" fill="none" stroke="none" d="M518.5,361.5h173a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-173a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text15" fill="black"><text id="kity_text_145" text-rendering="inherit" font-size="12" dy=".8em" y="366.5" x="523.5">branch session lock channel</text></g></g><g id="minder_node18"><g id="node_expander15" style="cursor: pointer;" display="none"><path id="kity_path_293" fill="white" stroke="gray" d="M513.5,424.5A6,6,0,1,1,501.5,424.5A6,6,0,1,1,513.5,424.5"></path><path id="kity_path_294" fill="none" stroke="gray"></path></g><path id="node_outline16" fill="none" stroke="none" d="M518.5,413.5h168a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-168a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text16" fill="black"><text id="kity_text_147" text-rendering="inherit" font-size="12" dy=".8em" y="418.5" x="523.5">global session lock channel</text></g></g><g id="minder_node19"><g id="node_expander22" style="cursor: pointer;"><path id="kity_path_314" fill="white" stroke="gray" d="M387.5,528.5A6,6,0,1,1,375.5,528.5A6,6,0,1,1,387.5,528.5"></path><path id="kity_path_315" fill="none" stroke="gray" d="M377,528.5L386,528.5"></path></g><path id="node_outline23" fill="none" stroke="none" d="M392.5,517.5h34a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-34a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text23" fill="black"><text id="kity_text_161" text-rendering="inherit" font-size="12" dy=".8em" y="522.5" x="397.5">lock</text></g></g><g id="minder_node20"><g id="node_expander21" style="cursor: pointer;"><path id="kity_path_311" fill="white" stroke="gray" d="M471.5,528.5A6,6,0,1,1,459.5,528.5A6,6,0,1,1,471.5,528.5"></path><path id="kity_path_312" fill="none" stroke="gray" d="M461,528.5L470,528.5"></path></g><path id="node_outline22" fill="none" stroke="none" d="M476.5,517.5h63a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-63a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text22" fill="black"><text id="kity_text_159" text-rendering="inherit" font-size="12" dy=".8em" y="522.5" x="481.5">interface</text></g></g><g id="minder_node22"><g id="node_expander18" style="cursor: pointer;" display="none"><path id="kity_path_302" fill="white" stroke="gray" d="M584.5,476.5A6,6,0,1,1,572.5,476.5A6,6,0,1,1,584.5,476.5"></path><path id="kity_path_303" fill="none" stroke="gray"></path></g><path id="node_outline19" fill="none" stroke="rgb(57, 80, 96)" d="M589.5,465.5h85a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-85a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z" stroke-width="3"></path><g id="node_text19" fill="black"><text id="kity_text_153" text-rendering="inherit" font-size="12" dy=".8em" y="470.5" x="594.5">memory lock</text></g></g><g id="minder_node23"><g id="node_expander19" style="cursor: pointer;" display="none"><path id="kity_path_305" fill="white" stroke="gray" d="M584.5,528.5A6,6,0,1,1,572.5,528.5A6,6,0,1,1,584.5,528.5"></path><path id="kity_path_306" fill="none" stroke="gray"></path></g><path id="node_outline20" fill="none" stroke="none" d="M589.5,517.5h65a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-65a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text20" fill="black"><text id="kity_text_155" text-rendering="inherit" font-size="12" dy=".8em" y="522.5" x="594.5">etcd lock</text></g></g><g id="minder_node24"><g id="node_expander20" style="cursor: pointer;" display="none"><path id="kity_path_308" fill="white" stroke="gray" d="M584.5,580.5A6,6,0,1,1,572.5,580.5A6,6,0,1,1,584.5,580.5"></path><path id="kity_path_309" fill="none" stroke="gray"></path></g><path id="node_outline21" fill="none" stroke="none" d="M589.5,569.5h53a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-53a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text21" fill="black"><text id="kity_text_157" text-rendering="inherit" font-size="12" dy=".8em" y="574.5" x="594.5">db lock</text></g></g><g id="minder_node25"><g id="node_expander24" style="cursor: pointer;"><path id="kity_path_320" fill="white" stroke="gray" d="M387.5,632.5A6,6,0,1,1,375.5,632.5A6,6,0,1,1,387.5,632.5"></path><path id="kity_path_321" fill="none" stroke="gray" d="M377,632.5L386,632.5"></path></g><path id="node_outline25" fill="none" stroke="none" d="M392.5,621.5h48a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-48a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text25" fill="black"><text id="kity_text_165" text-rendering="inherit" font-size="12" dy=".8em" y="626.5" x="397.5">model</text></g></g><g id="minder_node26"><g id="node_expander23" style="cursor: pointer;" display="none"><path id="kity_path_317" fill="white" stroke="gray" d="M485.5,632.5A6,6,0,1,1,473.5,632.5A6,6,0,1,1,485.5,632.5"></path><path id="kity_path_318" fill="none" stroke="gray"></path></g><path id="node_outline24" fill="none" stroke="none" d="M490.5,621.5h108a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-108a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text24" fill="black"><text id="kity_text_163" text-rendering="inherit" font-size="12" dy=".8em" y="626.5" x="495.5">session condition</text></g></g><g id="minder_node27"><g id="node_expander33" style="cursor: pointer;"><path id="kity_path_347" fill="white" stroke="gray" d="M387.5,801.5A6,6,0,1,1,375.5,801.5A6,6,0,1,1,387.5,801.5"></path><path id="kity_path_348" fill="none" stroke="gray" d="M377,801.5L386,801.5"></path></g><path id="node_outline34" fill="none" stroke="none" d="M392.5,790.5h47a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-47a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z" stroke-width="3"></path><g id="node_text34" fill="black"><text id="kity_text_183" text-rendering="inherit" font-size="12" dy=".8em" y="795.5" x="397.5">holder</text></g></g><g id="minder_node28"><g id="node_expander29" style="cursor: pointer;"><path id="kity_path_335" fill="white" stroke="gray" d="M484.5,736.5A6,6,0,1,1,472.5,736.5A6,6,0,1,1,484.5,736.5"></path><path id="kity_path_336" fill="none" stroke="gray" d="M474,736.5L483,736.5"></path></g><path id="node_outline30" fill="none" stroke="none" d="M489.5,725.5h63a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-63a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text30" fill="black"><text id="kity_text_175" text-rendering="inherit" font-size="12" dy=".8em" y="730.5" x="494.5">interface</text></g></g><g id="minder_node30"><g id="node_expander26" style="cursor: pointer;" display="none"><path id="kity_path_326" fill="white" stroke="gray" d="M597.5,684.5A6,6,0,1,1,585.5,684.5A6,6,0,1,1,597.5,684.5"></path><path id="kity_path_327" fill="none" stroke="gray"></path></g><path id="node_outline27" fill="none" stroke="none" d="M602.5,673.5h57a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-57a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z" stroke-width="3"></path><g id="node_text27" fill="black"><text id="kity_text_169" text-rendering="inherit" font-size="12" dy=".8em" y="678.5" x="607.5">file store</text></g></g><g id="minder_node31"><g id="node_expander27" style="cursor: pointer;" display="none"><path id="kity_path_329" fill="white" stroke="gray" d="M597.5,736.5A6,6,0,1,1,585.5,736.5A6,6,0,1,1,597.5,736.5"></path><path id="kity_path_330" fill="none" stroke="gray"></path></g><path id="node_outline28" fill="none" stroke="none" d="M602.5,725.5h57a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-57a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text28" fill="black"><text id="kity_text_171" text-rendering="inherit" font-size="12" dy=".8em" y="730.5" x="607.5">db store</text></g></g><g id="minder_node32"><g id="node_expander28" style="cursor: pointer;" display="none"><path id="kity_path_332" fill="white" stroke="gray" d="M597.5,788.5A6,6,0,1,1,585.5,788.5A6,6,0,1,1,597.5,788.5"></path><path id="kity_path_333" fill="none" stroke="gray"></path></g><path id="node_outline29" fill="none" stroke="none" d="M602.5,777.5h69a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-69a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text29" fill="black"><text id="kity_text_173" text-rendering="inherit" font-size="12" dy=".8em" y="782.5" x="607.5">etcd store</text></g></g><g id="minder_node33"><g id="node_expander32" style="cursor: pointer;"><path id="kity_path_344" fill="white" stroke="gray" d="M484.5,866.5A6,6,0,1,1,472.5,866.5A6,6,0,1,1,484.5,866.5"></path><path id="kity_path_345" fill="none" stroke="gray" d="M474,866.5L483,866.5"></path></g><path id="node_outline33" fill="none" stroke="none" d="M489.5,855.5h107a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-107a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text33" fill="black"><text id="kity_text_181" text-rendering="inherit" font-size="12" dy=".8em" y="860.5" x="494.5">session manager</text></g></g><g id="minder_node34"><g id="node_expander30" style="cursor: pointer;" display="none"><path id="kity_path_338" fill="white" stroke="gray" d="M641.5,840.5A6,6,0,1,1,629.5,840.5A6,6,0,1,1,641.5,840.5"></path><path id="kity_path_339" fill="none" stroke="gray"></path></g><path id="node_outline31" fill="none" stroke="none" d="M646.5,829.5h58a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-58a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text31" fill="black"><text id="kity_text_177" text-rendering="inherit" font-size="12" dy=".8em" y="834.5" x="651.5">memory</text></g></g><g id="minder_node35"><g id="node_expander31" style="cursor: pointer;" display="none"><path id="kity_path_341" fill="white" stroke="gray" d="M641.5,892.5A6,6,0,1,1,629.5,892.5A6,6,0,1,1,641.5,892.5"></path><path id="kity_path_342" fill="none" stroke="gray"></path></g><path id="node_outline32" fill="none" stroke="none" d="M646.5,881.5h26a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-26a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text32" fill="black"><text id="kity_text_179" text-rendering="inherit" font-size="12" dy=".8em" y="886.5" x="651.5">db</text></g></g><g id="minder_node36"><g id="node_expander38" style="cursor: pointer;"><path id="kity_path_362" fill="white" stroke="gray" d="M292.5,1005.5A6,6,0,1,1,280.5,1005.5A6,6,0,1,1,292.5,1005.5"></path><path id="kity_path_363" fill="none" stroke="gray" d="M282,1005.5L291,1005.5"></path></g><path id="node_outline39" fill="rgb(238, 243, 246)" stroke="rgb(115, 161, 191)" d="M296.5,992.5h51a3,3,0,0,1,3,3v20a3,3,0,0,1,-3,3h-51a3,3,0,0,1,-3,-3v-20a3,3,0,0,1,3,-3z" stroke-width="1"></path><g id="node_text39" fill="black"><text id="kity_text_193" text-rendering="inherit" font-size="14" dy=".8em" y="998.5" x="313.5">rm</text></g></g><g id="minder_node37"><g id="node_expander35" style="cursor: pointer;" display="none"><path id="kity_path_353" fill="white" stroke="gray" d="M390.5,953.5A6,6,0,1,1,378.5,953.5A6,6,0,1,1,390.5,953.5"></path><path id="kity_path_354" fill="none" stroke="gray"></path></g><path id="node_outline36" fill="none" stroke="none" d="M395.5,942.5h47a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-47a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text36" fill="black"><text id="kity_text_187" text-rendering="inherit" font-size="12" dy=".8em" y="947.5" x="400.5">config</text></g></g><g id="minder_node38"><g id="node_expander36" style="cursor: pointer;" display="none"><path id="kity_path_356" fill="white" stroke="gray" d="M390.5,1005.5A6,6,0,1,1,378.5,1005.5A6,6,0,1,1,390.5,1005.5"></path><path id="kity_path_357" fill="none" stroke="gray"></path></g><path id="node_outline37" fill="none" stroke="none" d="M395.5,994.5h64a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-64a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text37" fill="black"><text id="kity_text_189" text-rendering="inherit" font-size="12" dy=".8em" y="999.5" x="400.5">sql parser</text></g></g><g id="minder_node39"><g id="node_expander37" style="cursor: pointer;" display="none"><path id="kity_path_359" fill="white" stroke="gray" d="M390.5,1057.5A6,6,0,1,1,378.5,1057.5A6,6,0,1,1,390.5,1057.5"></path><path id="kity_path_360" fill="none" stroke="gray"></path></g><path id="node_outline38" fill="none" stroke="none" d="M395.5,1046.5h62a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-62a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text38" fill="black"><text id="kity_text_191" text-rendering="inherit" font-size="12" dy=".8em" y="1051.5" x="400.5">undo log</text></g></g><g id="minder_node40"><g id="node_expander39" style="cursor: pointer;" display="none"><path id="kity_path_365" fill="white" stroke="gray" d="M292.5,1121.5A6,6,0,1,1,280.5,1121.5A6,6,0,1,1,292.5,1121.5"></path><path id="kity_path_366" fill="none" stroke="gray"></path></g><path id="node_outline40" fill="rgb(238, 243, 246)" stroke="rgb(115, 161, 191)" d="M296.5,1108.5h52a3,3,0,0,1,3,3v20a3,3,0,0,1,-3,3h-52a3,3,0,0,1,-3,-3v-20a3,3,0,0,1,3,-3z" stroke-width="1"></path><g id="node_text40" fill="black"><text id="kity_text_195" text-rendering="inherit" font-size="14" dy=".8em" y="1114.5" x="313.5">tm</text></g></g><g id="minder_node41"><g id="node_expander43" style="cursor: pointer;"><path id="kity_path_377" fill="white" stroke="gray" d="M292.5,1211.5A6,6,0,1,1,280.5,1211.5A6,6,0,1,1,292.5,1211.5"></path><path id="kity_path_378" fill="none" stroke="gray" d="M282,1211.5L291,1211.5"></path></g><path id="node_outline44" fill="rgb(238, 243, 246)" stroke="rgb(115, 161, 191)" d="M296.5,1198.5h86a3,3,0,0,1,3,3v20a3,3,0,0,1,-3,3h-86a3,3,0,0,1,-3,-3v-20a3,3,0,0,1,3,-3z" stroke-width="1"></path><g id="node_text44" fill="black"><text id="kity_text_203" text-rendering="inherit" font-size="14" dy=".8em" y="1204.5" x="313.5">logging</text></g></g><g id="minder_node42"><g id="node_expander42" style="cursor: pointer;"><path id="kity_path_374" fill="white" stroke="gray" d="M425.5,1211.5A6,6,0,1,1,413.5,1211.5A6,6,0,1,1,425.5,1211.5"></path><path id="kity_path_375" fill="none" stroke="gray" d="M415,1211.5L424,1211.5"></path></g><path id="node_outline43" fill="none" stroke="none" d="M430.5,1200.5h63a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-63a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text43" fill="black"><text id="kity_text_201" text-rendering="inherit" font-size="12" dy=".8em" y="1205.5" x="435.5">interface</text></g></g><g id="minder_node43"><g id="node_expander40" style="cursor: pointer;" display="none"><path id="kity_path_368" fill="white" stroke="gray" d="M538.5,1185.5A6,6,0,1,1,526.5,1185.5A6,6,0,1,1,538.5,1185.5"></path><path id="kity_path_369" fill="none" stroke="gray"></path></g><path id="node_outline41" fill="none" stroke="none" d="M543.5,1174.5h77a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-77a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text41" fill="black"><text id="kity_text_197" text-rendering="inherit" font-size="12" dy=".8em" y="1179.5" x="548.5">console log</text></g></g><g id="minder_node44"><g id="node_expander41" style="cursor: pointer;" display="none"><path id="kity_path_371" fill="white" stroke="gray" d="M538.5,1237.5A6,6,0,1,1,526.5,1237.5A6,6,0,1,1,538.5,1237.5"></path><path id="kity_path_372" fill="none" stroke="gray"></path></g><path id="node_outline42" fill="none" stroke="none" d="M543.5,1226.5h48a5,5,0,0,1,5,5v12a5,5,0,0,1,-5,5h-48a5,5,0,0,1,-5,-5v-12a5,5,0,0,1,5,-5z"></path><g id="node_text42" fill="black"><text id="kity_text_199" text-rendering="inherit" font-size="12" dy=".8em" y="1231.5" x="548.5">file log</text></g></g><g id="minder_node45"><g id="node_expander44" style="cursor: pointer;" display="none"><path id="kity_path_380" fill="white" stroke="gray" d="M292.5,1301.5A6,6,0,1,1,280.5,1301.5A6,6,0,1,1,292.5,1301.5"></path><path id="kity_path_381" fill="none" stroke="gray"></path></g><path id="node_outline45" fill="rgb(238, 243, 246)" stroke="rgb(115, 161, 191)" d="M296.5,1288.5h53a3,3,0,0,1,3,3v20a3,3,0,0,1,-3,3h-53a3,3,0,0,1,-3,-3v-20a3,3,0,0,1,3,-3z" stroke-width="1"></path><g id="node_text45" fill="black"><text id="kity_text_205" text-rendering="inherit" font-size="14" dy=".8em" y="1294.5" x="313.5">util</text></g></g></g></g></svg>
\ No newline at end of file
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..cc1f07c
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,17 @@
+module github.com/dk-lockdown/seata-golang
+
+go 1.13.3
+
+require (
+	github.com/dubbogo/getty v1.3.3
+	github.com/dubbogo/gost v1.6.0
+	github.com/gorilla/websocket v1.4.1 // indirect
+	github.com/pkg/errors v0.9.1
+	github.com/stretchr/testify v1.5.1
+	go.uber.org/atomic v1.5.0
+	go.uber.org/zap v1.14.0 // indirect
+	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
+	gopkg.in/yaml.v2 v2.2.8
+	vimagination.zapto.org/byteio v0.0.0-20200222190125-d27cba0f0b10
+	vimagination.zapto.org/memio v0.0.0-20200222190306-588ebc67b97d // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..ee4f0bc
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,84 @@
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dubbogo/getty v1.3.3 h1:8m4zZBqFHO+NmhH7rMPlFuuYRVjcPD7cUhumevqMZZs=
+github.com/dubbogo/getty v1.3.3/go.mod h1:U92BDyJ6sW9Jpohr2Vlz8w2uUbIbNZ3d+6rJvFTSPp0=
+github.com/dubbogo/gost v1.5.2 h1:ri/03971hdpnn3QeCU+4UZgnRNGDXLDGDucR/iozZm8=
+github.com/dubbogo/gost v1.5.2/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
+github.com/dubbogo/gost v1.6.0 h1:30ERJDdVUcfpc/oFtqPspazQ5dHfyRbDQ2QZvAFxaUE=
+github.com/dubbogo/gost v1.6.0/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
+github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
+go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
+go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
+go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.14.0 h1:/pduUoebOeeJzTDFuoMgC6nRkiasr1sBCIEorly7m4o=
+go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+vimagination.zapto.org/byteio v0.0.0-20200222190125-d27cba0f0b10 h1:pxt6fVJP67Hxo1qk8JalUghLlk3abYByl+3e0JYfUlE=
+vimagination.zapto.org/byteio v0.0.0-20200222190125-d27cba0f0b10/go.mod h1:fl9OF22g6MTKgvHA1hqMXe/L7+ULWofVTwbC9loGu7A=
+vimagination.zapto.org/memio v0.0.0-20200222190306-588ebc67b97d h1:Mp6WiHHuiwHaknxTdxJ8pvC9/B4pOgW1PamKGexG7Fs=
+vimagination.zapto.org/memio v0.0.0-20200222190306-588ebc67b97d/go.mod h1:zHGDKp2tyvF4IAfLti4pKYqCJucXYmmKMb3UMrCHK/4=
diff --git a/logging/logging.go b/logging/logging.go
new file mode 100644
index 0000000..62ded83
--- /dev/null
+++ b/logging/logging.go
@@ -0,0 +1,186 @@
+package logging
+
+import (
+	"fmt"
+	"log"
+	"os"
+)
+
+// Level represents the level of logging.
+type LogLevel uint8
+
+const (
+	Debug LogLevel = iota
+	Info
+	Warn
+	Error
+	Fatal
+	Panic
+)
+
+type ILogger interface {
+	Debug(v ...interface{})
+	Debugf(format string, v ...interface{})
+
+	Info(v ...interface{})
+	Infof(format string, v ...interface{})
+
+	Warn(v ...interface{})
+	Warnf(format string, v ...interface{})
+
+	Error(v ...interface{})
+	Errorf(format string, v ...interface{})
+
+	Fatal(v ...interface{})
+	Fatalf(format string, v ...interface{})
+
+	Panic(v ...interface{})
+	Panicf(format string, v ...interface{})
+}
+
+const (
+	DefaultLogLevel = Info
+	DefaultNamespace = "default"
+)
+
+type SeataLogger struct {
+	loggers   []*log.Logger
+	namespace string
+	logLevel  LogLevel
+}
+
+var Logger *SeataLogger
+
+func init() {
+	var loggers = make([]*log.Logger, 0)
+	loggers = append(loggers, log.New(os.Stdout, "", log.LstdFlags))
+	Logger =  &SeataLogger{
+		loggers:   loggers,
+		namespace: DefaultNamespace,
+		logLevel:  DefaultLogLevel,
+	}
+}
+
+func merge(namespace, logLevel, msg string) string {
+	return fmt.Sprintf("%s %s %s", namespace, logLevel, msg)
+}
+
+func SetNamespace(namespace string) {
+	Logger.namespace = namespace
+}
+
+func SetLogLevel(logLevel LogLevel) {
+	Logger.logLevel = logLevel
+}
+
+func AddLogger(logger *log.Logger) {
+	Logger.loggers = append(Logger.loggers, logger)
+}
+
+func (l *SeataLogger) Debug(v ...interface{}) {
+	if Debug < l.logLevel || len(v) == 0 {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "DEBUG", fmt.Sprint(v...)))
+	}
+}
+
+func (l *SeataLogger) Debugf(format string, v ...interface{}) {
+	if Debug < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "DEBUG", fmt.Sprintf(format, v...)))
+	}
+}
+
+func (l *SeataLogger) Info(v ...interface{}) {
+	if Info < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "INFO", fmt.Sprint(v...)))
+	}
+}
+
+func (l *SeataLogger) Infof(format string, v ...interface{}) {
+	if Info < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "INFO", fmt.Sprintf(format, v...)))
+	}
+}
+
+func (l *SeataLogger) Warn(v ...interface{}) {
+	if Warn < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "WARNING", fmt.Sprint(v...)))
+	}
+}
+
+func (l *SeataLogger) Warnf(format string, v ...interface{}) {
+	if Warn < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "WARNING", fmt.Sprintf(format, v...)))
+	}
+}
+
+func (l *SeataLogger) Error(v ...interface{}) {
+	if Error < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "ERROR", fmt.Sprint(v...)))
+	}
+}
+
+func (l *SeataLogger) Errorf(format string, v ...interface{}) {
+	if Error < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "ERROR", fmt.Sprintf(format, v...)))
+	}
+}
+
+func (l *SeataLogger) Fatal(v ...interface{}) {
+	if Fatal < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "FATAL", fmt.Sprint(v...)))
+	}
+}
+
+func (l *SeataLogger) Fatalf(format string, v ...interface{}) {
+	if Fatal < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "FATAL", fmt.Sprintf(format, v...)))
+	}
+}
+
+func (l *SeataLogger) Panic(v ...interface{}) {
+	if Panic < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "PANIC", fmt.Sprint(v...)))
+	}
+}
+
+func (l *SeataLogger) Panicf(format string, v ...interface{}) {
+	if Panic < l.logLevel {
+		return
+	}
+	for _,log := range l.loggers {
+		log.Print(merge(l.namespace, "PANIC", fmt.Sprintf(format, v...)))
+	}
+}
\ No newline at end of file
diff --git a/logging/logging_test.go b/logging/logging_test.go
new file mode 100644
index 0000000..3a42f3c
--- /dev/null
+++ b/logging/logging_test.go
@@ -0,0 +1,7 @@
+package logging
+
+import "testing"
+
+func TestSeataLogger_Info(t *testing.T) {
+	Logger.Info("there is a bug")
+}
\ No newline at end of file
diff --git a/meta/branch_status.go b/meta/branch_status.go
new file mode 100644
index 0000000..8bb019f
--- /dev/null
+++ b/meta/branch_status.go
@@ -0,0 +1,102 @@
+package meta
+
+import "fmt"
+
+type BranchStatus byte
+
+const (
+	/**
+	 * The BranchStatus_Unknown.
+	 * description:BranchStatus_Unknown branch status.
+	 */
+	BranchStatusUnknown BranchStatus = iota
+
+	/**
+	 * The BranchStatus_Registered.
+	 * description:BranchStatus_Registered to TC.
+	 */
+	BranchStatusRegistered
+
+	/**
+	 * The Phase one done.
+	 * description:Branch logic is successfully done at phase one.
+	 */
+	BranchStatusPhaseoneDone
+
+	/**
+	 * The Phase one failed.
+	 * description:Branch logic is failed at phase one.
+	 */
+	BranchStatusPhaseoneFailed
+
+	/**
+	 * The Phase one timeout.
+	 * description:Branch logic is NOT reported for a timeout.
+	 */
+	BranchStatusPhaseoneTimeout
+
+	/**
+	 * The Phase two committed.
+	 * description:Commit logic is successfully done at phase two.
+	 */
+	BranchStatusPhasetwoCommitted
+
+	/**
+	 * The Phase two commit failed retryable.
+	 * description:Commit logic is failed but retryable.
+	 */
+	BranchStatusPhasetwoCommitFailedRetryable
+
+	/**
+	 * The Phase two commit failed unretryable.
+	 * description:Commit logic is failed and NOT retryable.
+	 */
+	BranchStatusPhasetwoCommitFailedUnretryable
+
+	/**
+	 * The Phase two rollbacked.
+	 * description:Rollback logic is successfully done at phase two.
+	 */
+	BranchStatusPhasetwoRollbacked
+
+	/**
+	 * The Phase two rollback failed retryable.
+	 * description:Rollback logic is failed but retryable.
+	 */
+	BranchStatusPhasetwoRollbackFailedRetryable
+
+	/**
+	 * The Phase two rollback failed unretryable.
+	 * description:Rollback logic is failed but NOT retryable.
+	 */
+	BranchStatusPhasetwoRollbackFailedUnretryable
+)
+
+func (s BranchStatus) String() string {
+	switch s {
+	case BranchStatusUnknown:
+		return "Unknown"
+	case BranchStatusRegistered:
+		return "Registered"
+	case BranchStatusPhaseoneDone:
+		return "PhaseoneDone"
+	case BranchStatusPhaseoneFailed:
+		return "PhaseoneFailed"
+	case BranchStatusPhaseoneTimeout:
+		return "PhaseoneTimeout"
+	case BranchStatusPhasetwoCommitted:
+		return "PhasetwoCommitted"
+	case BranchStatusPhasetwoCommitFailedRetryable:
+		return "PhasetwoCommitFailedRetryable"
+	case BranchStatusPhasetwoCommitFailedUnretryable:
+		return "CommitFailedUnretryable"
+	case BranchStatusPhasetwoRollbacked:
+		return "PhasetwoRollbacked"
+	case BranchStatusPhasetwoRollbackFailedRetryable:
+		return "RollbackFailedRetryable"
+	case BranchStatusPhasetwoRollbackFailedUnretryable:
+		return "RollbackFailedUnretryable"
+	default:
+		return fmt.Sprintf("%d", s)
+	}
+}
\ No newline at end of file
diff --git a/meta/branch_type.go b/meta/branch_type.go
new file mode 100644
index 0000000..ece65b9
--- /dev/null
+++ b/meta/branch_type.go
@@ -0,0 +1,36 @@
+package meta
+
+import "fmt"
+
+type BranchType byte
+
+const (
+	/**
+	 * The At.
+	 */
+	// BranchType_AT Branch
+	BranchTypeAT BranchType = iota
+
+	/**
+	 * The BranchType_TCC.
+	 */
+	BranchTypeTCC
+
+	/**
+	 * The BranchType_SAGA.
+	 */
+	BranchTypeSAGA
+)
+
+func (t BranchType) String() string {
+	switch t {
+	case BranchTypeAT:
+		return "AT"
+	case BranchTypeTCC:
+		return "TCC"
+	case BranchTypeSAGA:
+		return "SAGA"
+	default:
+		return fmt.Sprintf("%d", t)
+	}
+}
\ No newline at end of file
diff --git a/meta/global_status.go b/meta/global_status.go
new file mode 100644
index 0000000..2f129dd
--- /dev/null
+++ b/meta/global_status.go
@@ -0,0 +1,142 @@
+package meta
+
+import "fmt"
+
+type GlobalStatus int32
+
+const (
+	/**
+	 * Un known global status.
+	 */
+	// BranchStatus_Unknown
+	GlobalStatusUnknown GlobalStatus = iota
+
+	/**
+	 * The GlobalStatus_Begin.
+	 */
+	// PHASE 1: can accept new branch registering.
+	GlobalStatusBegin
+
+	/**
+	 * PHASE 2: Running Status: may be changed any time.
+	 */
+	// Committing.
+	GlobalStatusCommitting
+
+	/**
+	 * The Commit retrying.
+	 */
+	// Retrying commit after a recoverable failure.
+	GlobalStatusCommitRetrying
+
+	/**
+	 * Rollbacking global status.
+	 */
+	// Rollbacking
+	GlobalStatusRollbacking
+
+	/**
+	 * The Rollback retrying.
+	 */
+	// Retrying rollback after a recoverable failure.
+	GlobalStatusRollbackRetrying
+
+	/**
+	 * The Timeout rollbacking.
+	 */
+	// Rollbacking since timeout
+	GlobalStatusTimeoutRollbacking
+
+	/**
+	 * The Timeout rollback retrying.
+	 */
+	// Retrying rollback (since timeout) after a recoverable failure.
+	GlobalStatusTimeoutRollbackRetrying
+
+	/**
+	 * All branches can be async committed. The committing is NOT done yet, but it can be seen as committed for TM/RM
+	 * client.
+	 */
+	GlobalStatusAsyncCommitting
+
+	/**
+	 * PHASE 2: Final Status: will NOT change any more.
+	 */
+	// Finally: global transaction is successfully committed.
+	GlobalStatusCommitted
+
+	/**
+	 * The Commit failed.
+	 */
+	// Finally: failed to commit
+	GlobalStatusCommitFailed
+
+	/**
+	 * The Rollbacked.
+	 */
+	// Finally: global transaction is successfully rollbacked.
+	GlobalStatusRollbacked
+
+	/**
+	 * The Rollback failed.
+	 */
+	// Finally: failed to rollback
+	GlobalStatusRollbackFailed
+
+	/**
+	 * The Timeout rollbacked.
+	 */
+	// Finally: global transaction is successfully rollbacked since timeout.
+	GlobalStatusTimeoutRollbacked
+
+	/**
+	 * The Timeout rollback failed.
+	 */
+	// Finally: failed to rollback since timeout
+	GlobalStatusTimeoutRollbackFailed
+
+	/**
+	 * The Finished.
+	 */
+	// Not managed in session MAP any more
+	GlobalStatusFinished
+)
+
+func (s GlobalStatus) String() string {
+	switch s {
+	case GlobalStatusUnknown:
+		return "Unknown"
+	case GlobalStatusBegin:
+		return "Begin"
+	case GlobalStatusCommitting:
+		return "Committing"
+	case GlobalStatusCommitRetrying:
+		return "CommitRetrying"
+	case GlobalStatusRollbacking:
+		return "Rollbacking"
+	case GlobalStatusRollbackRetrying:
+		return "RollbackRetrying"
+	case GlobalStatusTimeoutRollbacking:
+		return "TimeoutRollbacking"
+	case GlobalStatusTimeoutRollbackRetrying:
+		return "TimeoutRollbackRetrying"
+	case GlobalStatusAsyncCommitting:
+		return "AsyncCommitting"
+	case GlobalStatusCommitted:
+		return "Committed"
+	case GlobalStatusCommitFailed:
+		return "CommitFailed"
+	case GlobalStatusRollbacked:
+		return "Rollbacked"
+	case GlobalStatusRollbackFailed:
+		return "RollbackFailed"
+	case GlobalStatusTimeoutRollbacked:
+		return "TimeoutRollbacked"
+	case GlobalStatusTimeoutRollbackFailed:
+		return "TimeoutRollbackFailed"
+	case GlobalStatusFinished:
+		return "Finished"
+	default:
+		return fmt.Sprintf("%d", s)
+	}
+}
\ No newline at end of file
diff --git a/meta/transaction_exception_code.go b/meta/transaction_exception_code.go
new file mode 100644
index 0000000..a8d6ddb
--- /dev/null
+++ b/meta/transaction_exception_code.go
@@ -0,0 +1,110 @@
+package meta
+
+type TransactionExceptionCode byte
+
+const (
+	/**
+	 * Unknown transaction exception code.
+	 */
+	TransactionExceptionCodeUnknown TransactionExceptionCode = iota
+
+	/**
+	 * BeginFailed
+	 */
+	TransactionExceptionCodeBeginFailed
+
+	/**
+	 * Lock key conflict transaction exception code.
+	 */
+	TransactionExceptionCodeLockKeyConflict
+
+	/**
+	 * Io transaction exception code.
+	 */
+	IO
+
+	/**
+	 * Branch rollback failed retriable transaction exception code.
+	 */
+	TransactionExceptionCodeBranchRollbackFailedRetriable
+
+	/**
+	 * Branch rollback failed unretriable transaction exception code.
+	 */
+	TransactionExceptionCodeBranchRollbackFailedUnretriable
+
+	/**
+	 * Branch register failed transaction exception code.
+	 */
+	TransactionExceptionCodeBranchRegisterFailed
+
+	/**
+	 * Branch report failed transaction exception code.
+	 */
+	TransactionExceptionCodeBranchReportFailed
+
+	/**
+	 * Lockable check failed transaction exception code.
+	 */
+	TransactionExceptionCodeLockableCheckFailed
+
+	/**
+	 * Branch transaction not exist transaction exception code.
+	 */
+	TransactionExceptionCodeBranchTransactionNotExist
+
+	/**
+	 * Global transaction not exist transaction exception code.
+	 */
+	TransactionExceptionCodeGlobalTransactionNotExist
+
+	/**
+	 * Global transaction not active transaction exception code.
+	 */
+	TransactionExceptionCodeGlobalTransactionNotActive
+
+	/**
+	 * Global transaction status invalid transaction exception code.
+	 */
+	TransactionExceptionCodeGlobalTransactionStatusInvalid
+
+	/**
+	 * Failed to send branch commit request transaction exception code.
+	 */
+	TransactionExceptionCodeFailedToSendBranchCommitRequest
+
+	/**
+	 * Failed to send branch rollback request transaction exception code.
+	 */
+	TransactionExceptionCodeFailedToSendBranchRollbackRequest
+
+	/**
+	 * Failed to add branch transaction exception code.
+	 */
+	TransactionExceptionCodeFailedToAddBranch
+
+	/**
+	 * Failed to lock global transaction exception code.
+	 */
+	TransactionExceptionCodeFailedLockGlobalTranscation
+
+	/**
+	 * FailedWriteSession
+	 */
+	TransactionExceptionCodeFailedWriteSession
+
+	/**
+	 * Failed to holder exception code
+	 */
+	FailedStore
+)
+
+type TransactionException struct {
+	Code TransactionExceptionCode
+	Message string
+}
+
+//Error 隐式继承 builtin.error 接口
+func (e TransactionException) Error() string {
+	return "TransactionException: " + e.Message
+}
\ No newline at end of file
diff --git a/meta/transaction_role.go b/meta/transaction_role.go
new file mode 100644
index 0000000..767633f
--- /dev/null
+++ b/meta/transaction_role.go
@@ -0,0 +1,33 @@
+package meta
+
+import "fmt"
+
+type TransactionRole byte
+
+const (
+	/**
+	 * tm
+	 */
+	TMROLE TransactionRole = iota
+	/**
+	 * rm
+	 */
+	RMROLE
+	/**
+	 * server
+	 */
+	SERVERROLE
+)
+
+func (r TransactionRole) String() string {
+	switch r {
+	case TMROLE:
+		return "TMROLE"
+	case RMROLE:
+		return "RMROLE"
+	case SERVERROLE:
+		return "SERVERROLE"
+	default:
+		return fmt.Sprintf("%d", r)
+	}
+}
\ No newline at end of file
diff --git a/model/resource.go b/model/resource.go
new file mode 100644
index 0000000..6a91e60
--- /dev/null
+++ b/model/resource.go
@@ -0,0 +1,28 @@
+package model
+
+import "github.com/dk-lockdown/seata-golang/meta"
+
+type IResource interface {
+	/**
+	 * Get the resource group id.
+	 * e.g. master and slave data-source should be with the same resource group id.
+	 *
+	 * @return resource group id.
+	 */
+	getResourceGroupId() string
+
+	/**
+	 * Get the resource id.
+	 * e.g. url of a data-source could be the id of the db data-source resource.
+	 *
+	 * @return resource id.
+	 */
+	getResourceId() string
+
+	/**
+	 * get resource type, BranchType_AT, BranchType_TCC, BranchType_SAGA and XA
+	 *
+	 * @return
+	 */
+	getBranchType() meta.BranchType
+}
\ No newline at end of file
diff --git a/model/set.go b/model/set.go
new file mode 100644
index 0000000..7b7fd1e
--- /dev/null
+++ b/model/set.go
@@ -0,0 +1,69 @@
+package model
+
+import "sync"
+
+type Set struct {
+	m map[string]bool
+	sync.RWMutex
+}
+
+func NewSet() *Set {
+	return &Set{
+		m: make(map[string]bool),
+	}
+}
+
+// Add add
+func (s *Set) Add(item string) {
+	s.Lock()
+	defer s.Unlock()
+	s.m[item] = true
+}
+
+// Remove deletes the specified item from the map
+func (s *Set) Remove(item string) {
+	s.Lock()
+	defer s.Unlock()
+	delete(s.m, item)
+}
+
+// Has looks for the existence of an item
+func (s *Set) Has(item string) bool {
+	s.RLock()
+	defer s.RUnlock()
+	_, ok := s.m[item]
+	return ok
+}
+
+// Len returns the number of items in a set.
+func (s *Set) Len() int {
+	return len(s.List())
+}
+
+// Clear removes all items from the set
+func (s *Set) Clear() {
+	s.Lock()
+	defer s.Unlock()
+	s.m = make(map[string]bool)
+}
+
+// IsEmpty checks for emptiness
+func (s *Set) IsEmpty() bool {
+	if s.Len() == 0 {
+		return true
+	}
+	return false
+}
+
+// Set returns a slice of all items
+func (s *Set) List() []string {
+	s.RLock()
+	defer s.RUnlock()
+	list := make([]string, 0)
+	for item := range s.m {
+		list = append(list, item)
+	}
+	return list
+}
+
+
diff --git a/protocal/codec/codec.go b/protocal/codec/codec.go
new file mode 100644
index 0000000..0366cad
--- /dev/null
+++ b/protocal/codec/codec.go
@@ -0,0 +1,243 @@
+package codec
+
+import (
+	"bytes"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/protocal"
+	"vimagination.zapto.org/byteio"
+)
+
+type SerializerType byte
+
+const (
+	SEATA = byte(0x1)
+	PROTOBUF = byte(0x2)
+	KRYO = byte(0x4)
+	FST = byte(0x8)
+)
+
+type Encoder func(in interface{}) []byte
+
+type Decoder func(in []byte) (interface{},int)
+
+func MessageEncoder(codecType byte,in interface{}) []byte {
+	switch codecType {
+	case SEATA:
+		return SeataEncoder(in)
+	default:
+		logging.Logger.Errorf("not support codecType, %s",codecType)
+		return nil
+	}
+}
+
+func MessageDecoder(codecType byte,in []byte) (interface{},int) {
+	switch codecType {
+	case SEATA:
+		return SeataDecoder(in)
+	default:
+		logging.Logger.Errorf("not support codecType, %s",codecType)
+		return nil,0
+	}
+}
+
+
+func SeataEncoder(in interface{}) []byte {
+	var result = make([]byte, 0)
+	msg := in.(protocal.MessageTypeAware)
+	typeCode := msg.GetTypeCode()
+	encoder := getMessageEncoder(typeCode)
+
+	typeC := uint16(typeCode)
+	if encoder != nil {
+		body := encoder(in)
+		result = append(result,[]byte{ byte(typeC >> 8), byte(typeC) }...)
+		result = append(result,body...)
+	}
+	return  result
+}
+
+func SeataDecoder(in []byte) (interface{},int) {
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+	typeCode, _ ,_ := r.ReadInt16()
+
+	decoder := getMessageDecoder(typeCode)
+	if decoder != nil {
+		return decoder(in[2:])
+	}
+	return nil,0
+}
+
+func getMessageEncoder(typeCode int16) Encoder {
+	switch typeCode {
+	case protocal.TypeSeataMerge:
+		return MergedWarpMessageEncoder
+	case protocal.TypeSeataMergeResult:
+		return MergeResultMessageEncoder
+	case protocal.TypeRegClt:
+		return RegisterTMRequestEncoder
+	case protocal.TypeRegCltResult:
+		return RegisterTMResponseEncoder
+	case protocal.TypeRegRm:
+		return RegisterRMRequestEncoder
+	case protocal.TypeRegRmResult:
+		return RegisterRMResponseEncoder
+	case protocal.TypeBranchCommit:
+		return BranchCommitRequestEncoder
+	case protocal.TypeBranchRollback:
+		return BranchRollbackRequestEncoder
+	case protocal.TypeGlobalReport:
+		return GlobalReportRequestEncoder
+	default:
+		var encoder Encoder
+		encoder = getMergeRequestMessageEncoder(typeCode)
+		if encoder != nil {
+			return encoder
+		}
+		encoder = getMergeResponseMessageEncoder(typeCode)
+		if encoder != nil {
+			return encoder
+		}
+		logging.Logger.Errorf("not support typeCode, %d",typeCode)
+		return nil
+	}
+}
+
+func getMergeRequestMessageEncoder(typeCode int16) Encoder {
+	switch typeCode {
+	case protocal.TypeGlobalBegin:
+		return GlobalBeginRequestEncoder
+	case protocal.TypeGlobalCommit:
+		return GlobalCommitRequestEncoder
+	case protocal.TypeGlobalRollback:
+		return GlobalRollbackRequestEncoder
+	case protocal.TypeGlobalStatus:
+		return GlobalStatusRequestEncoder
+	case protocal.TypeGlobalLockQuery:
+		return GlobalLockQueryRequestEncoder
+	case protocal.TypeBranchRegister:
+		return BranchRegisterRequestEncoder
+	case protocal.TypeBranchStatusReport:
+		return BranchReportRequestEncoder
+	case protocal.TypeGlobalReport:
+		return GlobalReportRequestEncoder
+	default:
+		break
+	}
+	return nil
+}
+
+func getMergeResponseMessageEncoder(typeCode int16) Encoder {
+	switch typeCode {
+	case protocal.TypeGlobalBeginResult:
+		return GlobalBeginResponseEncoder
+	case protocal.TypeGlobalCommitResult:
+		return GlobalCommitResponseEncoder
+	case protocal.TypeGlobalRollbackResult:
+		return GlobalRollbackResponseEncoder
+	case protocal.TypeGlobalStatusResult:
+		return GlobalStatusResponseEncoder
+	case protocal.TypeGlobalLockQueryResult:
+		return GlobalLockQueryResponseEncoder
+	case protocal.TypeBranchRegisterResult:
+		return BranchRegisterResponseEncoder
+	case protocal.TypeBranchStatusReportResult:
+		return BranchReportResponseEncoder
+	case protocal.TypeBranchCommitResult:
+		return BranchCommitResponseEncoder
+	case protocal.TypeBranchRollbackResult:
+		return BranchRollbackResponseEncoder
+	case protocal.TypeGlobalReportResult:
+		return GlobalReportResponseEncoder
+	default:
+		break
+	}
+	return nil
+}
+
+
+func getMessageDecoder(typeCode int16) Decoder {
+	switch typeCode {
+	case protocal.TypeSeataMerge:
+		return MergedWarpMessageDecoder
+	case protocal.TypeSeataMergeResult:
+		return MergeResultMessageDecoder
+	case protocal.TypeRegClt:
+		return RegisterTMRequestDecoder
+	case protocal.TypeRegCltResult:
+		return RegisterTMResponseDecoder
+	case protocal.TypeRegRm:
+		return RegisterRMRequestDecoder
+	case protocal.TypeRegRmResult:
+		return RegisterRMResponseDecoder
+	case protocal.TypeBranchCommit:
+		return BranchCommitRequestDecoder
+	case protocal.TypeBranchRollback:
+		return BranchRollbackRequestDecoder
+	case protocal.TypeGlobalReport:
+		return GlobalReportRequestDecoder
+	default:
+		var Decoder Decoder
+		Decoder = getMergeRequestMessageDecoder(typeCode)
+		if Decoder != nil {
+			return Decoder
+		}
+		Decoder = getMergeResponseMessageDecoder(typeCode)
+		if Decoder != nil {
+			return Decoder
+		}
+		logging.Logger.Errorf("not support typeCode, %d",typeCode)
+		return nil
+	}
+}
+
+func getMergeRequestMessageDecoder(typeCode int16) Decoder {
+	switch typeCode {
+	case protocal.TypeGlobalBegin:
+		return GlobalBeginRequestDecoder
+	case protocal.TypeGlobalCommit:
+		return GlobalCommitRequestDecoder
+	case protocal.TypeGlobalRollback:
+		return GlobalRollbackRequestDecoder
+	case protocal.TypeGlobalStatus:
+		return GlobalStatusRequestDecoder
+	case protocal.TypeGlobalLockQuery:
+		return GlobalLockQueryRequestDecoder
+	case protocal.TypeBranchRegister:
+		return BranchRegisterRequestDecoder
+	case protocal.TypeBranchStatusReport:
+		return BranchReportRequestDecoder
+	case protocal.TypeGlobalReport:
+		return GlobalReportRequestDecoder
+	default:
+		break
+	}
+	return nil
+}
+
+func getMergeResponseMessageDecoder(typeCode int16) Decoder {
+	switch typeCode {
+	case protocal.TypeGlobalBeginResult:
+		return GlobalBeginResponseDecoder
+	case protocal.TypeGlobalCommitResult:
+		return GlobalCommitResponseDecoder
+	case protocal.TypeGlobalRollbackResult:
+		return GlobalRollbackResponseDecoder
+	case protocal.TypeGlobalStatusResult:
+		return GlobalStatusResponseDecoder
+	case protocal.TypeGlobalLockQueryResult:
+		return GlobalLockQueryResponseDecoder
+	case protocal.TypeBranchRegisterResult:
+		return BranchRegisterResponseDecoder
+	case protocal.TypeBranchStatusReportResult:
+		return BranchReportResponseDecoder
+	case protocal.TypeBranchCommitResult:
+		return BranchCommitResponseDecoder
+	case protocal.TypeBranchRollbackResult:
+		return BranchRollbackResponseDecoder
+	case protocal.TypeGlobalReportResult:
+		return GlobalReportResponseDecoder
+	default:
+		break
+	}
+	return nil
+}
\ No newline at end of file
diff --git a/protocal/codec/seata_decoder.go b/protocal/codec/seata_decoder.go
new file mode 100644
index 0000000..fbd388c
--- /dev/null
+++ b/protocal/codec/seata_decoder.go
@@ -0,0 +1,773 @@
+package codec
+
+import (
+	"bytes"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/protocal"
+	"vimagination.zapto.org/byteio"
+)
+
+func AbstractResultMessageDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+	 	readN = 0
+	 	totalReadN = 0
+	)
+	msg := protocal.AbstractResultMessage{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+	resultCode, _ := r.ReadByte()
+	msg.ResultCode = protocal.ResultCode(resultCode)
+	totalReadN += 1
+	if msg.ResultCode == protocal.ResultCodeFailed {
+		length16, readN, _ = r.ReadUint16()
+		totalReadN += readN
+		if length16 > 0 {
+			msg.Msg, readN, _ = r.ReadString(int(length16))
+			totalReadN += readN
+		}
+	}
+
+	return msg,totalReadN
+}
+
+func MergedWarpMessageDecoder(in []byte) (interface{},int) {
+	var (
+		size16 int16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	result := protocal.MergedWarpMessage{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	r.ReadInt32()
+	totalReadN += 4
+	size16,readN,_ = r.ReadInt16()
+	totalReadN += readN
+	result.Msgs = make([]protocal.MessageTypeAware,0)
+	for index := 0; index < int(size16); index++ {
+		typeCode,_,_ := r.ReadInt16()
+		totalReadN += 2
+		decoder := getMessageDecoder(typeCode)
+		if decoder != nil {
+			msg,readN := decoder(in[totalReadN:])
+			totalReadN += readN
+			result.Msgs = append(result.Msgs,msg.(protocal.MessageTypeAware))
+		}
+	}
+	return result,totalReadN
+}
+
+func MergeResultMessageDecoder(in []byte) (interface{},int) {
+	var (
+		size16 int16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	result := protocal.MergeResultMessage{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	r.ReadInt32()
+	totalReadN += 4
+	size16,readN,_ = r.ReadInt16()
+	totalReadN += readN
+	result.Msgs = make([]protocal.MessageTypeAware,0)
+
+	for index := 0; index < int(size16); index++ {
+		typeCode,_,_ := r.ReadInt16()
+		totalReadN += 2
+		decoder := getMessageDecoder(typeCode)
+		if decoder != nil {
+			msg,readN := decoder(in[totalReadN:])
+			totalReadN += readN
+			result.Msgs = append(result.Msgs,msg.(protocal.MessageTypeAware))
+		}
+	}
+	return result,totalReadN
+}
+
+func AbstractIdentifyRequestDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.AbstractIdentifyRequest{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Version, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ApplicationId, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.TransactionServiceGroup, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ExtraData = make([]byte,int(length16))
+		readN, _ := r.Read(msg.ExtraData)
+		totalReadN += readN
+	}
+
+	return msg,totalReadN
+}
+
+func AbstractIdentifyResponseDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.AbstractIdentifyResponse{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	identified, _ := r.ReadByte()
+	totalReadN += 1
+	if identified == byte(1){
+		msg.Identified = true
+	} else if identified == byte(0) {
+		msg.Identified = false
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Version, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	return msg,totalReadN
+}
+
+func RegisterRMRequestDecoder(in []byte) (interface{},int) {
+	var (
+		length32 uint32 = 0
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.RegisterRMRequest{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Version, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ApplicationId, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.TransactionServiceGroup, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ExtraData = make([]byte,int(length16))
+		readN, _ := r.Read(msg.ExtraData)
+		totalReadN += readN
+	}
+
+	length32, readN, _ = r.ReadUint32()
+	totalReadN += readN
+	if length32 > 0 {
+		msg.ResourceIds, readN, _ = r.ReadString(int(length32))
+		totalReadN += readN
+	}
+
+	return msg,totalReadN
+}
+
+func RegisterRMResponseDecoder(in []byte) (interface{},int) {
+	resp,totalReadN := AbstractIdentifyResponseDecoder(in)
+	abstractIdentifyResponse := resp.(protocal.AbstractIdentifyResponse)
+	msg := protocal.RegisterRMResponse{AbstractIdentifyResponse:abstractIdentifyResponse}
+	return msg,totalReadN
+}
+
+func RegisterTMRequestDecoder(in []byte) (interface{},int) {
+	req,totalReadN := AbstractIdentifyRequestDecoder(in)
+	abstractIdentifyRequest := req.(protocal.AbstractIdentifyRequest)
+	msg := protocal.RegisterTMRequest{AbstractIdentifyRequest:abstractIdentifyRequest}
+	return msg,totalReadN
+}
+
+func RegisterTMResponseDecoder(in []byte) (interface{},int) {
+	resp,totalReadN := AbstractIdentifyResponseDecoder(in)
+	abstractIdentifyResponse := resp.(protocal.AbstractIdentifyResponse)
+	msg := protocal.RegisterRMResponse{AbstractIdentifyResponse:abstractIdentifyResponse}
+	return msg,totalReadN
+}
+
+func AbstractTransactionResponseDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.AbstractTransactionResponse{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+	resultCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.ResultCode = protocal.ResultCode(resultCode)
+	if msg.ResultCode == protocal.ResultCodeFailed {
+		length16, readN, _ = r.ReadUint16()
+		totalReadN += readN
+		if length16 > 0 {
+			msg.Msg, readN, _ = r.ReadString(int(length16))
+			totalReadN += readN
+		}
+	}
+
+	exceptionCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.TransactionExceptionCode = meta.TransactionExceptionCode(exceptionCode)
+
+	return msg,totalReadN
+}
+
+func AbstractBranchEndRequestDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.AbstractBranchEndRequest{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Xid, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	msg.BranchId, _, _ = r.ReadInt64()
+	totalReadN += 8
+	branchType, _ := r.ReadByte()
+	totalReadN += 1
+	msg.BranchType = meta.BranchType(branchType)
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ResourceId, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ApplicationData = make([]byte,int(length16))
+		readN,_ := r.Read(msg.ApplicationData)
+		totalReadN += readN
+	}
+
+	return msg,totalReadN
+}
+
+func AbstractBranchEndResponseDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.AbstractBranchEndResponse{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+	resultCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.ResultCode = protocal.ResultCode(resultCode)
+	if msg.ResultCode == protocal.ResultCodeFailed {
+		length16, readN, _ = r.ReadUint16()
+		totalReadN += readN
+		if length16 > 0 {
+			msg.Msg, readN, _ = r.ReadString(int(length16))
+			totalReadN += readN
+		}
+	}
+
+	exceptionCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.TransactionExceptionCode = meta.TransactionExceptionCode(exceptionCode)
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Xid, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	msg.BranchId, _, _ = r.ReadInt64()
+	totalReadN += 8
+	branchStatus,_ := r.ReadByte()
+	totalReadN += 1
+	msg.BranchStatus = meta.BranchStatus(branchStatus)
+
+	return msg,totalReadN
+}
+
+func AbstractGlobalEndRequestDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.AbstractGlobalEndRequest{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Xid, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ExtraData = make([]byte,int(length16))
+		readN,_ := r.Read(msg.ExtraData)
+		totalReadN += readN
+	}
+
+	return msg,totalReadN
+}
+
+func AbstractGlobalEndResponseDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.AbstractGlobalEndResponse{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+	resultCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.ResultCode = protocal.ResultCode(resultCode)
+	if msg.ResultCode == protocal.ResultCodeFailed {
+		length16, readN, _ = r.ReadUint16()
+		totalReadN += readN
+		if length16 > 0 {
+			msg.Msg, readN, _ = r.ReadString(int(length16))
+			totalReadN += readN
+		}
+	}
+
+	exceptionCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.TransactionExceptionCode = meta.TransactionExceptionCode(exceptionCode)
+
+	globalStatus,_ := r.ReadByte()
+	totalReadN += 1
+	msg.GlobalStatus = meta.GlobalStatus(globalStatus)
+
+	return msg,totalReadN
+}
+
+func BranchCommitRequestDecoder(in []byte) (interface{},int) {
+	req,totalReadN := AbstractBranchEndRequestDecoder(in)
+	abstractBranchEndRequest := req.(protocal.AbstractBranchEndRequest)
+	msg := protocal.BranchCommitRequest{AbstractBranchEndRequest:abstractBranchEndRequest}
+	return msg,totalReadN
+}
+
+func BranchCommitResponseDecoder(in []byte) (interface{},int) {
+	resp,totalReadN := AbstractBranchEndResponseDecoder(in)
+	abstractBranchEndResponse := resp.(protocal.AbstractBranchEndResponse)
+	msg := protocal.BranchCommitResponse{AbstractBranchEndResponse:abstractBranchEndResponse}
+	return msg,totalReadN
+}
+
+func BranchRegisterRequestDecoder(in []byte) (interface{},int) {
+	var (
+		length32 uint32 = 0
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.BranchRegisterRequest{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Xid, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	branchType, _ := r.ReadByte()
+	totalReadN += 1
+	msg.BranchType = meta.BranchType(branchType)
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ResourceId, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length32, readN, _ = r.ReadUint32()
+	totalReadN += readN
+	if length32 > 0 {
+		msg.LockKey, readN, _ = r.ReadString(int(length32))
+		totalReadN += readN
+	}
+
+	length32, readN, _ = r.ReadUint32()
+	totalReadN += readN
+	if length32 > 0 {
+		msg.ApplicationData = make([]byte,int(length32))
+		readN,_ := r.Read(msg.ApplicationData)
+		totalReadN += readN
+	}
+
+	return msg,totalReadN
+}
+
+func BranchRegisterResponseDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.BranchRegisterResponse{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+	resultCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.ResultCode = protocal.ResultCode(resultCode)
+	if msg.ResultCode == protocal.ResultCodeFailed {
+		length16, readN, _ = r.ReadUint16()
+		totalReadN += readN
+		if length16 > 0 {
+			msg.Msg, readN, _ = r.ReadString(int(length16))
+			totalReadN += readN
+		}
+	}
+
+	exceptionCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.TransactionExceptionCode = meta.TransactionExceptionCode(exceptionCode)
+
+	msg.BranchId, readN, _ = r.ReadInt64()
+	totalReadN += readN
+
+	return msg,totalReadN
+}
+
+func BranchReportRequestDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.BranchReportRequest{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Xid, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	msg.BranchId, _, _ = r.ReadInt64()
+	branchStatus, _ := r.ReadByte()
+	msg.Status = meta.BranchStatus(branchStatus)
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ResourceId, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ApplicationData = make([]byte,int(length16))
+		readN,_ := r.Read(msg.ApplicationData)
+		totalReadN += readN
+	}
+
+	branchType, _ := r.ReadByte()
+	totalReadN += 1
+	msg.BranchType = meta.BranchType(branchType)
+
+	return msg,totalReadN
+}
+
+func BranchReportResponseDecoder(in []byte) (interface{},int) {
+	resp,totalReadN := AbstractTransactionResponseDecoder(in)
+	abstractTransactionResponse := resp.(protocal.AbstractTransactionResponse)
+	msg := protocal.BranchReportResponse{AbstractTransactionResponse: abstractTransactionResponse}
+	return msg,totalReadN
+}
+
+func BranchRollbackRequestDecoder(in []byte) (interface{},int) {
+	req,totalReadN := AbstractBranchEndRequestDecoder(in)
+	abstractBranchEndRequest := req.(protocal.AbstractBranchEndRequest)
+	msg := protocal.BranchRollbackRequest{AbstractBranchEndRequest:abstractBranchEndRequest}
+	return msg,totalReadN
+}
+
+func BranchRollbackResponseDecoder(in []byte) (interface{},int) {
+	resp,totalReadN := AbstractBranchEndResponseDecoder(in)
+	abstractBranchEndResponse := resp.(protocal.AbstractBranchEndResponse)
+	msg := protocal.BranchRollbackResponse{AbstractBranchEndResponse:abstractBranchEndResponse}
+	return msg,totalReadN
+}
+
+func GlobalBeginRequestDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.GlobalBeginRequest{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	timeout, readN, _ := r.ReadInt32()
+	totalReadN += readN
+	msg.Timeout = timeout
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.TransactionName, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	return msg,totalReadN
+}
+
+func GlobalBeginResponseDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.GlobalBeginResponse{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+	resultCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.ResultCode = protocal.ResultCode(resultCode)
+	if msg.ResultCode == protocal.ResultCodeFailed {
+		length16, readN, _ = r.ReadUint16()
+		totalReadN += readN
+		if length16 > 0 {
+			msg.Msg, readN, _ = r.ReadString(int(length16))
+			totalReadN += readN
+		}
+	}
+
+	exceptionCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.TransactionExceptionCode = meta.TransactionExceptionCode(exceptionCode)
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Xid, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ExtraData = make([]byte,int(length16))
+		readN,_ := r.Read(msg.ExtraData)
+		totalReadN += readN
+	}
+
+	return msg,totalReadN
+}
+
+func GlobalCommitRequestDecoder(in []byte) (interface{},int) {
+	req,totalReadN := AbstractGlobalEndRequestDecoder(in)
+	abstractGlobalEndRequest := req.(protocal.AbstractGlobalEndRequest)
+	msg := protocal.GlobalCommitRequest{AbstractGlobalEndRequest:abstractGlobalEndRequest}
+	return msg,totalReadN
+}
+
+func GlobalCommitResponseDecoder(in []byte) (interface{},int) {
+	resp,totalReadN := AbstractGlobalEndResponseDecoder(in)
+	abstractGlobalEndResponse := resp.(protocal.AbstractGlobalEndResponse)
+	msg := protocal.GlobalCommitResponse{AbstractGlobalEndResponse:abstractGlobalEndResponse}
+	return msg,totalReadN
+}
+
+func GlobalLockQueryRequestDecoder(in []byte) (interface{},int) {
+	req,totalReadN := BranchRegisterRequestDecoder(in)
+	branchRegisterRequest := req.(protocal.BranchRegisterRequest)
+	msg := protocal.GlobalLockQueryRequest{BranchRegisterRequest:branchRegisterRequest}
+	return msg,totalReadN
+}
+
+func GlobalLockQueryResponseDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.GlobalLockQueryResponse{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+	resultCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.ResultCode = protocal.ResultCode(resultCode)
+	if msg.ResultCode == protocal.ResultCodeFailed {
+		length16, readN, _ = r.ReadUint16()
+		totalReadN += readN
+		if length16 > 0 {
+			msg.Msg, readN, _ = r.ReadString(int(length16))
+			totalReadN += readN
+		}
+	}
+
+	exceptionCode, _ := r.ReadByte()
+	totalReadN += 1
+	msg.TransactionExceptionCode = meta.TransactionExceptionCode(exceptionCode)
+
+	lockable, readN, _ := r.ReadUint16()
+	totalReadN += readN
+	if lockable == uint16(1) {
+		msg.Lockable = true
+	} else if lockable == uint16(0) {
+		msg.Lockable = false
+	}
+
+	return msg,totalReadN
+}
+
+func GlobalReportRequestDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.GlobalReportRequest{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.Xid, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 {
+		msg.ExtraData = make([]byte,int(length16))
+		readN, _ := r.Read(msg.ExtraData)
+		totalReadN += readN
+	}
+
+	globalStatus,_ := r.ReadByte()
+	totalReadN += 1
+	msg.GlobalStatus = meta.GlobalStatus(globalStatus)
+
+	return msg,totalReadN
+}
+
+func GlobalReportResponseDecoder(in []byte) (interface{},int) {
+	resp,totalReadN := AbstractGlobalEndResponseDecoder(in)
+	abstractGlobalEndResponse := resp.(protocal.AbstractGlobalEndResponse)
+	msg := protocal.GlobalReportResponse{AbstractGlobalEndResponse:abstractGlobalEndResponse}
+	return msg,totalReadN
+}
+
+func GlobalRollbackRequestDecoder(in []byte) (interface{},int) {
+	req,totalReadN := AbstractGlobalEndRequestDecoder(in)
+	abstractGlobalEndRequest := req.(protocal.AbstractGlobalEndRequest)
+	msg := protocal.GlobalRollbackRequest{AbstractGlobalEndRequest:abstractGlobalEndRequest}
+	return msg,totalReadN
+}
+
+func GlobalRollbackResponseDecoder(in []byte) (interface{},int) {
+	resp,totalReadN := AbstractGlobalEndResponseDecoder(in)
+	abstractGlobalEndResponse := resp.(protocal.AbstractGlobalEndResponse)
+	msg := protocal.GlobalRollbackResponse{AbstractGlobalEndResponse:abstractGlobalEndResponse}
+	return msg,totalReadN
+}
+
+func GlobalStatusRequestDecoder(in []byte) (interface{},int) {
+	req,totalReadN := AbstractGlobalEndRequestDecoder(in)
+	abstractGlobalEndRequest := req.(protocal.AbstractGlobalEndRequest)
+	msg := protocal.GlobalStatusRequest{AbstractGlobalEndRequest:abstractGlobalEndRequest}
+	return msg,totalReadN
+}
+
+func GlobalStatusResponseDecoder(in []byte) (interface{},int) {
+	resp,totalReadN := AbstractGlobalEndResponseDecoder(in)
+	abstractGlobalEndResponse := resp.(protocal.AbstractGlobalEndResponse)
+	msg := protocal.GlobalStatusResponse{AbstractGlobalEndResponse:abstractGlobalEndResponse}
+	return msg,totalReadN
+}
+
+func UndoLogDeleteRequestDecoder(in []byte) (interface{},int) {
+	var (
+		length16 uint16 = 0
+		readN = 0
+		totalReadN = 0
+	)
+	msg := protocal.UndoLogDeleteRequest{}
+
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(in)}
+	branchType, _ := r.ReadByte()
+	totalReadN += 1
+	msg.BranchType = meta.BranchType(branchType)
+
+	length16, readN, _ = r.ReadUint16()
+	totalReadN += readN
+	if length16 > 0 { 
+		msg.ResourceId, readN, _ = r.ReadString(int(length16))
+		totalReadN += readN
+	}
+
+	msg.SaveDays, readN, _ = r.ReadInt16()
+	totalReadN += readN
+
+	return msg,totalReadN
+}
\ No newline at end of file
diff --git a/protocal/codec/seata_encoder.go b/protocal/codec/seata_encoder.go
new file mode 100644
index 0000000..1163ec0
--- /dev/null
+++ b/protocal/codec/seata_encoder.go
@@ -0,0 +1,560 @@
+package codec
+
+import (
+	"bytes"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/protocal"
+	"vimagination.zapto.org/byteio"
+)
+
+func AbstractResultMessageEncoder(in interface{}) []byte {
+	var (
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	message := in.(protocal.AbstractResultMessage)
+
+	w.WriteByte(byte(message.ResultCode))
+	if message.ResultCode == protocal.ResultCodeFailed {
+		var msg string
+		if message.Msg != "" {
+			if len(message.Msg) > 128 {
+				msg = message.Msg[:128]
+			} else {
+				msg = message.Msg
+			}
+			// 暂时不考虑 message.Msg 包含中文的情况,这样字符串的长度就是 byte 数组的长度
+
+			w.WriteInt16(int16(len(msg)))
+			w.WriteString(msg)
+		} else {
+			w.WriteInt16(zero16)
+		}
+	}
+
+
+	return b.Bytes()
+}
+
+func MergedWarpMessageEncoder(in interface{}) []byte {
+	var (
+		b bytes.Buffer
+		result = make([]byte,0)
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	req,_ := in.(protocal.MergedWarpMessage)
+	w.WriteInt16(int16(len(req.Msgs)))
+
+	for _,msg := range req.Msgs {
+		encoder := getMessageEncoder(msg.GetTypeCode())
+		if encoder != nil {
+			data := encoder(msg)
+			w.WriteInt16(msg.GetTypeCode())
+			w.Write(data)
+		}
+	}
+
+	size := uint32(b.Len())
+	result = append(result,[]byte{ byte(size>>24),byte(size>>16),byte(size>>8),byte(size) }...)
+	result = append(result, b.Bytes()...)
+
+	if len(req.Msgs)>20 {
+		logging.Logger.Debugf("msg in one packet: %s ,buffer size: %s", len(req.Msgs),size)
+	}
+	return result
+}
+
+func MergeResultMessageEncoder(in interface{}) []byte {
+	var (
+		b bytes.Buffer
+		result = make([]byte,0)
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	req,_ := in.(protocal.MergeResultMessage)
+	w.WriteInt16(int16(len(req.Msgs)))
+
+	for _,msg := range req.Msgs {
+		encoder := getMessageEncoder(msg.GetTypeCode())
+		if encoder != nil {
+			data := encoder(msg)
+			w.WriteInt16(msg.GetTypeCode())
+			w.Write(data)
+		}
+	}
+
+	size := uint32(b.Len())
+	result = append(result,[]byte{ byte(size>>24),byte(size>>16),byte(size>>8),byte(size) }...)
+	result = append(result, b.Bytes()...)
+
+	if len(req.Msgs)>20 {
+		logging.Logger.Debugf("msg in one packet: %s ,buffer size: %s", len(req.Msgs),size)
+	}
+	return result
+}
+
+func AbstractIdentifyRequestEncoder(in interface{}) []byte {
+	var (
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	req := in.(protocal.AbstractIdentifyRequest)
+
+	if req.Version != "" {
+		w.WriteInt16(int16(len(req.Version)))
+		w.WriteString(req.Version)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if req.ApplicationId != "" {
+		w.WriteInt16(int16(len(req.ApplicationId)))
+		w.WriteString(req.ApplicationId)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if req.TransactionServiceGroup != "" {
+		w.WriteInt16(int16(len(req.TransactionServiceGroup)))
+		w.WriteString(req.TransactionServiceGroup)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if req.ExtraData != nil {
+		w.WriteUint16(uint16(len(req.ExtraData)))
+		w.Write(req.ExtraData)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	return b.Bytes()
+}
+
+func AbstractIdentifyResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.AbstractIdentifyResponse)
+
+	var (
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	if resp.Identified {
+		w.WriteByte(byte(1))
+	} else {
+		w.WriteByte(byte(0))
+	}
+
+	if resp.Version != "" {
+		w.WriteInt16(int16(len(resp.Version)))
+		w.WriteString(resp.Version)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	return b.Bytes()
+}
+
+func RegisterRMRequestEncoder(in interface{}) []byte {
+	req := in.(protocal.RegisterRMRequest)
+	data := AbstractIdentifyRequestEncoder(req.AbstractIdentifyRequest)
+
+	var (
+		zero32 int32 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	if req.ResourceIds != "" {
+		w.WriteInt32(int32(len(req.ResourceIds)))
+		w.WriteString(req.ResourceIds)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	result := append(data,b.Bytes()...)
+	return result
+}
+
+func RegisterRMResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.RegisterRMResponse)
+	return AbstractIdentifyResponseEncoder(resp.AbstractIdentifyResponse)
+}
+
+func RegisterTMRequestEncoder(in interface{}) []byte {
+	req := in.(protocal.RegisterTMRequest)
+	return AbstractIdentifyRequestEncoder(req.AbstractIdentifyRequest)
+}
+
+func RegisterTMResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.RegisterTMResponse)
+	return AbstractIdentifyResponseEncoder(resp.AbstractIdentifyResponse)
+}
+
+func AbstractTransactionResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.AbstractTransactionResponse)
+	data := AbstractResultMessageEncoder(resp.AbstractResultMessage)
+
+	result := append(data,byte(resp.TransactionExceptionCode))
+
+	return result
+}
+
+func AbstractBranchEndRequestEncoder(in interface{}) []byte {
+	var (
+		zero32 int32 = 0
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	req,_ := in.(protocal.AbstractBranchEndRequest)
+
+	if req.Xid != "" {
+		w.WriteInt16(int16(len(req.Xid)))
+		w.WriteString(req.Xid)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	w.WriteInt64(req.BranchId)
+	w.WriteByte(byte(req.BranchType))
+
+	if req.ResourceId != "" {
+		w.WriteInt16(int16(len(req.ResourceId)))
+		w.WriteString(req.ResourceId)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if req.ApplicationData != nil {
+		w.WriteUint32(uint32(len(req.ApplicationData)))
+		w.Write(req.ApplicationData)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	return b.Bytes()
+}
+
+func AbstractBranchEndResponseEncoder(in interface{}) []byte {
+	resp,_ := in.(protocal.AbstractBranchEndResponse)
+	data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse)
+
+	var (
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	if resp.Xid != "" {
+		w.WriteInt16(int16(len(resp.Xid)))
+		w.WriteString(resp.Xid)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	w.WriteInt64(resp.BranchId)
+	w.WriteByte(byte(resp.BranchStatus))
+
+	result := append(data,b.Bytes()...)
+
+	return result
+}
+
+func AbstractGlobalEndRequestEncoder(in interface{}) []byte {
+	var (
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	req,_ := in.(protocal.AbstractGlobalEndRequest)
+
+	if req.Xid != "" {
+		w.WriteInt16(int16(len(req.Xid)))
+		w.WriteString(req.Xid)
+	} else {
+		w.WriteInt16(zero16)
+	}
+	if req.ExtraData != nil {
+		w.WriteUint16(uint16(len(req.ExtraData)))
+		w.Write(req.ExtraData)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	return b.Bytes()
+}
+
+func AbstractGlobalEndResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.AbstractGlobalEndResponse)
+	data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse)
+
+	result := append(data,byte(resp.GlobalStatus))
+
+	return result
+}
+
+func BranchCommitRequestEncoder(in interface{}) []byte {
+	req := in.(protocal.BranchCommitRequest)
+	return AbstractBranchEndRequestEncoder(req.AbstractBranchEndRequest)
+}
+
+func BranchCommitResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.BranchCommitResponse)
+	return AbstractBranchEndResponseEncoder(resp.AbstractBranchEndResponse)
+}
+
+func BranchRegisterRequestEncoder(in interface{}) []byte {
+	var (
+		zero32 int32 = 0
+		zero16 int16 = 0
+		b bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	req,_ := in.(protocal.BranchRegisterRequest)
+
+	if req.Xid != "" {
+		w.WriteInt16(int16(len(req.Xid)))
+		w.WriteString(req.Xid)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	w.WriteByte(byte(req.BranchType))
+
+	if req.ResourceId != "" {
+		w.WriteInt16(int16(len(req.ResourceId)))
+		w.WriteString(req.ResourceId)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if req.LockKey != "" {
+		w.WriteInt32(int32(len(req.LockKey)))
+		w.WriteString(req.LockKey)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	if req.ApplicationData != nil {
+		w.WriteUint32(uint32(len(req.ApplicationData)))
+		w.Write(req.ApplicationData)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	return b.Bytes()
+}
+
+func BranchRegisterResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.BranchRegisterResponse)
+	data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse)
+
+	c := uint64(resp.BranchId)
+	branchIdBytes := []byte{
+		byte(c >> 56),
+		byte(c >> 48),
+		byte(c >> 40),
+		byte(c >> 32),
+		byte(c >> 24),
+		byte(c >> 16),
+		byte(c >> 8),
+		byte(c),
+	}
+	result := append(data,branchIdBytes...)
+
+	return result
+}
+
+func BranchReportRequestEncoder(in interface{}) []byte {
+	var (
+		zero32 int32 = 0
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	req,_ := in.(protocal.BranchReportRequest)
+
+	if req.Xid != "" {
+		w.WriteInt16(int16(len(req.Xid)))
+		w.WriteString(req.Xid)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	w.WriteInt64(req.BranchId)
+	w.WriteByte(byte(req.Status))
+
+	if req.ResourceId != "" {
+		w.WriteInt16(int16(len(req.ResourceId)))
+		w.WriteString(req.ResourceId)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if req.ApplicationData != nil {
+		w.WriteUint32(uint32(len(req.ApplicationData)))
+		w.Write(req.ApplicationData)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	w.WriteByte(byte(req.BranchType))
+
+	return b.Bytes()
+}
+
+func BranchReportResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.BranchReportResponse)
+	return AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse)
+}
+
+func BranchRollbackRequestEncoder(in interface{}) []byte {
+	req := in.(protocal.BranchRollbackRequest)
+	return AbstractBranchEndRequestEncoder(req.AbstractBranchEndRequest)
+}
+
+func BranchRollbackResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.BranchRollbackResponse)
+	return AbstractBranchEndResponseEncoder(resp.AbstractBranchEndResponse)
+}
+
+func GlobalBeginRequestEncoder(in interface{}) []byte {
+	var (
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	req,_ := in.(protocal.GlobalBeginRequest)
+
+	w.WriteInt32(req.Timeout)
+	if req.TransactionName != "" {
+		w.WriteInt16(int16(len(req.TransactionName)))
+		w.WriteString(req.TransactionName)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	return b.Bytes()
+}
+
+func GlobalBeginResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.GlobalBeginResponse)
+	data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse)
+
+	var (
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	if resp.Xid != "" {
+		w.WriteInt16(int16(len(resp.Xid)))
+		w.WriteString(resp.Xid)
+	} else {
+		w.WriteInt16(zero16)
+	}
+	if resp.ExtraData != nil {
+		w.WriteUint16(uint16(len(resp.ExtraData)))
+		w.Write(resp.ExtraData)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	result := append(data,b.Bytes()...)
+
+	return result
+}
+
+func GlobalCommitRequestEncoder(in interface{}) []byte {
+	req := in.(protocal.GlobalCommitRequest)
+	return AbstractGlobalEndRequestEncoder(req.AbstractGlobalEndRequest)
+}
+
+func GlobalCommitResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.GlobalCommitResponse)
+	return AbstractGlobalEndResponseEncoder(resp.AbstractGlobalEndResponse)
+}
+
+func GlobalLockQueryRequestEncoder(in interface{}) []byte {
+	return BranchRegisterRequestEncoder(in)
+}
+
+func GlobalLockQueryResponseEncoder(in interface{}) []byte {
+	resp,_ := in.(protocal.GlobalLockQueryResponse)
+	data := AbstractTransactionResponseEncoder(resp.AbstractTransactionResponse)
+
+	var result []byte
+	if resp.Lockable {
+		result = append(data,byte(0),byte(1))
+	} else {
+		result = append(data,byte(0),byte(0))
+	}
+
+	return result
+}
+
+func GlobalReportRequestEncoder(in interface{}) []byte {
+	req,_ := in.(protocal.GlobalReportRequest)
+	data := AbstractGlobalEndRequestEncoder(req.AbstractGlobalEndRequest)
+
+	result := append(data,byte(req.GlobalStatus))
+	return result
+}
+
+func GlobalReportResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.GlobalReportResponse)
+	return AbstractGlobalEndResponseEncoder(resp.AbstractGlobalEndResponse)
+}
+
+func GlobalRollbackRequestEncoder(in interface{}) []byte {
+	req := in.(protocal.GlobalRollbackRequest)
+	return AbstractGlobalEndRequestEncoder(req.AbstractGlobalEndRequest)
+}
+
+func GlobalRollbackResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.GlobalRollbackResponse)
+	return AbstractGlobalEndResponseEncoder(resp.AbstractGlobalEndResponse)
+}
+
+func GlobalStatusRequestEncoder(in interface{}) []byte {
+	req := in.(protocal.GlobalStatusRequest)
+	return AbstractGlobalEndRequestEncoder(req.AbstractGlobalEndRequest)
+}
+
+func GlobalStatusResponseEncoder(in interface{}) []byte {
+	resp := in.(protocal.GlobalStatusResponse)
+	return AbstractGlobalEndResponseEncoder(resp.AbstractGlobalEndResponse)
+}
+
+func UndoLogDeleteRequestEncoder(in interface{}) []byte {
+	var (
+		zero16 int16 = 0
+		b      bytes.Buffer
+	)
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	req,_ := in.(protocal.UndoLogDeleteRequest)
+
+	w.WriteByte(byte(req.BranchType))
+	if req.ResourceId != "" {
+		w.WriteInt16(int16(len(req.ResourceId)))
+		w.WriteString(req.ResourceId)
+	} else {
+		w.WriteInt16(zero16)
+	}
+	w.WriteInt16(req.SaveDays)
+
+	return b.Bytes()
+}
\ No newline at end of file
diff --git a/protocal/constant.go b/protocal/constant.go
new file mode 100644
index 0000000..c170cc3
--- /dev/null
+++ b/protocal/constant.go
@@ -0,0 +1,13 @@
+package protocal
+
+var MAGIC_CODE_BYTES = [2]byte{ 0xda, 0xda }
+const (
+	VERSION = 1
+	MAX_FRAME_LENGTH = 8 * 1024 * 1024
+	V1_HEAD_LENGTH = 16
+	MSGTYPE_RESQUEST = 0
+	MSGTYPE_RESPONSE = 1
+	MSGTYPE_RESQUEST_ONEWAY = 2
+	MSGTYPE_HEARTBEAT_REQUEST = 3
+	MSGTYPE_HEARTBEAT_RESPONSE = 4
+)
diff --git a/protocal/heart_beat_message.go b/protocal/heart_beat_message.go
new file mode 100644
index 0000000..a7acfc7
--- /dev/null
+++ b/protocal/heart_beat_message.go
@@ -0,0 +1,16 @@
+package protocal
+
+type HeartBeatMessage struct {
+	Ping bool
+}
+
+var HeartBeatMessagePing = HeartBeatMessage{true}
+var HeartBeatMessagePong = HeartBeatMessage{false}
+
+func (msg HeartBeatMessage) ToString () string {
+	if msg.Ping {
+		return "services ping"
+	} else {
+		return "services pong"
+	}
+}
\ No newline at end of file
diff --git a/protocal/identify.go b/protocal/identify.go
new file mode 100644
index 0000000..3c05aa8
--- /dev/null
+++ b/protocal/identify.go
@@ -0,0 +1,26 @@
+package protocal
+
+type AbstractResultMessage struct {
+	ResultCode ResultCode
+	Msg string
+}
+
+type AbstractIdentifyRequest struct {
+	Version string
+
+	ApplicationId string
+
+	TransactionServiceGroup string
+
+	ExtraData []byte
+}
+
+type AbstractIdentifyResponse struct {
+	AbstractResultMessage
+
+	Version string
+
+	ExtraData []byte
+
+	Identified bool
+}
\ No newline at end of file
diff --git a/protocal/merged_message.go b/protocal/merged_message.go
new file mode 100644
index 0000000..ec16a92
--- /dev/null
+++ b/protocal/merged_message.go
@@ -0,0 +1,17 @@
+package protocal
+
+type MergedWarpMessage struct {
+	Msgs []MessageTypeAware
+	MsgIds []int32
+}
+
+func (req MergedWarpMessage) GetTypeCode() int16 {
+	return TypeSeataMerge
+}
+type MergeResultMessage struct {
+	Msgs []MessageTypeAware
+}
+
+func (resp MergeResultMessage) GetTypeCode() int16 {
+	return TypeSeataMergeResult
+}
\ No newline at end of file
diff --git a/protocal/message_type.go b/protocal/message_type.go
new file mode 100644
index 0000000..733d2d0
--- /dev/null
+++ b/protocal/message_type.go
@@ -0,0 +1,117 @@
+package protocal
+
+type MessageType int16
+
+const (
+	/**
+	 * The constant TYPE_GLOBAL_BEGIN.
+	 */
+	 TypeGlobalBegin = 1
+	/**
+	 * The constant TYPE_GLOBAL_BEGIN_RESULT.
+	 */
+	 TypeGlobalBeginResult = 2
+	/**
+	 * The constant TYPE_GLOBAL_COMMIT.
+	 */
+	 TypeGlobalCommit = 7
+	/**
+	 * The constant TYPE_GLOBAL_COMMIT_RESULT.
+	 */
+	 TypeGlobalCommitResult = 8
+	/**
+	 * The constant TYPE_GLOBAL_ROLLBACK.
+	 */
+	 TypeGlobalRollback = 9
+	/**
+	 * The constant TYPE_GLOBAL_ROLLBACK_RESULT.
+	 */
+	 TypeGlobalRollbackResult = 10
+	/**
+	 * The constant TYPE_GLOBAL_STATUS.
+	 */
+	 TypeGlobalStatus = 15
+	/**
+	 * The constant TYPE_GLOBAL_STATUS_RESULT.
+	 */
+	 TypeGlobalStatusResult = 16
+	/**
+	 * The constant TYPE_GLOBAL_REPORT.
+	 */
+	 TypeGlobalReport = 17
+	/**
+	 * The constant TYPE_GLOBAL_REPORT_RESULT.
+	 */
+	 TypeGlobalReportResult = 18
+	/**
+	 * The constant TYPE_GLOBAL_LOCK_QUERY.
+	 */
+	 TypeGlobalLockQuery = 21
+	/**
+	 * The constant TYPE_GLOBAL_LOCK_QUERY_RESULT.
+	 */
+	 TypeGlobalLockQueryResult = 22
+
+	/**
+	 * The constant TYPE_BRANCH_COMMIT.
+	 */
+	 TypeBranchCommit = 3
+	/**
+	 * The constant TYPE_BRANCH_COMMIT_RESULT.
+	 */
+	 TypeBranchCommitResult = 4
+	/**
+	 * The constant TYPE_BRANCH_ROLLBACK.
+	 */
+	 TypeBranchRollback = 5
+	/**
+	 * The constant TYPE_BRANCH_ROLLBACK_RESULT.
+	 */
+	 TypeBranchRollbackResult = 6
+	/**
+	 * The constant TYPE_BRANCH_REGISTER.
+	 */
+	 TypeBranchRegister = 11
+	/**
+	 * The constant TYPE_BRANCH_REGISTER_RESULT.
+	 */
+	 TypeBranchRegisterResult = 12
+	/**
+	 * The constant TYPE_BRANCH_STATUS_REPORT.
+	 */
+	 TypeBranchStatusReport = 13
+	/**
+	 * The constant TYPE_BRANCH_STATUS_REPORT_RESULT.
+	 */
+	 TypeBranchStatusReportResult = 14
+
+	/**
+	 * The constant TYPE_SEATA_MERGE.
+	 */
+	 TypeSeataMerge = 59
+	/**
+	 * The constant TYPE_SEATA_MERGE_RESULT.
+	 */
+	 TypeSeataMergeResult = 60
+
+	/**
+	 * The constant TYPE_REG_CLT.
+	 */
+	 TypeRegClt = 101
+	/**
+	 * The constant TYPE_REG_CLT_RESULT.
+	 */
+	 TypeRegCltResult = 102
+	/**
+	 * The constant TYPE_REG_RM.
+	 */
+	 TypeRegRm = 103
+	/**
+	 * The constant TYPE_REG_RM_RESULT.
+	 */
+	 TypeRegRmResult = 104
+	/**
+	 * The constant TYPE_RM_DELETE_UNDOLOG.
+	 */
+	 TypeRmDeleteUndolog = 111
+)
diff --git a/protocal/message_type_aware.go b/protocal/message_type_aware.go
new file mode 100644
index 0000000..8bdcd7f
--- /dev/null
+++ b/protocal/message_type_aware.go
@@ -0,0 +1,5 @@
+package protocal
+
+type MessageTypeAware interface {
+	GetTypeCode() int16
+}
diff --git a/protocal/result_code.go b/protocal/result_code.go
new file mode 100644
index 0000000..bc84081
--- /dev/null
+++ b/protocal/result_code.go
@@ -0,0 +1,18 @@
+package protocal
+
+type ResultCode byte
+
+const (
+
+	/**
+	 * ResultCodeFailed result code.
+	 */
+	// ResultCodeFailed
+	ResultCodeFailed ResultCode = iota
+
+	/**
+	 * Success result code.
+	 */
+	// Success
+	ResultCodeSuccess
+)
diff --git a/protocal/rm.go b/protocal/rm.go
new file mode 100644
index 0000000..62c3e2c
--- /dev/null
+++ b/protocal/rm.go
@@ -0,0 +1,18 @@
+package protocal
+
+type RegisterRMRequest struct {
+	AbstractIdentifyRequest
+	ResourceIds string
+}
+
+func (req RegisterRMRequest) GetTypeCode() int16 {
+	return TypeRegRm
+}
+
+type RegisterRMResponse struct {
+	AbstractIdentifyResponse
+}
+
+func (resp RegisterRMResponse) GetTypeCode() int16 {
+	return TypeRegRmResult
+}
\ No newline at end of file
diff --git a/protocal/rpc_message.go b/protocal/rpc_message.go
new file mode 100644
index 0000000..eb70b86
--- /dev/null
+++ b/protocal/rpc_message.go
@@ -0,0 +1,10 @@
+package protocal
+
+type RpcMessage struct {
+	Id int32
+	MessageType byte
+	Codec byte
+	Compressor byte
+	HeadMap map[string]string
+	Body interface{}
+}
diff --git a/protocal/tm.go b/protocal/tm.go
new file mode 100644
index 0000000..f962128
--- /dev/null
+++ b/protocal/tm.go
@@ -0,0 +1,17 @@
+package protocal
+
+type RegisterTMRequest struct {
+	AbstractIdentifyRequest
+}
+
+func (req RegisterTMRequest) GetTypeCode() int16 {
+	return TypeRegClt
+}
+
+type RegisterTMResponse struct {
+	AbstractIdentifyResponse
+}
+
+func (resp RegisterTMResponse) GetTypeCode() int16 {
+	return TypeRegCltResult
+}
\ No newline at end of file
diff --git a/protocal/transaction.go b/protocal/transaction.go
new file mode 100644
index 0000000..1624b5a
--- /dev/null
+++ b/protocal/transaction.go
@@ -0,0 +1,227 @@
+package protocal
+
+import (
+	"github.com/dk-lockdown/seata-golang/meta"
+)
+
+type AbstractTransactionResponse struct {
+	AbstractResultMessage
+	TransactionExceptionCode meta.TransactionExceptionCode
+}
+
+type AbstractBranchEndRequest struct {
+	Xid             string
+	BranchId        int64
+	BranchType      meta.BranchType
+	ResourceId      string
+	ApplicationData []byte
+}
+
+type AbstractBranchEndResponse struct {
+	AbstractTransactionResponse
+
+	Xid          string
+	BranchId     int64
+	BranchStatus meta.BranchStatus
+}
+
+type AbstractGlobalEndRequest struct {
+	Xid string
+	ExtraData []byte
+}
+
+
+type AbstractGlobalEndResponse struct {
+	AbstractTransactionResponse
+
+	GlobalStatus meta.GlobalStatus
+}
+
+type BranchRegisterRequest struct {
+	Xid             string
+	BranchType      meta.BranchType
+	ResourceId      string
+	LockKey         string
+	ApplicationData []byte
+}
+
+func (req BranchRegisterRequest) GetTypeCode() int16 {
+	return TypeBranchRegister
+}
+
+type BranchRegisterResponse struct {
+	AbstractTransactionResponse
+
+	BranchId int64
+}
+
+func (resp BranchRegisterResponse) GetTypeCode() int16 {
+	return TypeBranchRegisterResult
+}
+
+type BranchReportRequest struct {
+	Xid 			string
+	BranchId        int64
+	ResourceId      string
+	Status			meta.BranchStatus
+	ApplicationData []byte
+	BranchType      meta.BranchType
+}
+
+func (req BranchReportRequest) GetTypeCode() int16 {
+	return TypeBranchStatusReport
+}
+
+type BranchReportResponse struct {
+	AbstractTransactionResponse
+}
+
+func (resp BranchReportResponse) GetTypeCode() int16 {
+	return TypeBranchStatusReportResult
+}
+
+type BranchCommitRequest struct {
+	AbstractBranchEndRequest
+}
+
+func (req BranchCommitRequest) GetTypeCode() int16 {
+	return TypeBranchCommit
+}
+
+type BranchCommitResponse struct {
+	AbstractBranchEndResponse
+}
+
+func (resp BranchCommitResponse) GetTypeCode() int16 {
+	return TypeBranchCommitResult
+}
+
+type BranchRollbackRequest struct {
+	AbstractBranchEndRequest
+}
+
+func (req BranchRollbackRequest) GetTypeCode() int16 {
+	return TypeBranchRollback
+}
+
+type BranchRollbackResponse struct {
+	AbstractBranchEndResponse
+}
+
+func (resp BranchRollbackResponse) GetTypeCode() int16 {
+	return TypeGlobalRollbackResult
+}
+
+type GlobalBeginRequest struct {
+	Timeout int32
+	TransactionName string
+}
+
+func (req GlobalBeginRequest) GetTypeCode() int16 {
+	return TypeGlobalBegin
+}
+
+type GlobalBeginResponse struct {
+	AbstractTransactionResponse
+
+	Xid string
+	ExtraData []byte
+}
+
+func (resp GlobalBeginResponse) GetTypeCode() int16 {
+	return TypeGlobalBeginResult
+}
+
+type GlobalStatusRequest struct {
+	AbstractGlobalEndRequest
+}
+
+func (req GlobalStatusRequest) GetTypeCode() int16 {
+	return TypeGlobalStatus
+}
+
+type GlobalStatusResponse struct {
+	AbstractGlobalEndResponse
+}
+
+func (resp GlobalStatusResponse) GetTypeCode() int16 {
+	return TypeGlobalStatusResult
+}
+
+type GlobalLockQueryRequest struct {
+	BranchRegisterRequest
+}
+
+func (req GlobalLockQueryRequest) GetTypeCode() int16 {
+	return TypeGlobalLockQuery
+}
+
+type GlobalLockQueryResponse struct {
+	AbstractTransactionResponse
+
+	Lockable bool
+}
+
+func (resp GlobalLockQueryResponse) GetTypeCode() int16 {
+	return TypeGlobalLockQueryResult
+}
+
+type GlobalReportRequest struct {
+	AbstractGlobalEndRequest
+
+	GlobalStatus meta.GlobalStatus
+}
+
+func (req GlobalReportRequest) GetTypeCode() int16 {
+	return TypeGlobalStatus
+}
+
+type GlobalReportResponse struct {
+	AbstractGlobalEndResponse
+}
+
+func (resp GlobalReportResponse) GetTypeCode() int16 {
+	return TypeGlobalStatusResult
+}
+
+type GlobalCommitRequest struct {
+	AbstractGlobalEndRequest
+}
+
+func (req GlobalCommitRequest) GetTypeCode() int16 {
+	return TypeGlobalCommit
+}
+
+type GlobalCommitResponse struct {
+	AbstractGlobalEndResponse
+}
+
+func (resp GlobalCommitResponse) GetTypeCode() int16 {
+	return TypeGlobalCommitResult
+}
+
+type GlobalRollbackRequest struct {
+	AbstractGlobalEndRequest
+}
+
+func (req GlobalRollbackRequest) GetTypeCode() int16 {
+	return TypeGlobalRollback
+}
+
+type GlobalRollbackResponse struct {
+	AbstractGlobalEndResponse
+}
+
+func (resp GlobalRollbackResponse) GetTypeCode() int16 {
+	return TypeGlobalRollbackResult
+}
+
+type UndoLogDeleteRequest struct {
+	ResourceId string
+	SaveDays int16
+	BranchType meta.BranchType
+}
+
+func (req UndoLogDeleteRequest) GetTypeCode() int16 {
+	return TypeRmDeleteUndolog
+}
\ No newline at end of file
diff --git a/rm/resource_manager.go b/rm/resource_manager.go
new file mode 100644
index 0000000..bcf3493
--- /dev/null
+++ b/rm/resource_manager.go
@@ -0,0 +1,109 @@
+package rm
+
+import (
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/model"
+)
+
+type IResourceManagerInbound interface {
+	/**
+	 * Commit a branch transaction.
+	 *
+	 * @param branchType      the branch type
+	 * @param xid             Transaction id.
+	 * @param branchId        Branch id.
+	 * @param resourceId      Resource id.
+	 * @param applicationData Application data bind with this branch.
+	 * @return Status of the branch after committing.
+	 * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
+	 *                              out.
+	 */
+	BranchCommit(branchType meta.BranchType, xid string, branchId int64, resourceId string, applicationData []byte) (meta.BranchStatus, error)
+
+	/**
+	 * Rollback a branch transaction.
+	 *
+	 * @param branchType      the branch type
+	 * @param xid             Transaction id.
+	 * @param branchId        Branch id.
+	 * @param resourceId      Resource id.
+	 * @param applicationData Application data bind with this branch.
+	 * @return Status of the branch after rollbacking.
+	 * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
+	 *                              out.
+	 */
+	BranchRollback(branchType meta.BranchType, xid string, branchId int64, resourceId string, applicationData []byte) (meta.BranchStatus, error)
+}
+
+type IResourceManagerOutbound interface {
+	/**
+	 * Branch register long.
+	 *
+	 * @param branchType the branch type
+	 * @param resourceId the resource id
+	 * @param clientId   the client id
+	 * @param xid        the xid
+	 * @param applicationData the context
+	 * @param lockKeys   the lock keys
+	 * @return the long
+	 * @throws TransactionException the transaction exception
+	 */
+	BranchRegister(branchType meta.BranchType, resourceId string, clientId string, xid string, applicationData []byte, lockKeys string) (int64, error)
+
+	/**
+	 * Branch report.
+	 *
+	 * @param branchType      the branch type
+	 * @param xid             the xid
+	 * @param branchId        the branch id
+	 * @param status          the status
+	 * @param applicationData the application data
+	 * @throws TransactionException the transaction exception
+	 */
+	BranchReport(branchType meta.BranchType, xid string, branchId int64, status meta.BranchStatus, applicationData []byte) error
+
+	/**
+	 * Lock query boolean.
+	 *
+	 * @param branchType the branch type
+	 * @param resourceId the resource id
+	 * @param xid        the xid
+	 * @param lockKeys   the lock keys
+	 * @return the boolean
+	 * @throws TransactionException the transaction exception
+	 */
+	LockQuery(branchType meta.BranchType, resourceId string, xid string, lockKeys string) (bool, error)
+}
+
+type IResourceManager interface {
+	IResourceManagerInbound
+	IResourceManagerOutbound
+
+	/**
+	 * Register a Resource to be managed by Resource Manager.
+	 *
+	 * @param resource The resource to be managed.
+	 */
+	registerResource(resource model.IResource)
+
+	/**
+	 * Unregister a Resource from the Resource Manager.
+	 *
+	 * @param resource The resource to be removed.
+	 */
+	unregisterResource(resource model.IResource)
+
+	/**
+	 * Get all resources managed by this manager.
+	 *
+	 * @return resourceId -> Resource Map
+	 */
+	getManagedResources() map[string]model.IResource
+
+	/**
+	 * Get the BranchType.
+	 *
+	 * @return The BranchType of ResourceManager.
+	 */
+	getBranchType() meta.BranchType
+}
\ No newline at end of file
diff --git a/tc/app/cmd/main.go b/tc/app/cmd/main.go
new file mode 100644
index 0000000..df813cc
--- /dev/null
+++ b/tc/app/cmd/main.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+	"os"
+	"github.com/dk-lockdown/seata-golang/tc/config"
+	"github.com/dk-lockdown/seata-golang/tc/server"
+)
+
+const (
+	APP_CONF_FILE     = "APP_CONF_FILE"
+)
+
+func main() {
+	confFile := os.Getenv(APP_CONF_FILE)
+	config.InitConf(confFile)
+	server.SetServerGrpool()
+	srv := server.NewServer()
+	conf := config.GetServerConfig()
+	srv.Start(conf.Host+":"+conf.Port)
+}
diff --git a/tc/app/profiles/dev/config.yml b/tc/app/profiles/dev/config.yml
new file mode 100644
index 0000000..f449844
--- /dev/null
+++ b/tc/app/profiles/dev/config.yml
@@ -0,0 +1,28 @@
+host: "127.0.0.1"
+port: "8091"
+timeout_retry_period: "1s"
+rollbacking_retry_period: "1s"
+committing_retry_period: "1s"
+aync_committing_retry_period: "1s"
+log_delete_period: "24h"
+getty_config:
+  session_timeout : "20s"
+  session_number : 700
+  getty_session_param:
+    compress_encoding : false
+    tcp_no_delay : true
+    tcp_keep_alive : true
+    keep_alive_period : "120s"
+    tcp_r_buf_size : 262144
+    tcp_w_buf_size : 524288
+    pkg_rq_size : 1024
+    pkg_wq_size : 512
+    tcp_read_timeout : "1s"
+    tcp_write_timeout : "5s"
+    wait_timeout : "1s"
+    max_msg_len : 4096
+    session_name : "seata-server"
+
+store_config:
+  max_global_session_size: 512
+  max_branch_session_size: 16384
\ No newline at end of file
diff --git a/tc/config/getty_config.go b/tc/config/getty_config.go
new file mode 100644
index 0000000..015c026
--- /dev/null
+++ b/tc/config/getty_config.go
@@ -0,0 +1,38 @@
+package config
+
+import "time"
+
+type GettySessionParam struct {
+	CompressEncoding bool   `default:"false" yaml:"compress_encoding" json:"compress_encoding,omitempty"`
+	TcpNoDelay       bool   `default:"true" yaml:"tcp_no_delay" json:"tcp_no_delay,omitempty"`
+	TcpKeepAlive     bool   `default:"true" yaml:"tcp_keep_alive" json:"tcp_keep_alive,omitempty"`
+	KeepAlivePrd     string `default:"180s" yaml:"keep_alive_period" json:"keep_alive_period,omitempty"`
+	KeepAlivePeriod  time.Duration
+	TcpRBufSize      int    `default:"262144" yaml:"tcp_r_buf_size" json:"tcp_r_buf_size,omitempty"`
+	TcpWBufSize      int    `default:"65536" yaml:"tcp_w_buf_size" json:"tcp_w_buf_size,omitempty"`
+	PkgWQSize        int    `default:"1024" yaml:"pkg_wq_size" json:"pkg_wq_size,omitempty"`
+	TcpReadTmt       string `default:"1s" yaml:"tcp_read_timeout" json:"tcp_read_timeout,omitempty"`
+	TcpReadTimeout   time.Duration
+	TcpWriteTmt      string `default:"5s" yaml:"tcp_write_timeout" json:"tcp_write_timeout,omitempty"`
+	TcpWriteTimeout  time.Duration
+	WaitTmt      string `default:"7s" yaml:"wait_timeout" json:"wait_timeout,omitempty"`
+	WaitTimeout      time.Duration
+	MaxMsgLen        int    `default:"1024" yaml:"max_msg_len" json:"max_msg_len,omitempty"`
+	SessionName      string `default:"rpc" yaml:"session_name" json:"session_name,omitempty"`
+}
+
+// Config holds supported types by the multiconfig package
+type GettyConfig struct {
+	// session
+	SessionTmt     string `default:"60s" yaml:"session_timeout" json:"session_timeout,omitempty"`
+	SessionTimeout time.Duration
+	SessionNumber  int `default:"1000" yaml:"session_number" json:"session_number,omitempty"`
+
+	// grpool
+	GrPoolSize  int `default:"0" yaml:"gr_pool_size" json:"gr_pool_size,omitempty"`
+	QueueLen    int `default:"0" yaml:"queue_len" json:"queue_len,omitempty"`
+	QueueNumber int `default:"0" yaml:"queue_number" json:"queue_number,omitempty"`
+
+	// session tcp parameters
+	GettySessionParam GettySessionParam `required:"true" yaml:"getty_session_param" json:"getty_session_param,omitempty"`
+}
\ No newline at end of file
diff --git a/tc/config/server_config.go b/tc/config/server_config.go
new file mode 100644
index 0000000..a637a69
--- /dev/null
+++ b/tc/config/server_config.go
@@ -0,0 +1,104 @@
+package config
+
+import (
+	"fmt"
+	"github.com/pkg/errors"
+	"gopkg.in/yaml.v2"
+	"io/ioutil"
+	"path"
+	"time"
+)
+
+var (
+	conf ServerConfig
+)
+
+func GetServerConfig() ServerConfig {
+	return conf
+}
+
+type ServerConfig struct {
+	Host                             string `default:"127.0.0.1" yaml:"host" json:"host,omitempty"`
+	Port                             string `default:"8091" yaml:"port" json:"port,omitempty"`
+	MaxRollbackRetryTimeout          int64  `default:"-1" yaml:"max_rollback_retry_timeout" json:"max_rollback_retry_timeout,omitempty"`
+	RollbackRetryTimeoutUnlockEnable bool   `default:"false" yaml:"rollback_retry_timeout_unlock_enable" json:"rollback_retry_timeout_unlock_enable,omitempty"`
+	MaxCommitRetryTimeout            int64  `default:"-1" yaml:"max_commit_retry_timeout" json:"max_commit_retry_timeout,omitempty"`
+	TimeoutRetryPrd                  string `default:"1s" yaml:"timeout_retry_period" json:"timeout_retry_period,omitempty"`
+	TimeoutRetryPeriod               time.Duration
+	RollbackingRetryPrd              string `default:"1s" yaml:"rollbacking_retry_period" json:"rollbacking_retry_period,omitempty"`
+	RollbackingRetryPeriod           time.Duration
+	CommittingRetryPrd               string `default:"1s" yaml:"committing_retry_period" json:"committing_retry_period,omitempty"`
+	CommittingRetryPeriod            time.Duration
+	AsynCommittingRetryPrd           string `default:"1s" yaml:"aync_committing_retry_period" json:"aync_committing_retry_period,omitempty"`
+	AsynCommittingRetryPeriod        time.Duration
+	LogDeletePrd                     string `default:"24h" yaml:"log_delete_period" json:"log_delete_period,omitempty"`
+	LogDeletePeriod                  time.Duration
+	GettyConfig                      GettyConfig `required:"true" yaml:"getty_config" json:"getty_config,omitempty"`
+	UndoConfig                       UndoConfig  `required:"true" yaml:"undo_config" json:"undo_config,omitempty"`
+	StoreConfig                      StoreConfig `required:"true" yaml:"store_config" json:"store_config,omitempty"`
+}
+
+
+func InitConf(confFile string) error {
+	var err error
+
+	if confFile == "" {
+		return errors.WithMessagef(err,fmt.Sprintf("application configure file name is nil"))
+	}
+	if path.Ext(confFile) != ".yml" {
+		return errors.WithMessagef(err,fmt.Sprintf("application configure file name{%v} suffix must be .yml", confFile))
+	}
+
+	conf = ServerConfig{}
+	confFileStream, err := ioutil.ReadFile(confFile)
+	if err != nil {
+		return errors.WithMessagef(err,fmt.Sprintf("ioutil.ReadFile(file:%s) = error:%s", confFile, err))
+	}
+	err = yaml.Unmarshal(confFileStream, &conf)
+	if err != nil {
+		return errors.WithMessagef(err,fmt.Sprintf("yaml.Unmarshal() = error:%s", err))
+	}
+
+	if conf.TimeoutRetryPeriod, err = time.ParseDuration(conf.TimeoutRetryPrd); err != nil {
+		return errors.WithMessagef(err, "time.ParseDuration(TimeoutRetryPrd{%#v})", conf.TimeoutRetryPrd)
+	}
+
+	conf.RollbackingRetryPeriod, err = time.ParseDuration(conf.RollbackingRetryPrd)
+	if err != nil {
+		return errors.WithMessagef(err,"time.ParseDuration(RollbackingRetryPrd{%#v})", conf.RollbackingRetryPrd)
+	}
+	if conf.CommittingRetryPeriod, err = time.ParseDuration(conf.CommittingRetryPrd); err != nil {
+		return errors.WithMessagef(err, "time.ParseDuration(CommittingRetryPrd{%#v})", conf.CommittingRetryPrd)
+	}
+
+	if conf.AsynCommittingRetryPeriod, err = time.ParseDuration(conf.AsynCommittingRetryPrd); err != nil {
+		return errors.WithMessagef(err, "time.ParseDuration(AsynCommittingRetryPrd{%#v})", conf.AsynCommittingRetryPrd)
+	}
+
+	if conf.LogDeletePeriod, err = time.ParseDuration(conf.LogDeletePrd); err != nil {
+		return errors.WithMessagef(err, "time.ParseDuration(LogDeletePrd{%#v})", conf.LogDeletePrd)
+	}
+
+	conf.GettyConfig.SessionTimeout, err = time.ParseDuration(conf.GettyConfig.SessionTmt)
+	if err != nil {
+		return errors.WithMessagef(err,fmt.Sprintf("time.ParseDuration(SessionTimeout{%#v}) = error{%v}", conf.GettyConfig.SessionTmt, err))
+	}
+	if conf.GettyConfig.GettySessionParam.KeepAlivePeriod, err = time.ParseDuration(conf.GettyConfig.GettySessionParam.KeepAlivePrd); err != nil {
+		return errors.WithMessagef(err, "time.ParseDuration(KeepAlivePeriod{%#v})", conf.GettyConfig.GettySessionParam.KeepAlivePrd)
+	}
+
+	if conf.GettyConfig.GettySessionParam.TcpReadTimeout, err = time.ParseDuration(conf.GettyConfig.GettySessionParam.TcpReadTmt); err != nil {
+		return errors.WithMessagef(err, "time.ParseDuration(TcpReadTimeout{%#v})", conf.GettyConfig.GettySessionParam.TcpReadTmt)
+	}
+
+	if conf.GettyConfig.GettySessionParam.TcpWriteTimeout, err = time.ParseDuration(conf.GettyConfig.GettySessionParam.TcpWriteTmt); err != nil {
+		return errors.WithMessagef(err, "time.ParseDuration(TcpWriteTimeout{%#v})", conf.GettyConfig.GettySessionParam.TcpWriteTmt)
+	}
+
+	if conf.GettyConfig.GettySessionParam.WaitTimeout, err = time.ParseDuration(conf.GettyConfig.GettySessionParam.WaitTmt); err != nil {
+		return errors.WithMessagef(err, "time.ParseDuration(WaitTimeout{%#v})", conf.GettyConfig.GettySessionParam.WaitTmt)
+	}
+
+	storeConfig = conf.StoreConfig
+	return nil
+}
diff --git a/tc/config/store_config.go b/tc/config/store_config.go
new file mode 100644
index 0000000..bf08a61
--- /dev/null
+++ b/tc/config/store_config.go
@@ -0,0 +1,58 @@
+package config
+
+const (
+	DefaultFileDir              = "root.data"
+	DefaultMaxBranchSessionSize = 1024 * 16
+	DefaultMaxGlobalSessionSize = 512
+	DefaultWriteBufferSize      = 1024 * 16
+	DefualtServiceSessionReloadReadSize = 100
+)
+
+type FlushDiskMode int
+
+const (
+	/**
+	 * sync flush disk
+	 */
+	FlushdiskModeSyncModel FlushDiskMode = iota
+
+	/**
+	 * async flush disk
+	 */
+	FlushdiskModeAsyncModel
+)
+
+type StoreConfig struct {
+	MaxBranchSessionSize int             `default:"16384" yaml:"max_branch_session_size" json:"max_branch_session_size,omitempty"`
+	MaxGlobalSessionSize int             `default:"512" yaml:"max_global_session_size" json:"max_global_session_size,omitempty"`
+	StoreMode            string          `default:"file" yaml:"mode" json:"mode,omitempty"`
+	FileStoreConfig      FileStoreConfig `yaml:"file" json:"file,omitempty"`
+	DBStoreConfig        DBStoreConfig   `yaml:"db" json:"db,omitempty"`
+}
+
+type FileStoreConfig struct {
+	FileDir                  string        `default:"root.data" yaml:"file_dir" json:"file_dir,omitempty"`
+	FileWriteBufferCacheSize int           `default:"16384" yaml:"file_write_buffer_cache_size" json:"file_write_buffer_cache_size,omitempty"`
+	FlushDiskMode            FlushDiskMode `default:"1" yaml:"flush_disk_mode" json:"flush_disk_mode,omitempty"`
+	SessionReloadReadSize    int           `default:"100" yaml:"session_reload_read_size" json:"session_reload_read_size,omitempty"`
+}
+
+type DBStoreConfig struct {
+
+}
+
+var storeConfig StoreConfig
+
+func GetStoreConfig() StoreConfig {
+	return storeConfig
+}
+
+func GetDefaultFileStoreConfig() FileStoreConfig{
+	return FileStoreConfig{
+		FileDir:                  DefaultFileDir,
+		FileWriteBufferCacheSize: DefaultWriteBufferSize,
+		FlushDiskMode:            0,
+		SessionReloadReadSize:    DefualtServiceSessionReloadReadSize,
+	}
+}
+
diff --git a/tc/config/undo_config.go b/tc/config/undo_config.go
new file mode 100644
index 0000000..ca757d6
--- /dev/null
+++ b/tc/config/undo_config.go
@@ -0,0 +1,5 @@
+package config
+
+type UndoConfig struct {
+	LogSaveDays int16 `default:"7" yaml:"log_save_days" json:"log_save_days,omitempty"`
+}
\ No newline at end of file
diff --git a/tc/event/event_manager.go b/tc/event/event_manager.go
new file mode 100644
index 0000000..8f0c3f4
--- /dev/null
+++ b/tc/event/event_manager.go
@@ -0,0 +1,11 @@
+package event
+
+type EventManager struct {
+	GlobalTransactionEventChannel chan GlobalTransactionEvent
+}
+
+var EventBus EventManager
+
+func init() {
+	EventBus = EventManager{GlobalTransactionEventChannel:make(chan GlobalTransactionEvent,1000)}
+}
\ No newline at end of file
diff --git a/tc/event/global_transaction_event.go b/tc/event/global_transaction_event.go
new file mode 100644
index 0000000..a369872
--- /dev/null
+++ b/tc/event/global_transaction_event.go
@@ -0,0 +1,41 @@
+package event
+
+import "github.com/dk-lockdown/seata-golang/meta"
+
+const (
+	RoleTC = "tc"
+	RoleTM = "tm"
+	RoleRM = "rm"
+)
+
+type GlobalTransactionEvent struct {
+	id int64
+	role string
+	name string
+	beginTime int64
+	endTime int64
+	status meta.GlobalStatus
+}
+
+func NewGlobalTransactionEvent(id int64,role string,name string,beginTime int64,endTime int64,status meta.GlobalStatus) GlobalTransactionEvent {
+	return GlobalTransactionEvent{
+		id,
+		role,
+		name,
+		beginTime,
+		endTime,
+		status,
+	}
+}
+
+func (event GlobalTransactionEvent) GetId() int64 { return event.id }
+
+func (event GlobalTransactionEvent) GetRole() string { return event.role }
+
+func (event GlobalTransactionEvent) GetName() string { return event.name }
+
+func (event GlobalTransactionEvent) GetBeginTime() int64 { return event.beginTime }
+
+func (event GlobalTransactionEvent) GetEndTime() int64 { return event.endTime }
+
+func (event GlobalTransactionEvent) GetStatus() meta.GlobalStatus { return event.status }
\ No newline at end of file
diff --git a/tc/holder/default_session_manager.go b/tc/holder/default_session_manager.go
new file mode 100644
index 0000000..f766dda
--- /dev/null
+++ b/tc/holder/default_session_manager.go
@@ -0,0 +1,66 @@
+package holder
+
+import (
+	"github.com/dk-lockdown/seata-golang/tc/model"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"github.com/dk-lockdown/seata-golang/util"
+)
+
+type DefaultSessionManager struct {
+	AbstractSessionManager
+	SessionMap              map[string]*session.GlobalSession
+}
+
+func NewDefaultSessionManager(name string) ISessionManager {
+	return &DefaultSessionManager{
+		AbstractSessionManager: AbstractSessionManager {
+			TransactionStoreManager:  &AbstractTransactionStoreManager{},
+			Name: name,
+		},
+		SessionMap: make(map[string]*session.GlobalSession),
+	}
+}
+
+func (sessionManager *DefaultSessionManager) AddGlobalSession(session *session.GlobalSession) error {
+	sessionManager.AbstractSessionManager.AddGlobalSession(session)
+	sessionManager.SessionMap[session.Xid] = session
+	return nil
+}
+
+
+func (sessionManager *DefaultSessionManager) FindGlobalSession(xid string) *session.GlobalSession {
+	return sessionManager.SessionMap[xid]
+}
+
+func (sessionManager *DefaultSessionManager) FindGlobalSessionWithBranchSessions(xid string, withBranchSessions bool) *session.GlobalSession {
+	return sessionManager.SessionMap[xid]
+}
+
+func (sessionManager *DefaultSessionManager) RemoveGlobalSession(session *session.GlobalSession) error{
+	sessionManager.AbstractSessionManager.RemoveGlobalSession(session)
+	delete(sessionManager.SessionMap,session.Xid)
+	return nil
+}
+
+func (sessionManager *DefaultSessionManager) AllSessions() []*session.GlobalSession {
+	var sessions = make([]*session.GlobalSession,0)
+	for _,session := range sessionManager.SessionMap {
+		sessions = append(sessions,session)
+	}
+	return sessions
+}
+
+
+func (sessionManager *DefaultSessionManager) FindGlobalSessions(condition model.SessionCondition) []*session.GlobalSession {
+	var sessions = make([]*session.GlobalSession,0)
+	for _,session := range sessionManager.SessionMap {
+		if int64(util.CurrentTimeMillis()) - session.BeginTime > condition.OverTimeAliveMills {
+			sessions = append(sessions, session)
+		}
+	}
+	return sessions
+}
+
+func (sessionManager *DefaultSessionManager) SetTransactionStoreManager(transactionStoreManager ITransactionStoreManager) {
+	sessionManager.TransactionStoreManager = transactionStoreManager
+}
\ No newline at end of file
diff --git a/tc/holder/default_session_manager_test.go b/tc/holder/default_session_manager_test.go
new file mode 100644
index 0000000..b4a1262
--- /dev/null
+++ b/tc/holder/default_session_manager_test.go
@@ -0,0 +1,87 @@
+package holder
+
+import (
+	"github.com/stretchr/testify/assert"
+	"github.com/dk-lockdown/seata-golang/common"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"github.com/dk-lockdown/seata-golang/util"
+	"testing"
+)
+
+func TestDefaultSessionManager_AddGlobalSession_RemoveGlobalSession(t *testing.T) {
+	gs := globalSessionProvider()
+
+	sessionManager := NewDefaultSessionManager("default")
+	sessionManager.AddGlobalSession(gs)
+	sessionManager.RemoveGlobalSession(gs)
+}
+
+func TestDefaultSessionManager_FindGlobalSession(t *testing.T) {
+	gs := globalSessionProvider()
+	sessionManager := NewDefaultSessionManager("default")
+	sessionManager.AddGlobalSession(gs)
+	expected := sessionManager.FindGlobalSession(gs.Xid)
+
+	assert.NotNil(t,expected)
+	assert.Equal(t,gs.TransactionId,expected.TransactionId)
+	assert.Equal(t,gs.ApplicationId,expected.ApplicationId)
+	assert.Equal(t,gs.TransactionServiceGroup,expected.TransactionServiceGroup)
+	assert.Equal(t,gs.TransactionName,expected.TransactionName)
+	assert.Equal(t,gs.Status,expected.Status)
+
+	sessionManager.RemoveGlobalSession(gs)
+}
+
+func globalSessionsProvider() []*session.GlobalSession {
+	common.XID.IpAddress="127.0.0.1"
+	common.XID.Port=9876
+
+	result := make([]*session.GlobalSession,0)
+	gs1 := session.NewGlobalSession().
+		SetApplicationId("demo-app").
+		SetTransactionId(util.GeneratorUUID()).
+		SetTransactionServiceGroup("my_test_tx_group").
+		SetTransactionName("test").
+		SetTimeout(6000)
+	gs1.SetXid(common.XID.GenerateXID(gs1.TransactionId))
+
+	gs2 := session.NewGlobalSession().
+		SetApplicationId("demo-app").
+		SetTransactionId(util.GeneratorUUID()).
+		SetTransactionServiceGroup("my_test_tx_group").
+		SetTransactionName("test").
+		SetTimeout(6000)
+	gs2.SetXid(common.XID.GenerateXID(gs2.TransactionId))
+
+	result = append(result,gs1)
+	result = append(result,gs2)
+	return result
+}
+
+func globalSessionProvider() *session.GlobalSession {
+	common.XID.IpAddress="127.0.0.1"
+	common.XID.Port=9876
+
+	gs := session.NewGlobalSession().
+		SetApplicationId("demo-app").
+		SetTransactionId(util.GeneratorUUID()).
+		SetTransactionServiceGroup("my_test_tx_group").
+		SetTransactionName("test").
+		SetTimeout(6000)
+	gs.SetXid(common.XID.GenerateXID(gs.TransactionId))
+	return gs
+}
+
+func branchSessionProvider(globalSession *session.GlobalSession) *session.BranchSession {
+	bs := session.NewBranchSession().
+		SetTransactionId(globalSession.TransactionId).
+		SetBranchId(1).
+		SetResourceGroupId("my_test_tx_group").
+		SetResourceId("tb_1").
+		SetLockKey("t_1").
+		SetBranchType(meta.BranchTypeAT).
+		SetApplicationData([]byte("{\"data\":\"test\"}"))
+
+	return bs
+}
\ No newline at end of file
diff --git a/tc/holder/file_based_session_manager.go b/tc/holder/file_based_session_manager.go
new file mode 100644
index 0000000..bc38e3a
--- /dev/null
+++ b/tc/holder/file_based_session_manager.go
@@ -0,0 +1,215 @@
+package holder
+
+import (
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/tc/config"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"github.com/dk-lockdown/seata-golang/util"
+)
+
+type Reloadable interface {
+	/**
+	 * Reload states.
+	 */
+	Reload()
+}
+
+type FileBasedSessionManager struct {
+	conf config.FileStoreConfig
+	DefaultSessionManager
+}
+
+func NewFileBasedSessionManager(conf config.FileStoreConfig) ISessionManager {
+	transactionStoreManager := &FileTransactionStoreManager{}
+	transactionStoreManager.InitFile(conf.FileDir)
+	sessionManager := DefaultSessionManager{
+		AbstractSessionManager: AbstractSessionManager{
+			TransactionStoreManager: transactionStoreManager,
+			Name: conf.FileDir,
+		},
+		SessionMap:             make(map[string]*session.GlobalSession),
+	}
+	transactionStoreManager.SessionManager = &sessionManager
+	return &FileBasedSessionManager{
+		conf:                  conf,
+		DefaultSessionManager: sessionManager,
+	}
+}
+
+func (sessionManager *FileBasedSessionManager)  Reload() {
+	sessionManager.restoreSessions()
+	sessionManager.washSessions()
+}
+
+func (sessionManager *FileBasedSessionManager) restoreSessions() {
+	unhandledBranchBuffer := make(map[int64]*session.BranchSession)
+	sessionManager.restoreSessionsToUnhandledBranchBuffer(true,unhandledBranchBuffer)
+	sessionManager.restoreSessionsToUnhandledBranchBuffer(false,unhandledBranchBuffer)
+	if len(unhandledBranchBuffer) > 0 {
+		for _,branchSession := range unhandledBranchBuffer {
+			found := sessionManager.SessionMap[branchSession.Xid]
+			if found == nil {
+				logging.Logger.Infof("GlobalSession Does Not Exists For BranchSession [%d/%s]",branchSession.BranchId,branchSession.Xid)
+			} else {
+				existingBranch := found.GetBranch(branchSession.BranchId)
+				if existingBranch == nil {
+					found.Add(branchSession)
+				} else {
+					existingBranch.Status = branchSession.Status
+				}
+			}
+		}
+	}
+}
+
+func (sessionManager *FileBasedSessionManager) restoreSessionsToUnhandledBranchBuffer(isHistory bool,unhandledBranchSessions map[int64]*session.BranchSession) {
+	transactionStoreManager, ok := sessionManager.TransactionStoreManager.(ReloadableStore)
+	if !ok {
+		return
+	}
+	for {
+		if transactionStoreManager.HasRemaining(isHistory) {
+			stores := transactionStoreManager.ReadWriteStore(sessionManager.conf.SessionReloadReadSize,isHistory)
+			sessionManager.restore(stores,unhandledBranchSessions)
+		} else {
+			break
+		}
+	}
+}
+
+func (sessionManager *FileBasedSessionManager) washSessions() {
+	if len(sessionManager.SessionMap) > 0 {
+		for _,globalSession := range sessionManager.SessionMap {
+			switch globalSession.Status {
+			case meta.GlobalStatusUnknown:
+			case meta.GlobalStatusCommitted:
+			case meta.GlobalStatusCommitFailed:
+			case meta.GlobalStatusRollbacked:
+			case meta.GlobalStatusRollbackFailed:
+			case meta.GlobalStatusTimeoutRollbacked:
+			case meta.GlobalStatusTimeoutRollbackFailed:
+			case meta.GlobalStatusFinished:
+				// Remove all sessions finished
+				delete(sessionManager.SessionMap, globalSession.Xid)
+				break
+			default:
+				break
+			}
+		}
+	}
+}
+
+func (sessionManager *FileBasedSessionManager) restore(stores []*TransactionWriteStore, unhandledBranchSessions map[int64]*session.BranchSession) {
+	maxRecoverId := util.UUID
+	for _,store := range stores {
+		logOperation := store.LogOperation
+		sessionStorable := store.SessionRequest
+		maxRecoverId = getMaxId(maxRecoverId, sessionStorable)
+		switch logOperation {
+		case LogOperationGlobalAdd:
+		case LogOperationGlobalUpdate:
+			{
+				globalSession := sessionStorable.(*session.GlobalSession)
+				if globalSession.TransactionId == int64(0) {
+					logging.Logger.Errorf("Restore globalSession from file failed, the transactionId is zero , xid:%s", globalSession.Xid)
+					break
+				}
+				foundGlobalSession := sessionManager.SessionMap[globalSession.Xid]
+				if foundGlobalSession == nil {
+					sessionManager.SessionMap[globalSession.Xid] = globalSession
+				} else {
+					foundGlobalSession.Status = globalSession.Status
+				}
+				break
+			}
+		case LogOperationGlobalRemove:
+			{
+				globalSession := sessionStorable.(*session.GlobalSession)
+				if globalSession.TransactionId == int64(0) {
+					logging.Logger.Errorf("Restore globalSession from file failed, the transactionId is zero , xid:%s", globalSession.Xid)
+					break
+				}
+				delete(sessionManager.SessionMap, globalSession.Xid)
+				break
+			}
+		case LogOperationBranchAdd:
+		case LogOperationBranchUpdate:
+			{
+				branchSession := sessionStorable.(*session.BranchSession)
+				if branchSession.TransactionId == int64(0) {
+					logging.Logger.Errorf("Restore branchSession from file failed, the transactionId is zero , xid:%s", branchSession.Xid)
+					break
+				}
+				foundGlobalSession := sessionManager.SessionMap[branchSession.Xid]
+				if foundGlobalSession == nil {
+					unhandledBranchSessions[branchSession.BranchId] = branchSession
+				} else {
+					existingBranch := foundGlobalSession.GetBranch(branchSession.BranchId)
+					if existingBranch == nil {
+						foundGlobalSession.Add(branchSession)
+					} else {
+						existingBranch.Status = branchSession.Status
+					}
+				}
+				break
+			}
+		case LogOperationBranchRemove:
+			{
+				branchSession := sessionStorable.(*session.BranchSession)
+				if branchSession.TransactionId == int64(0) {
+					logging.Logger.Errorf("Restore branchSession from file failed, the transactionId is zero , xid:%s", branchSession.Xid)
+					break
+				}
+				foundGlobalSession := sessionManager.SessionMap[branchSession.Xid]
+				if foundGlobalSession == nil {
+					logging.Logger.Infof("GlobalSession To Be Updated (Remove Branch) Does Not Exists [%d/%s]",branchSession.BranchId,branchSession.Xid)
+				} else {
+					existingBranch := foundGlobalSession.GetBranch(branchSession.BranchId)
+					if existingBranch == nil {
+						logging.Logger.Infof("BranchSession To Be Updated Does Not Exists [%d/%s]",branchSession.BranchId,branchSession.Xid)
+					} else {
+						foundGlobalSession.Remove(existingBranch)
+					}
+				}
+				break
+			}
+		default:
+			break
+		}
+	}
+	setMaxId(maxRecoverId)
+}
+
+func getMaxId(maxRecoverId int64, sessionStorable session.SessionStorable) int64 {
+	var currentId int64 = 0
+	var gs, ok1 = sessionStorable.(*session.GlobalSession)
+	if ok1 {
+		currentId = gs.TransactionId
+	}
+
+	var bs, ok2 = sessionStorable.(*session.BranchSession)
+	if ok2 {
+		currentId = bs.BranchId
+	}
+
+	if maxRecoverId > currentId {
+		return maxRecoverId
+	} else {
+		return currentId
+	}
+}
+
+func setMaxId(maxRecoverId int64) {
+	var currentId int64
+	// will be recover multi-thread later
+	for{
+		currentId = util.UUID
+		if currentId < maxRecoverId {
+			if util.SetUUID(currentId,maxRecoverId) {
+				break
+			}
+		}
+		break
+	}
+}
\ No newline at end of file
diff --git a/tc/holder/file_based_session_manager_test.go b/tc/holder/file_based_session_manager_test.go
new file mode 100644
index 0000000..21b108d
--- /dev/null
+++ b/tc/holder/file_based_session_manager_test.go
@@ -0,0 +1,132 @@
+package holder
+
+import (
+	"github.com/stretchr/testify/assert"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/tc/model"
+	"testing"
+)
+
+func TestFileBasedSessionManager_AddGlobalSession(t *testing.T) {
+	gs := globalSessionProvider()
+
+	sessionManager := NewFileBasedSessionManager("root.data")
+	sessionManager.AddGlobalSession(gs)
+	sessionManager.RemoveGlobalSession(gs)
+}
+
+
+func TestFileBasedSessionManager_FindGlobalSession(t *testing.T) {
+	gs := globalSessionProvider()
+	sessionManager := NewFileBasedSessionManager("root.data")
+	sessionManager.AddGlobalSession(gs)
+	expected := sessionManager.FindGlobalSession(gs.Xid)
+
+	assert.NotNil(t,expected)
+	assert.Equal(t,gs.TransactionId,expected.TransactionId)
+	assert.Equal(t,gs.ApplicationId,expected.ApplicationId)
+	assert.Equal(t,gs.TransactionServiceGroup,expected.TransactionServiceGroup)
+	assert.Equal(t,gs.TransactionName,expected.TransactionName)
+	assert.Equal(t,gs.Status,expected.Status)
+
+	sessionManager.RemoveGlobalSession(gs)
+}
+
+func TestFileBasedSessionManager_UpdateGlobalSessionStatus(t *testing.T) {
+	gs := globalSessionProvider()
+	sessionManager := NewFileBasedSessionManager("root.data")
+	sessionManager.AddGlobalSession(gs)
+	gs.Status = meta.GlobalStatusFinished
+	sessionManager.UpdateGlobalSessionStatus(gs,meta.GlobalStatusFinished)
+
+	expected := sessionManager.FindGlobalSession(gs.Xid)
+	assert.NotNil(t,gs)
+	assert.Equal(t,meta.GlobalStatusFinished,expected.Status)
+
+	sessionManager.RemoveGlobalSession(gs)
+}
+
+func TestFileBasedSessionManager_RemoveGlobalSession(t *testing.T) {
+	gs := globalSessionProvider()
+
+	sessionManager := NewFileBasedSessionManager("root.data")
+	sessionManager.AddGlobalSession(gs)
+	sessionManager.RemoveGlobalSession(gs)
+
+	expected := sessionManager.FindGlobalSession(gs.Xid)
+	assert.Nil(t,expected)
+}
+
+func TestFileBasedSessionManager_AddBranchSession(t *testing.T) {
+	gs := globalSessionProvider()
+	bs := branchSessionProvider(gs)
+
+	sessionManager := NewFileBasedSessionManager("root.data")
+	sessionManager.AddGlobalSession(gs)
+	sessionManager.AddBranchSession(gs,bs)
+	sessionManager.RemoveBranchSession(gs,bs)
+	sessionManager.RemoveGlobalSession(gs)
+}
+
+func TestFileBasedSessionManager_UpdateBranchSessionStatus(t *testing.T) {
+	gs := globalSessionProvider()
+	bs := branchSessionProvider(gs)
+
+	sessionManager := NewFileBasedSessionManager("root.data")
+	sessionManager.AddGlobalSession(gs)
+	sessionManager.AddBranchSession(gs,bs)
+	sessionManager.UpdateBranchSessionStatus(bs,meta.BranchStatusPhasetwoCommitted)
+	sessionManager.RemoveBranchSession(gs,bs)
+	sessionManager.RemoveGlobalSession(gs)
+}
+
+func TestFileBasedSessionManager_RemoveBranchSession(t *testing.T) {
+	gs := globalSessionProvider()
+	bs := branchSessionProvider(gs)
+
+	sessionManager := NewFileBasedSessionManager("root.data")
+	sessionManager.AddGlobalSession(gs)
+	sessionManager.AddBranchSession(gs,bs)
+	sessionManager.RemoveBranchSession(gs,bs)
+	sessionManager.RemoveGlobalSession(gs)
+}
+
+func TestFileBasedSessionManager_AllSessions(t *testing.T) {
+	gss := globalSessionsProvider()
+	sessionManager := NewFileBasedSessionManager("root.data")
+
+	for _,gs := range gss {
+		sessionManager.AddGlobalSession(gs)
+	}
+	allGs := sessionManager.AllSessions()
+	assert.NotNil(t,allGs)
+	assert.Equal(t,2,len(allGs))
+
+	for _,gs := range gss {
+		sessionManager.RemoveGlobalSession(gs)
+	}
+
+	allGs2 := sessionManager.AllSessions()
+	assert.Equal(t,0,len(allGs2))
+}
+
+func TestFileBasedSessionManager_FindGlobalSessionTest(t *testing.T) {
+	gss := globalSessionsProvider()
+	sessionManager := NewFileBasedSessionManager("root.data")
+
+	for _,gs := range gss {
+		sessionManager.AddGlobalSession(gs)
+	}
+	sessionCondition := model.SessionCondition{
+		OverTimeAliveMills: 30 * 24 * 3600,
+	}
+
+	expectedGlobalSessions := sessionManager.FindGlobalSessions(sessionCondition)
+
+	assert.NotNil(t,expectedGlobalSessions)
+	assert.Equal(t,2,len(expectedGlobalSessions))
+
+	for _,gs := range gss {
+		sessionManager.RemoveGlobalSession(gs)
+	}
+}
\ No newline at end of file
diff --git a/tc/holder/file_transaction_store_manager.go b/tc/holder/file_transaction_store_manager.go
new file mode 100644
index 0000000..9f9a69f
--- /dev/null
+++ b/tc/holder/file_transaction_store_manager.go
@@ -0,0 +1,232 @@
+package holder
+
+import (
+	"os"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/tc/model"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"github.com/dk-lockdown/seata-golang/util"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"vimagination.zapto.org/byteio"
+)
+
+var FileTrxNum int64 = 0
+var PerFileBlockSize int64 = 65535 * 8
+var HisDataFilenamePostfix = ".1"
+var MaxTrxTimeoutMills int64 = 30 * 60 * 1000
+
+type ReloadableStore interface {
+	/**
+	 * Read write holder.
+	 *
+	 * @param readSize  the read size
+	 * @param isHistory the is history
+	 * @return the list
+	 */
+	ReadWriteStore(readSize int, isHistory bool) []*TransactionWriteStore
+
+	/**
+	 * Has remaining boolean.
+	 *
+	 * @param isHistory the is history
+	 * @return the boolean
+	 */
+	HasRemaining(isHistory bool) bool
+}
+
+type FileTransactionStoreManager struct {
+	SessionManager ISessionManager
+
+	currFullFileName string
+	hisFullFileName string
+	currFileChannel *os.File
+	LastModifiedTime int64
+	TrxStartTimeMills int64
+	sync.Mutex
+
+	recoverHisOffset int64
+	recoverCurrOffset int64
+}
+
+func (storeManager * FileTransactionStoreManager) InitFile(fullFileName string) {
+	storeManager.currFullFileName = fullFileName
+	storeManager.hisFullFileName = fullFileName + HisDataFilenamePostfix
+	storeManager.currFileChannel,_ = os.OpenFile(fullFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
+	storeManager.TrxStartTimeMills = int64(util.CurrentTimeMillis())
+}
+
+func (storeManager * FileTransactionStoreManager) writeDataFrame(data []byte) {
+	dataLength := uint32(len(data))
+	dataLengthBytes := [4]byte{
+		byte(dataLength >> 24),
+		byte(dataLength >> 16),
+		byte(dataLength >> 8),
+		byte(dataLength),
+	}
+	storeManager.currFileChannel.Write(dataLengthBytes[:4])
+	storeManager.currFileChannel.Write(data)
+}
+
+func (storeManager * FileTransactionStoreManager) WriteSession(logOperation LogOperation, session session.SessionStorable) bool {
+	storeManager.Lock()
+	defer storeManager.Unlock()
+	var curFileTrxNum int64 = 0
+	data, err := (&TransactionWriteStore{
+		SessionRequest: session,
+		LogOperation:   logOperation,
+	}).Encode()
+	if err != nil {
+		logging.Logger.Info(err.Error())
+		return false
+	}
+	storeManager.writeDataFrame(data)
+	storeManager.LastModifiedTime = int64(util.CurrentTimeMillis())
+	curFileTrxNum = atomic.AddInt64(&FileTrxNum,1)
+	if curFileTrxNum %PerFileBlockSize == 0 &&
+		int64(util.CurrentTimeMillis()) - storeManager.TrxStartTimeMills > MaxTrxTimeoutMills {
+		storeManager.saveHistory()
+	}
+	return true
+}
+
+func (storeManager * FileTransactionStoreManager) ReadSession(xid string) *session.GlobalSession {
+	return nil
+}
+
+func (storeManager * FileTransactionStoreManager) ReadSessionWithBranchSessions(xid string, withBranchSessions bool) *session.GlobalSession {
+	return nil
+}
+
+func (storeManager * FileTransactionStoreManager) ReadSessionWithSessionCondition(sessionCondition model.SessionCondition) []*session.GlobalSession {
+	return nil
+}
+
+func (storeManager * FileTransactionStoreManager) Shutdown() {
+	storeManager.currFileChannel.Close()
+}
+
+func (storeManager * FileTransactionStoreManager) GetCurrentMaxSessionId() int64{
+	return int64(0)
+}
+
+func (storeManager * FileTransactionStoreManager) saveHistory() {
+	storeManager.findTimeoutAndSave()
+	os.Rename(storeManager.currFullFileName,storeManager.hisFullFileName)
+	storeManager.InitFile(storeManager.currFullFileName)
+}
+
+func (storeManager * FileTransactionStoreManager) findTimeoutAndSave() (bool,error) {
+	globalSessionsOverMaxTimeout := storeManager.SessionManager.FindGlobalSessions(model.SessionCondition{OverTimeAliveMills: MaxTrxTimeoutMills})
+
+	if globalSessionsOverMaxTimeout == nil {
+		return true,nil
+	}
+
+	for _, globalSession := range globalSessionsOverMaxTimeout {
+		globalWriteStore := &TransactionWriteStore{
+			SessionRequest: globalSession,
+			LogOperation:   LogOperationGlobalAdd,
+		}
+		data,err := globalWriteStore.Encode()
+		if err != nil {
+			return false,err
+		}
+		storeManager.writeDataFrame(data)
+
+		branchSessIonsOverMaXTimeout := globalSession.GetSortedBranches()
+		if len(branchSessIonsOverMaXTimeout) > 0 {
+			for _,branchSession := range branchSessIonsOverMaXTimeout {
+				branchWriteStore :=  &TransactionWriteStore{
+					SessionRequest: branchSession,
+					LogOperation:   LogOperationBranchAdd,
+				}
+				data,err := branchWriteStore.Encode()
+				if err != nil {
+					return false,err
+				}
+				storeManager.writeDataFrame(data)
+			}
+		}
+	}
+	return true,nil
+}
+
+func (storeManager * FileTransactionStoreManager) ReadWriteStore(readSize int, isHistory bool) []*TransactionWriteStore {
+	var (
+		file *os.File
+		currentOffset int64
+	)
+	if isHistory {
+		file, _ = os.OpenFile(storeManager.hisFullFileName, os.O_RDWR|os.O_CREATE, 0777)
+		currentOffset = storeManager.recoverHisOffset
+	} else {
+		file, _ = os.OpenFile(storeManager.currFullFileName, os.O_RDWR|os.O_CREATE, 0777)
+		currentOffset = storeManager.recoverCurrOffset
+	}
+
+	return storeManager.parseDataFile(file,readSize,currentOffset)
+}
+
+func (storeManager * FileTransactionStoreManager) HasRemaining(isHistory bool) bool {
+	var (
+		file *os.File
+		currentOffset int64
+	)
+	if isHistory {
+		file, _ = os.OpenFile(storeManager.hisFullFileName, os.O_RDWR|os.O_CREATE, 0777)
+		currentOffset = storeManager.recoverHisOffset
+	} else {
+		file, _ = os.OpenFile(storeManager.currFullFileName, os.O_RDWR|os.O_CREATE, 0777)
+		currentOffset = storeManager.recoverCurrOffset
+	}
+	defer file.Close()
+
+	fi,_ := file.Stat()
+	return currentOffset < fi.Size()
+}
+
+func (storeManager * FileTransactionStoreManager) parseDataFile(file *os.File, readSize int, currentOffset int64) []*TransactionWriteStore {
+	defer file.Close()
+	var result = make([]*TransactionWriteStore,0)
+	fi,_ := file.Stat()
+	fileSize := fi.Size()
+	reader := byteio.BigEndianReader{Reader:file}
+	offset := currentOffset
+	for {
+		if offset >= fileSize {
+			break
+		}
+		file.Seek(offset, 0)
+		dataLength, n, _ := reader.ReadUint32()
+		if n < 4 {
+			break
+		}
+
+		data := make([]byte, int(dataLength))
+		length, _ := reader.Read(data)
+		offset += int64(length + 4)
+
+		if length == int(dataLength) {
+			st := &TransactionWriteStore{}
+			st.Decode(data)
+			result = append(result, st)
+			if len(result) == readSize {
+				break
+			}
+		} else if length == 0 {
+			break
+		}
+	}
+	if isHisFile(fi.Name()) {
+		storeManager.recoverHisOffset = offset
+	} else {
+		storeManager.recoverCurrOffset = offset
+	}
+	return result
+}
+
+func isHisFile(path string) bool {
+	return strings.HasSuffix(path,HisDataFilenamePostfix)
+}
\ No newline at end of file
diff --git a/tc/holder/session_holder.go b/tc/holder/session_holder.go
new file mode 100644
index 0000000..2652289
--- /dev/null
+++ b/tc/holder/session_holder.go
@@ -0,0 +1,93 @@
+package holder
+
+import (
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/tc/config"
+	"github.com/dk-lockdown/seata-golang/tc/lock"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+)
+
+type SessionHolder struct {
+	RootSessionManager             ISessionManager
+	AsyncCommittingSessionManager  ISessionManager
+	RetryCommittingSessionManager  ISessionManager
+	RetryRollbackingSessionManager ISessionManager
+}
+
+var sessionHolder SessionHolder
+
+func init() {
+	sessionHolder = SessionHolder{
+		RootSessionManager:             NewFileBasedSessionManager(config.GetDefaultFileStoreConfig()),
+		AsyncCommittingSessionManager:  NewDefaultSessionManager("default"),
+		RetryCommittingSessionManager:  NewDefaultSessionManager("default"),
+		RetryRollbackingSessionManager: NewDefaultSessionManager("default"),
+	}
+
+	sessionHolder.reload()
+}
+
+func GetSessionHolder() SessionHolder {
+	return sessionHolder
+}
+
+func (sessionHolder SessionHolder) FindGlobalSession(xid string) *session.GlobalSession {
+	return sessionHolder.FindGlobalSessionWithBranchSessions(xid, true)
+}
+
+func (sessionHolder SessionHolder) FindGlobalSessionWithBranchSessions(xid string, withBranchSessions bool) *session.GlobalSession {
+	return sessionHolder.RootSessionManager.FindGlobalSessionWithBranchSessions(xid, withBranchSessions)
+}
+
+func (sessionHolder SessionHolder) reload() {
+	sessionManager, reloadable := sessionHolder.RootSessionManager.(Reloadable)
+	if reloadable {
+		sessionManager.Reload()
+
+		reloadedSessions := sessionHolder.RootSessionManager.AllSessions()
+		if reloadedSessions != nil && len(reloadedSessions) > 0 {
+			for _,globalSession := range reloadedSessions {
+				switch globalSession.Status {
+				case meta.GlobalStatusUnknown:
+				case meta.GlobalStatusCommitted:
+				case meta.GlobalStatusCommitFailed:
+				case meta.GlobalStatusRollbacked:
+				case meta.GlobalStatusRollbackFailed:
+				case meta.GlobalStatusTimeoutRollbacked:
+				case meta.GlobalStatusTimeoutRollbackFailed:
+				case meta.GlobalStatusFinished:
+					logging.Logger.Errorf("Reloaded Session should NOT be %s",globalSession.Status.String())
+					break
+				case meta.GlobalStatusAsyncCommitting:
+					sessionHolder.AsyncCommittingSessionManager.AddGlobalSession(globalSession)
+					break
+				default:
+					branchSessions := globalSession.GetSortedBranches()
+					for _,branchSession := range branchSessions {
+						lock.GetLockManager().AcquireLock(branchSession)
+					}
+					switch globalSession.Status {
+					case meta.GlobalStatusCommitting:
+					case meta.GlobalStatusCommitRetrying:
+						sessionHolder.RetryCommittingSessionManager.AddGlobalSession(globalSession)
+						break
+					case meta.GlobalStatusRollbacking:
+					case meta.GlobalStatusRollbackRetrying:
+					case meta.GlobalStatusTimeoutRollbacking:
+					case meta.GlobalStatusTimeoutRollbackRetrying:
+						sessionHolder.RetryRollbackingSessionManager.AddGlobalSession(globalSession)
+						break
+					case meta.GlobalStatusBegin:
+						globalSession.SetActive(true)
+						break
+					default:
+						logging.Logger.Errorf("NOT properly handled %s",globalSession.Status)
+						break
+					}
+					break
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/tc/holder/session_manager.go b/tc/holder/session_manager.go
new file mode 100644
index 0000000..b3f301d
--- /dev/null
+++ b/tc/holder/session_manager.go
@@ -0,0 +1,181 @@
+package holder
+
+import (
+	"errors"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/tc/model"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+)
+
+type ISessionManager interface {
+	/**
+	 * Add global session.
+	 *
+	 * @param session the session
+	 * @throws TransactionException the transaction exception
+	 */
+	AddGlobalSession(session *session.GlobalSession) error
+
+	/**
+	 * Find global session global session.
+	 *
+	 * @param xid the xid
+	 * @return the global session
+	 */
+	 FindGlobalSession(xid string) *session.GlobalSession
+
+	/**
+	 * Find global session global session.
+	 *
+	 * @param xid the xid
+	 * @param withBranchSessions the withBranchSessions
+	 * @return the global session
+	 */
+	FindGlobalSessionWithBranchSessions(xid string, withBranchSessions bool) *session.GlobalSession
+
+	/**
+	 * Update global session status.
+	 *
+	 * @param session the session
+	 * @param status  the status
+	 * @throws TransactionException the transaction exception
+	 */
+	UpdateGlobalSessionStatus(session *session.GlobalSession, status meta.GlobalStatus) error
+
+	/**
+	 * Remove global session.
+	 *
+	 * @param session the session
+	 * @throws TransactionException the transaction exception
+	 */
+	RemoveGlobalSession(session *session.GlobalSession) error
+
+	/**
+	 * Add branch session.
+	 *
+	 * @param globalSession the global session
+	 * @param session       the session
+	 * @throws TransactionException the transaction exception
+	 */
+	AddBranchSession(globalSession *session.GlobalSession, session *session.BranchSession) error
+
+	/**
+	 * Update branch session status.
+	 *
+	 * @param session the session
+	 * @param status  the status
+	 * @throws TransactionException the transaction exception
+	 */
+	UpdateBranchSessionStatus(session *session.BranchSession, status meta.BranchStatus) error
+
+	/**
+	 * Remove branch session.
+	 *
+	 * @param globalSession the global session
+	 * @param session       the session
+	 * @throws TransactionException the transaction exception
+	 */
+	RemoveBranchSession(globalSession *session.GlobalSession, session *session.BranchSession) error
+
+	/**
+	 * All sessions collection.
+	 *
+	 * @return the collection
+	 */
+	AllSessions() []*session.GlobalSession
+
+	/**
+	 * Find global sessions list.
+	 *
+	 * @param condition the condition
+	 * @return the list
+	 */
+	FindGlobalSessions(condition model.SessionCondition) []*session.GlobalSession
+}
+
+type AbstractSessionManager struct {
+	TransactionStoreManager ITransactionStoreManager
+	Name string
+}
+
+func (sessionManager *AbstractSessionManager) AddGlobalSession(session *session.GlobalSession) error{
+	logging.Logger.Debugf("MANAGER[%s] SESSION[%v] %s",sessionManager.Name, session, LogOperationGlobalAdd.String())
+	sessionManager.writeSession(LogOperationGlobalAdd,session)
+	return nil
+}
+
+func (sessionManager *AbstractSessionManager) UpdateGlobalSessionStatus(session *session.GlobalSession, status meta.GlobalStatus) error {
+	logging.Logger.Debugf("MANAGER[%s] SESSION[%v] %s",sessionManager.Name, session, LogOperationGlobalUpdate.String())
+	sessionManager.writeSession(LogOperationGlobalUpdate,session)
+	return nil
+}
+
+func (sessionManager *AbstractSessionManager) RemoveGlobalSession(session *session.GlobalSession) error{
+	logging.Logger.Debugf("MANAGER[%s] SESSION[%v] %s",sessionManager.Name, session, LogOperationGlobalRemove.String())
+	sessionManager.writeSession(LogOperationGlobalRemove,session)
+	return nil
+}
+
+func (sessionManager *AbstractSessionManager) AddBranchSession(globalSession *session.GlobalSession, session *session.BranchSession) error{
+	logging.Logger.Debugf("MANAGER[%s] SESSION[%v] %s",sessionManager.Name, session, LogOperationBranchAdd.String())
+	sessionManager.writeSession(LogOperationBranchAdd,session)
+	return nil
+}
+
+func (sessionManager *AbstractSessionManager) UpdateBranchSessionStatus(session *session.BranchSession, status meta.BranchStatus) error{
+	logging.Logger.Debugf("MANAGER[%s] SESSION[%v] %s",sessionManager.Name, session, LogOperationBranchUpdate.String())
+	sessionManager.writeSession(LogOperationBranchUpdate,session)
+	return nil
+}
+
+func (sessionManager *AbstractSessionManager) RemoveBranchSession(globalSession *session.GlobalSession, session *session.BranchSession) error{
+	logging.Logger.Debugf("MANAGER[%s] SESSION[%v] %s",sessionManager.Name, session, LogOperationBranchRemove.String())
+	sessionManager.writeSession(LogOperationBranchRemove,session)
+	return nil
+}
+
+
+func (sessionManager *AbstractSessionManager) writeSession(logOperation LogOperation, sessionStorable session.SessionStorable) error {
+	result := sessionManager.TransactionStoreManager.WriteSession(logOperation,sessionStorable)
+	if !result {
+		if logOperation == LogOperationGlobalAdd {
+			return &meta.TransactionException{
+				Code:    meta.TransactionExceptionCodeFailedWriteSession,
+				Message: "Fail to holder global session",
+			}
+		}
+		if logOperation == LogOperationGlobalUpdate {
+			return &meta.TransactionException{
+				Code:    meta.TransactionExceptionCodeFailedWriteSession,
+				Message: "Fail to update global session",
+			}
+		}
+		if logOperation == LogOperationGlobalRemove {
+			return &meta.TransactionException{
+				Code:    meta.TransactionExceptionCodeFailedWriteSession,
+				Message: "Fail to remove global session",
+			}
+		}
+		if logOperation == LogOperationBranchAdd {
+			return &meta.TransactionException{
+				Code:    meta.TransactionExceptionCodeFailedWriteSession,
+				Message: "Fail to holder branch session",
+			}
+		}
+		if logOperation == LogOperationBranchUpdate {
+			return &meta.TransactionException{
+				Code:    meta.TransactionExceptionCodeFailedWriteSession,
+				Message: "Fail to update branch session",
+			}
+		}
+		if logOperation == LogOperationBranchRemove {
+			return &meta.TransactionException{
+				Code:    meta.TransactionExceptionCodeFailedWriteSession,
+				Message: "Fail to remove branch session",
+			}
+		}
+		return errors.New("Unknown LogOperation:"+logOperation.String())
+	}
+	return nil
+}
\ No newline at end of file
diff --git a/tc/holder/transaction_store_manager.go b/tc/holder/transaction_store_manager.go
new file mode 100644
index 0000000..a0a2a44
--- /dev/null
+++ b/tc/holder/transaction_store_manager.go
@@ -0,0 +1,135 @@
+package holder
+
+import (
+	"fmt"
+	"github.com/dk-lockdown/seata-golang/tc/model"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+)
+
+type LogOperation byte
+
+const (
+	LogOperationGlobalAdd LogOperation = iota
+	/**
+	 * Global update log operation.
+	 */
+	LogOperationGlobalUpdate
+	/**
+	 * Global remove log operation.
+	 */
+	LogOperationGlobalRemove
+	/**
+	 * Branch add log operation.
+	 */
+	LogOperationBranchAdd
+	/**
+	 * Branch update log operation.
+	 */
+	LogOperationBranchUpdate
+	/**
+	 * Branch remove log operation.
+	 */
+	LogOperationBranchRemove
+)
+
+func (t LogOperation) String() string {
+	switch t {
+	case LogOperationGlobalAdd:
+		return "GlobalAdd"
+	case LogOperationGlobalUpdate:
+		return "GlobalUpdate"
+	case LogOperationGlobalRemove:
+		return "GlobalRemove"
+	case LogOperationBranchAdd:
+		return "BranchAdd"
+	case LogOperationBranchUpdate:
+		return "BranchUpdate"
+	case LogOperationBranchRemove:
+		return "BranchRemove"
+	default:
+		return fmt.Sprintf("%d", t)
+	}
+}
+
+type ITransactionStoreManager interface {
+	/**
+	 * Write session boolean.
+	 *
+	 * @param logOperation the log operation
+	 * @param session      the session
+	 * @return the boolean
+	 */
+	WriteSession(logOperation LogOperation, session session.SessionStorable) bool
+
+
+	/**
+	 * Read global session global session.
+	 *
+	 * @param xid the xid
+	 * @return the global session
+	 */
+	ReadSession(xid string) *session.GlobalSession
+
+	/**
+	 * Read session global session.
+	 *
+	 * @param xid the xid
+	 * @param withBranchSessions the withBranchSessions
+	 * @return the global session
+	 */
+	ReadSessionWithBranchSessions(xid string, withBranchSessions bool) *session.GlobalSession
+
+	/**
+	 * Read session by status list.
+	 *
+	 * @param sessionCondition the session condition
+	 * @return the list
+	 */
+	ReadSessionWithSessionCondition(sessionCondition model.SessionCondition) []*session.GlobalSession
+
+	/**
+	 * Shutdown.
+	 */
+	Shutdown()
+
+	/**
+	 * Gets current max session id.
+	 *
+	 * @return the current max session id
+	 */
+	GetCurrentMaxSessionId() int64
+}
+
+type AbstractTransactionStoreManager struct {
+
+}
+
+func (transactionStoreManager *AbstractTransactionStoreManager) WriteSession(logOperation LogOperation, session session.SessionStorable) bool {
+	return true
+}
+
+
+
+func (transactionStoreManager *AbstractTransactionStoreManager) ReadSession(xid string) *session.GlobalSession {
+	return nil
+}
+
+
+func (transactionStoreManager *AbstractTransactionStoreManager) ReadSessionWithBranchSessions(xid string, withBranchSessions bool) *session.GlobalSession {
+	return nil
+}
+
+func (transactionStoreManager *AbstractTransactionStoreManager) ReadSessionWithSessionCondition(sessionCondition model.SessionCondition) []*session.GlobalSession {
+	return nil
+}
+
+func (transactionStoreManager *AbstractTransactionStoreManager) Shutdown() {
+
+}
+
+
+func (transactionStoreManager *AbstractTransactionStoreManager) GetCurrentMaxSessionId() int64 {
+	return 0
+}
+
+
diff --git a/tc/holder/transaction_write_store.go b/tc/holder/transaction_write_store.go
new file mode 100644
index 0000000..81d8d4f
--- /dev/null
+++ b/tc/holder/transaction_write_store.go
@@ -0,0 +1,53 @@
+package holder
+
+import (
+	"github.com/pkg/errors"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+)
+
+type TransactionWriteStore struct {
+	SessionRequest session.SessionStorable
+	LogOperation LogOperation
+}
+
+func (transactionWriteStore *TransactionWriteStore) Encode() ([]byte, error){
+	bySessionRequest,err := transactionWriteStore.SessionRequest.Encode()
+	if err != nil {
+		return nil,err
+	}
+	byOpCode := transactionWriteStore.LogOperation
+
+	var result = make([]byte,0)
+	result = append(result,bySessionRequest...)
+	result = append(result,byte(byOpCode))
+	return result,nil
+}
+
+func (transactionWriteStore *TransactionWriteStore) Decode(src []byte) {
+	bySessionRequest := src[:len(src)-1]
+	byOpCode := src[len(src)-1:]
+
+	transactionWriteStore.LogOperation = LogOperation(byOpCode[0])
+	sessionRequest, _ := transactionWriteStore.getSessionInstanceByOperation()
+	sessionRequest.Decode(bySessionRequest)
+	transactionWriteStore.SessionRequest = sessionRequest
+}
+
+func (transactionWriteStore *TransactionWriteStore) getSessionInstanceByOperation() (session.SessionStorable,error) {
+	var sessionStorable session.SessionStorable
+	switch transactionWriteStore.LogOperation {
+	case LogOperationGlobalAdd:
+	case LogOperationGlobalUpdate:
+	case LogOperationGlobalRemove:
+		sessionStorable = session.NewGlobalSession()
+		break
+	case LogOperationBranchAdd:
+	case LogOperationBranchUpdate:
+	case LogOperationBranchRemove:
+		sessionStorable = session.NewBranchSession()
+		break
+	default:
+		return nil,errors.New("incorrect logOperation.")
+	}
+	return sessionStorable,nil
+}
\ No newline at end of file
diff --git a/tc/lock/lock_manager.go b/tc/lock/lock_manager.go
new file mode 100644
index 0000000..145efbd
--- /dev/null
+++ b/tc/lock/lock_manager.go
@@ -0,0 +1,56 @@
+package lock
+
+import (
+	"github.com/dk-lockdown/seata-golang/tc/session"
+)
+
+type ILockManager interface {
+	/**
+	 * Acquire lock boolean.
+	 *
+	 * @param branchSession the branch session
+	 * @return the boolean
+	 * @throws TransactionException the transaction exception
+	 */
+	AcquireLock(branchSession *session.BranchSession) (bool, error)
+
+	/**
+	 * Un lock boolean.
+	 *
+	 * @param branchSession the branch session
+	 * @return the boolean
+	 * @throws TransactionException the transaction exception
+	 */
+	ReleaseLock(branchSession *session.BranchSession) (bool, error)
+
+	/**
+	 * GlobalSession 是没有锁的,所有的锁都在 BranchSession 上,因为 BranchSession 才
+	 * 持有资源,释放 GlobalSession 锁是指释放它所有的 BranchSession 上的锁
+	 * Un lock boolean.
+	 *
+	 * @param globalSession the global session
+	 * @return the boolean
+	 * @throws TransactionException the transaction exception
+	 */
+	ReleaseGlobalSessionLock(globalSession *session.GlobalSession) (bool, error)
+
+	/**
+	 * Is lockable boolean.
+	 *
+	 * @param xid        the xid
+	 * @param resourceId the resource id
+	 * @param lockKey    the lock key
+	 * @return the boolean
+	 * @throws TransactionException the transaction exception
+	 */
+	IsLockable(xid string, resourceId string, lockKey string) bool
+
+	/**
+	 * Clean all locks.
+	 *
+	 * @throws TransactionException the transaction exception
+	 */
+	CleanAllLocks()
+
+	GetLockKeyCount() int64
+}
\ No newline at end of file
diff --git a/tc/lock/lock_manager_test.go b/tc/lock/lock_manager_test.go
new file mode 100644
index 0000000..c919709
--- /dev/null
+++ b/tc/lock/lock_manager_test.go
@@ -0,0 +1,152 @@
+package lock
+
+import (
+	"github.com/stretchr/testify/assert"
+	"github.com/dk-lockdown/seata-golang/common"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"github.com/dk-lockdown/seata-golang/util"
+	"sync"
+	"testing"
+)
+
+func TestLockManager_AcquireLock(t *testing.T) {
+	bs := branchSessionProvider()
+	ok,err := GetLockManager().AcquireLock(bs)
+	assert.Equal(t,ok,true)
+	assert.Equal(t,err,nil)
+}
+
+func TestLockManager_IsLockable(t *testing.T) {
+	transId := util.GeneratorUUID()
+	ok := GetLockManager().IsLockable(common.XID.GenerateXID(transId),"tb_1","tb_1:13")
+	assert.Equal(t,ok,true)
+}
+
+func TestLockManager_AcquireLock_Fail(t *testing.T) {
+	sessions := branchSessionsProvider()
+	result1,err1 := GetLockManager().AcquireLock(sessions[0])
+	result2,err2 := GetLockManager().AcquireLock(sessions[1])
+	assert.True(t,result1)
+	assert.Equal(t,err1,nil)
+	assert.False(t,result2)
+	assert.Equal(t,err2,nil)
+}
+
+func  TestLockManager_AcquireLock_DeadLock(t *testing.T) {
+	sessions := deadlockBranchSessionsProvider()
+	defer func() {
+		GetLockManager().ReleaseLock(sessions[0])
+		GetLockManager().ReleaseLock(sessions[1])
+	}()
+
+	wg := sync.WaitGroup{}
+	wg.Add(2)
+	go func(session *session.BranchSession) {
+		defer wg.Done()
+		result, err := GetLockManager().AcquireLock(session)
+		logging.Logger.Infof("1: %v %v",result,err)
+	}(sessions[0])
+
+	go func(session *session.BranchSession) {
+		defer wg.Done()
+		result, err := GetLockManager().AcquireLock(session)
+		logging.Logger.Infof("2: %v %v",result,err)
+	}(sessions[1])
+	wg.Wait()
+	assert.True(t,true)
+}
+
+func TestLockManager_IsLockable2(t *testing.T) {
+	bs := branchSessionProvider()
+	bs.SetLockKey("t:4")
+	result1 := GetLockManager().IsLockable(bs.Xid,bs.ResourceId,bs.LockKey)
+	assert.True(t,result1)
+	GetLockManager().AcquireLock(bs)
+	bs.SetTransactionId(util.GeneratorUUID())
+	result2 := GetLockManager().IsLockable(bs.Xid,bs.ResourceId,bs.LockKey)
+	assert.False(t,result2)
+}
+
+func  TestLockManager_AcquireLock_SessionHolder(t *testing.T) {
+	sessions := duplicatePkBranchSessionsProvider()
+	result1, _ := GetLockManager().AcquireLock(sessions[0])
+	assert.True(t,result1)
+	assert.Equal(t,int64(4),GetLockManager().GetLockKeyCount())
+	result2, _ := GetLockManager().ReleaseLock(sessions[0])
+	assert.True(t,result2)
+	assert.Equal(t,int64(0),GetLockManager().GetLockKeyCount())
+
+	result3, _ := GetLockManager().AcquireLock(sessions[1])
+	assert.True(t,result3)
+	assert.Equal(t,int64(4),GetLockManager().GetLockKeyCount())
+	result4, _ := GetLockManager().ReleaseLock(sessions[1])
+	assert.True(t,result4)
+	assert.Equal(t,int64(0),GetLockManager().GetLockKeyCount())
+}
+
+func deadlockBranchSessionsProvider() []*session.BranchSession {
+	return baseBranchSessionsProvider("tb_2", "t:1,2,3,4,5", "t:5,4,3,2,1")
+}
+
+func duplicatePkBranchSessionsProvider() []*session.BranchSession {
+	return baseBranchSessionsProvider("tb_2", "t:1,2;t1:1;t2:2", "t:1,2;t1:1;t2:2")
+}
+
+func branchSessionsProvider() []*session.BranchSession {
+	return baseBranchSessionsProvider("tb_1", "t:1,2", "t:1,2")
+}
+
+func baseBranchSessionsProvider(resourceId string, lockKey1 string, lockKey2 string) []*session.BranchSession {
+	var branchSessions = make([]*session.BranchSession,0)
+	transId := util.GeneratorUUID()
+	transId2 := util.GeneratorUUID()
+	bs := session.NewBranchSession().
+		SetXid(common.XID.GenerateXID(transId)).
+		SetTransactionId(transId).
+		SetBranchId(1).
+		SetResourceGroupId("my_test_tx_group").
+		SetResourceId(resourceId).
+		SetLockKey(lockKey1).
+		SetBranchType(meta.BranchTypeAT).
+		SetStatus(meta.BranchStatusUnknown).
+		SetClientId("c1").
+		SetApplicationData([]byte("{\"data\":\"test\"}"))
+
+	bs1 := session.NewBranchSession().
+		SetXid(common.XID.GenerateXID(transId2)).
+		SetTransactionId(transId2).
+		SetBranchId(1).
+		SetResourceGroupId("my_test_tx_group").
+		SetResourceId(resourceId).
+		SetLockKey(lockKey2).
+		SetBranchType(meta.BranchTypeAT).
+		SetStatus(meta.BranchStatusUnknown).
+		SetClientId("c1").
+		SetApplicationData([]byte("{\"data\":\"test\"}"))
+
+	branchSessions = append(branchSessions,bs)
+	branchSessions = append(branchSessions,bs1)
+	return branchSessions
+}
+
+func branchSessionProvider() *session.BranchSession {
+	common.XID.IpAddress="127.0.0.1"
+	common.XID.Port=9876
+
+	transId := util.GeneratorUUID()
+	bs := session.NewBranchSession().
+		SetXid(common.XID.GenerateXID(transId)).
+		SetTransactionId(transId).
+		SetBranchId(1).
+		SetResourceGroupId("my_test_tx_group").
+		SetResourceId("tb_1").
+		SetLockKey("tb_1:13").
+		SetBranchType(meta.BranchTypeAT).
+		SetStatus(meta.BranchStatusUnknown).
+		SetClientId("c1").
+		SetApplicationData([]byte("{\"data\":\"test\"}"))
+
+	return bs
+}
\ No newline at end of file
diff --git a/tc/lock/locker.go b/tc/lock/locker.go
new file mode 100644
index 0000000..d0eb7ca
--- /dev/null
+++ b/tc/lock/locker.go
@@ -0,0 +1,16 @@
+package lock
+
+import "sync"
+
+var lockManager ILockManager
+
+func init() {
+	lockManager = &MemoryLocker{
+		LockMap:      &sync.Map{},
+		BucketHolder: &sync.Map{},
+	}
+}
+
+func GetLockManager() ILockManager {
+	return lockManager
+}
\ No newline at end of file
diff --git a/tc/lock/memory_lock.go b/tc/lock/memory_lock.go
new file mode 100644
index 0000000..f423bd5
--- /dev/null
+++ b/tc/lock/memory_lock.go
@@ -0,0 +1,188 @@
+package lock
+
+import (
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/model"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"github.com/dk-lockdown/seata-golang/util"
+	"github.com/pkg/errors"
+	"strconv"
+	"sync"
+	"sync/atomic"
+)
+
+const BucketPerTable = 128
+
+type MemoryLocker struct {
+	LockMap *sync.Map
+	// 高流量下,锁资源越多,BucketHolder 的性能越下降
+	BucketHolder *sync.Map
+
+	LockKeyCount int64
+}
+
+
+func (ml *MemoryLocker) AcquireLock(branchSession *session.BranchSession) (bool, error) {
+	if branchSession == nil {
+		logging.Logger.Errorf("branchSession can't be null for memory/file locker.")
+		return false, errors.New("branchSession can't be null for memory/file locker.")
+	}
+
+	lockKey := branchSession.LockKey
+	if lockKey == "" {
+		return true,nil
+	}
+
+	locks := collectRowLocksByBranchSession(branchSession)
+	if locks == nil { return true,nil }
+	return ml.acquireLockByRowLocks(branchSession,locks)
+}
+
+
+func (ml *MemoryLocker) ReleaseLock(branchSession *session.BranchSession) (bool, error) {
+	if branchSession == nil {
+		logging.Logger.Info("branchSession can't be null for memory/file locker.")
+		return false,errors.New("branchSession can't be null for memory/file locker")
+	}
+
+	locks := collectRowLocksByBranchSession(branchSession)
+	return ml.releaseLockByRowLocks(branchSession,locks)
+}
+
+func (ml *MemoryLocker) ReleaseGlobalSessionLock(globalSession *session.GlobalSession) (bool, error) {
+	branchSessions := globalSession.GetSortedBranches()
+	releaseLockResult := true
+	for _,branchSession := range branchSessions {
+		ok, err := ml.ReleaseLock(branchSession)
+		if err != nil {
+			return ok,err
+		}
+		if !ok { releaseLockResult = false }
+
+	}
+	return releaseLockResult, nil
+}
+
+func (ml *MemoryLocker) IsLockable(xid string, resourceId string, lockKey string) bool {
+	locks := collectRowLocksByLockKeyResourceIdXid(lockKey, resourceId, xid)
+	return ml.isLockableByRowLocks(locks)
+}
+
+func  (ml *MemoryLocker) CleanAllLocks() {
+	ml.LockMap = &sync.Map{}
+	ml.BucketHolder = &sync.Map{}
+	ml.LockKeyCount = 0
+}
+
+func  (ml *MemoryLocker) GetLockKeyCount() int64 {
+	return ml.LockKeyCount
+}
+
+// AcquireLock 申请锁资源,resourceId -> tableName -> bucketId -> pk -> transactionId
+func (ml *MemoryLocker) acquireLockByRowLocks(branchSession *session.BranchSession,rowLocks []*RowLock) (bool, error) {
+	if rowLocks == nil { return true, nil }
+
+	resourceId := branchSession.ResourceId
+	transactionId := branchSession.TransactionId
+
+	dbLockMap,_ := ml.LockMap.LoadOrStore(resourceId,&sync.Map{})
+
+	cDbLockMap := dbLockMap.(*sync.Map)
+	for _, rowLock := range rowLocks {
+		tableLockMap,_ := cDbLockMap.LoadOrStore(rowLock.TableName,&sync.Map{})
+
+		cTableLockMap := tableLockMap.(*sync.Map)
+
+		bucketId := util.String(rowLock.Pk) % BucketPerTable
+		bucketKey := strconv.Itoa(bucketId)
+		bucketLockMap,_ := cTableLockMap.LoadOrStore(bucketKey,&sync.Map{})
+
+		cBucketLockMap := bucketLockMap.(*sync.Map)
+
+		previousLockTransactionId,loaded := cBucketLockMap.LoadOrStore(rowLock.Pk, transactionId)
+		if !loaded {
+
+			//No existing rowLock, and now locked by myself
+			keysInHolder,_ := ml.BucketHolder.LoadOrStore(cBucketLockMap, model.NewSet())
+
+			sKeysInHolder := keysInHolder.(*model.Set)
+			sKeysInHolder.Add(rowLock.Pk)
+
+			atomic.AddInt64(&ml.LockKeyCount,1)
+		} else if previousLockTransactionId == transactionId {
+			// Locked by me before
+			continue
+		} else {
+			logging.Logger.Infof("Global rowLock on [%s:%s] is holding by %d", rowLock.TableName, rowLock.Pk,previousLockTransactionId)
+			// branchSession unlock
+			_,err := ml.ReleaseLock(branchSession)
+			return false,err
+		}
+	}
+
+	return true, nil
+}
+
+func (ml *MemoryLocker) releaseLockByRowLocks(branchSession *session.BranchSession,rowLocks []*RowLock) (bool,error) {
+	if rowLocks == nil { return false, nil }
+
+	releaseLock := func (key, value interface{}) bool {
+		cBucketLockMap := key.(*sync.Map)
+		keys := value.(*model.Set)
+
+		for _, key := range keys.List() {
+			transId, ok := cBucketLockMap.Load(key)
+			if ok && transId == branchSession.TransactionId {
+				cBucketLockMap.Delete(key)
+				// keys.List() 是一个新的 slice,移除 key 并不会导致错误发生
+				keys.Remove(key)
+				atomic.AddInt64(&ml.LockKeyCount,-1)
+			}
+		}
+		return true
+	}
+
+	ml.BucketHolder.Range(releaseLock)
+
+	return true, nil
+}
+
+func  (ml *MemoryLocker) isLockableByRowLocks(rowLocks []*RowLock) bool {
+	if rowLocks == nil { return true }
+
+	resourceId := rowLocks[0].ResourceId
+	transactionId := rowLocks[0].TransactionId
+
+	dbLockMap, ok := ml.LockMap.Load(resourceId)
+	if  !ok {
+		return true
+	}
+
+	cDbLockMap := dbLockMap.(*sync.Map)
+	for _, rowLock := range rowLocks {
+		tableLockMap,ok := cDbLockMap.Load(rowLock.TableName)
+		if !ok {
+			continue
+		}
+		cTableLockMap := tableLockMap.(*sync.Map)
+
+		bucketId := util.String(rowLock.Pk) % BucketPerTable
+		bucketKey := strconv.Itoa(bucketId)
+		bucketLockMap,ok := cTableLockMap.Load(bucketKey)
+		if !ok {
+			continue
+		}
+		cBucketLockMap := bucketLockMap.(*sync.Map)
+
+		previousLockTransactionId,ok := cBucketLockMap.Load(rowLock.Pk)
+		if !ok || previousLockTransactionId == transactionId {
+			// Locked by me before
+			continue
+		} else {
+			logging.Logger.Infof("Global rowLock on [%s:%s] is holding by %d", rowLock.TableName, rowLock.Pk,previousLockTransactionId)
+			return false
+		}
+	}
+
+	return true
+}
\ No newline at end of file
diff --git a/tc/lock/row_lock.go b/tc/lock/row_lock.go
new file mode 100644
index 0000000..4059e05
--- /dev/null
+++ b/tc/lock/row_lock.go
@@ -0,0 +1,76 @@
+package lock
+
+import (
+	"github.com/dk-lockdown/seata-golang/common"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"strings"
+)
+
+type RowLock struct {
+	Xid string
+
+	TransactionId int64
+
+	BranchId int64
+
+	ResourceId string
+
+	TableName string
+
+	Pk string
+
+	RowKey string
+
+	Feature string
+}
+
+
+func collectRowLocksByBranchSession(branchSession *session.BranchSession) []*RowLock {
+	if branchSession == nil || branchSession.LockKey == "" {
+		return nil
+	}
+	return collectRowLocks(branchSession.LockKey,branchSession.ResourceId,branchSession.Xid,branchSession.TransactionId,branchSession.BranchId)
+}
+
+func collectRowLocksByLockKeyResourceIdXid(lockKey string,
+	resourceId string,
+	xid string) []*RowLock {
+
+	return collectRowLocks(lockKey,resourceId,xid,common.XID.GetTransactionId(xid),0)
+}
+
+func collectRowLocks(lockKey string,
+	resourceId string,
+	xid string,
+	transactionId int64,
+	branchId int64) []*RowLock {
+	var locks = make([]*RowLock,0)
+	tableGroupedLockKeys := strings.Split(lockKey,";")
+	for _, tableGroupedLockKey := range tableGroupedLockKeys {
+		idx := strings.Index(tableGroupedLockKey,":")
+		if idx < 0 { return nil }
+
+		tableName := tableGroupedLockKey[0:idx]
+		mergedPKs := tableGroupedLockKey[idx+1:]
+
+		if mergedPKs == "" { return nil }
+
+		pks := strings.Split(mergedPKs,",")
+		if len(pks) == 0 { return nil }
+
+		for _,pk := range pks {
+			if pk != "" {
+				rowLock := &RowLock{
+					Xid:           xid,
+					TransactionId: transactionId,
+					BranchId:      branchId,
+					ResourceId:    resourceId,
+					TableName:     tableName,
+					Pk:            pk,
+				}
+				locks = append(locks,rowLock)
+			}
+		}
+	}
+	return locks
+}
\ No newline at end of file
diff --git a/tc/model/session_condition.go b/tc/model/session_condition.go
new file mode 100644
index 0000000..78e7390
--- /dev/null
+++ b/tc/model/session_condition.go
@@ -0,0 +1,11 @@
+package model
+
+import "github.com/dk-lockdown/seata-golang/meta"
+
+type SessionCondition struct{
+	TransactionId int64
+	Xid string
+	Status meta.GlobalStatus
+	Statuses []meta.GlobalStatus
+	OverTimeAliveMills int64
+}
\ No newline at end of file
diff --git a/tc/server/default_coordinator.go b/tc/server/default_coordinator.go
new file mode 100644
index 0000000..df3f826
--- /dev/null
+++ b/tc/server/default_coordinator.go
@@ -0,0 +1,659 @@
+package server
+
+import (
+	"fmt"
+	"github.com/dubbogo/getty"
+	"github.com/pkg/errors"
+	"go.uber.org/atomic"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/protocal"
+	"github.com/dk-lockdown/seata-golang/protocal/codec"
+	"github.com/dk-lockdown/seata-golang/tc/config"
+	"github.com/dk-lockdown/seata-golang/tc/event"
+	"github.com/dk-lockdown/seata-golang/tc/holder"
+	"github.com/dk-lockdown/seata-golang/tc/lock"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"github.com/dk-lockdown/seata-golang/util"
+	"sync"
+	"time"
+)
+
+const (
+	RPC_REQUEST_TIMEOUT = 30 * time.Second
+	ALWAYS_RETRY_BOUNDARY = 0
+)
+
+// MessageFuture ...
+type MessageFuture struct {
+	id        int32
+	err       error
+	response  interface{}
+	done      chan bool
+}
+
+// NewMessageFuture ...
+func NewMessageFuture(message protocal.RpcMessage) *MessageFuture {
+	return &MessageFuture{
+		id:   message.Id,
+		done: make(chan bool),
+	}
+}
+
+type DefaultCoordinator struct {
+	conf config.ServerConfig
+	core ITransactionCoordinator
+	idGenerator atomic.Uint32
+	futures *sync.Map
+	timeoutCheckTicker *time.Ticker
+	retryRollbackingTicker *time.Ticker
+	retryCommittingTicker *time.Ticker
+	asyncCommittingTicker *time.Ticker
+	undoLogDeleteTicker *time.Ticker
+}
+
+func NewDefaultCoordinator(conf config.ServerConfig) *DefaultCoordinator {
+	coordinator := &DefaultCoordinator{
+		conf:                   conf,
+		idGenerator:            atomic.Uint32{},
+		futures:                &sync.Map{},
+		timeoutCheckTicker:     time.NewTicker(conf.TimeoutRetryPeriod),
+		retryRollbackingTicker: time.NewTicker(conf.RollbackingRetryPeriod),
+		retryCommittingTicker:  time.NewTicker(conf.CommittingRetryPeriod),
+		asyncCommittingTicker:  time.NewTicker(conf.AsynCommittingRetryPeriod),
+		undoLogDeleteTicker:    time.NewTicker(conf.LogDeletePeriod),
+	}
+	core := NewCore(coordinator)
+	coordinator.core = core
+
+	go coordinator.processTimeoutCheck()
+	go coordinator.processRetryRollbacking()
+	go coordinator.processRetryCommitting()
+	go coordinator.processAsyncCommitting()
+	go coordinator.processUndoLogDelete()
+	return coordinator
+}
+
+
+func (coordinator *DefaultCoordinator) OnOpen(session getty.Session) error {
+	logging.Logger.Infof("got session:%s", session.Stat())
+	return nil
+}
+
+func (coordinator *DefaultCoordinator) OnError(session getty.Session, err error) {
+	session.Close()
+	logging.Logger.Infof("session{%s} got error{%v}, will be closed.", session.Stat(), err)
+}
+
+func (coordinator *DefaultCoordinator) OnClose(session getty.Session) {
+	logging.Logger.Info("session{%s} is closing......", session.Stat())
+}
+
+func (coordinator *DefaultCoordinator) OnMessage(session getty.Session, pkg interface{}) {
+	logging.Logger.Info("received message:{%v}", pkg)
+	rpcMessage,ok := pkg.(protocal.RpcMessage)
+	if ok {
+		_,isRegTM := rpcMessage.Body.(protocal.RegisterTMRequest)
+		if isRegTM {
+			coordinator.OnRegTmMessage(rpcMessage,session)
+			return
+		}
+
+		heartBeat,isHeartBeat := rpcMessage.Body.(protocal.HeartBeatMessage)
+		if isHeartBeat && heartBeat == protocal.HeartBeatMessagePing {
+			coordinator.OnCheckMessage(rpcMessage,session)
+			return
+		}
+
+		if rpcMessage.MessageType == protocal.MSGTYPE_RESQUEST ||
+			rpcMessage.MessageType == protocal.MSGTYPE_RESQUEST_ONEWAY {
+			logging.Logger.Debugf("msgId:%s, body:%v", rpcMessage.Id, rpcMessage.Body)
+			_,isRegRM := rpcMessage.Body.(protocal.RegisterRMRequest)
+			if isRegRM {
+				coordinator.OnRegRmMessage(rpcMessage,session)
+			} else {
+				if SessionManager.IsRegistered(session) {
+					coordinator.OnTrxMessage(rpcMessage,session)
+				} else {
+					session.Close()
+					logging.Logger.Infof("close a unhandled connection! [%v]", session)
+				}
+			}
+		} else {
+			resp,loaded := coordinator.futures.Load(rpcMessage.Id)
+			if loaded {
+				response := resp.(*MessageFuture)
+				response.response = rpcMessage.Body
+				response.done <- true
+				coordinator.futures.Delete(rpcMessage.Id)
+			}
+		}
+	}
+}
+
+func (coordinator *DefaultCoordinator) OnCron(session getty.Session) {
+
+}
+
+/////////////////////////////////////////////////////////////
+// ServerMessageListener
+/////////////////////////////////////////////////////////////
+func (coordinator *DefaultCoordinator) OnTrxMessage(rpcMessage protocal.RpcMessage, session getty.Session) {
+	rpcContext := SessionManager.GetContextFromIdentified(session)
+	logging.Logger.Debugf("server received:%v,clientIp:%s,vgroup:%s",rpcMessage.Body,session.RemoteAddr(),rpcContext.TransactionServiceGroup)
+
+	warpMessage, isWarpMessage := rpcMessage.Body.(protocal.MergedWarpMessage)
+	if isWarpMessage {
+		resultMessage := protocal.MergeResultMessage{Msgs:make([]protocal.MessageTypeAware,0)}
+		for _,msg := range warpMessage.Msgs {
+			resp := coordinator.handleTrxMessage(msg,*rpcContext)
+			resultMessage.Msgs = append(resultMessage.Msgs,resp)
+		}
+		coordinator.SendResponse(rpcMessage,rpcContext.session,resultMessage)
+	} else {
+		message := rpcMessage.Body.(protocal.MessageTypeAware)
+		resp := coordinator.handleTrxMessage(message,*rpcContext)
+		coordinator.SendResponse(rpcMessage,rpcContext.session,resp)
+	}
+}
+
+func (coordinator *DefaultCoordinator) handleTrxMessage(msg protocal.MessageTypeAware,ctx RpcContext) protocal.MessageTypeAware {
+	switch msg.GetTypeCode() {
+	case protocal.TypeGlobalBegin:
+		req := msg.(protocal.GlobalBeginRequest)
+		resp := coordinator.doGlobalBegin(req,ctx)
+		return resp
+	case protocal.TypeGlobalStatus:
+		req := msg.(protocal.GlobalStatusRequest)
+		resp := coordinator.doGlobalStatus(req,ctx)
+		return resp
+	case protocal.TypeGlobalReport:
+		req := msg.(protocal.GlobalReportRequest)
+		resp := coordinator.doGlobalReport(req,ctx)
+		return resp
+	case protocal.TypeGlobalCommit:
+		req := msg.(protocal.GlobalCommitRequest)
+		resp := coordinator.doGlobalCommit(req,ctx)
+		return resp
+	case protocal.TypeGlobalRollback:
+		req := msg.(protocal.GlobalRollbackRequest)
+		resp := coordinator.doGlobalRollback(req,ctx)
+		return resp
+	case protocal.TypeBranchRegister:
+		req := msg.(protocal.BranchRegisterRequest)
+		resp := coordinator.doBranchRegister(req,ctx)
+		return resp
+	case protocal.TypeBranchStatusReport:
+		req := msg.(protocal.BranchReportRequest)
+		resp := coordinator.doBranchReport(req,ctx)
+		return resp
+	default:
+		return nil
+	}
+}
+
+func (coordinator *DefaultCoordinator) OnRegRmMessage(rpcMessage protocal.RpcMessage, session getty.Session) {
+	message := rpcMessage.Body.(protocal.RegisterRMRequest)
+
+	//version things
+	SessionManager.RegisterRmGettySession(message,session)
+	logging.Logger.Debugf("checkAuth for client:%s,vgroup:%s,applicationId:%s",session.RemoteAddr(),message.TransactionServiceGroup,message.ApplicationId)
+
+	coordinator.SendResponse(rpcMessage,session,protocal.RegisterRMResponse{AbstractIdentifyResponse: protocal.AbstractIdentifyResponse{Identified: true}})
+}
+
+func (coordinator *DefaultCoordinator) OnRegTmMessage(rpcMessage protocal.RpcMessage, session getty.Session) {
+	message := rpcMessage.Body.(protocal.RegisterTMRequest)
+
+	//version things
+	SessionManager.RegisterTmGettySession(message,session)
+	logging.Logger.Debugf("checkAuth for client:%s,vgroup:%s,applicationId:%s",session.RemoteAddr(),message.TransactionServiceGroup,message.ApplicationId)
+
+	coordinator.SendResponse(rpcMessage,session,protocal.RegisterTMResponse{AbstractIdentifyResponse: protocal.AbstractIdentifyResponse{Identified: true}})
+}
+
+func (coordinator *DefaultCoordinator) OnCheckMessage(rpcMessage protocal.RpcMessage, session getty.Session) {
+	coordinator.SendResponse(rpcMessage,session,protocal.HeartBeatMessagePong)
+	logging.Logger.Debugf("received PING from %s", session.RemoteAddr())
+}
+
+/////////////////////////////////////////////////////////////
+// ServerMessageSender
+/////////////////////////////////////////////////////////////
+func (coordinator *DefaultCoordinator) SendResponse(request protocal.RpcMessage, session getty.Session, msg interface{}) {
+	var ss = session
+	_,ok := msg.(protocal.HeartBeatMessage)
+	if !ok {
+		ss = SessionManager.GetSameClientGettySession(session)
+	}
+	if ss != nil {
+		coordinator.defaultSendResponse(request,ss,msg)
+	}
+}
+
+
+func (coordinator *DefaultCoordinator) SendSyncRequest(resourceId string, clientId string, message interface{}) (interface{},error) {
+	return coordinator.SendSyncRequestWithTimeout(resourceId,clientId,message,RPC_REQUEST_TIMEOUT)
+}
+
+
+func (coordinator *DefaultCoordinator) SendSyncRequestWithTimeout(resourceId string, clientId string, message interface{}, timeout time.Duration) (interface{},error) {
+	session,err := SessionManager.GetGettySession(resourceId,clientId)
+	if err != nil {
+		return nil, errors.WithStack(err)
+	}
+	return coordinator.sendAsyncRequestWithResponse("",session,message,timeout)
+}
+
+
+func (coordinator *DefaultCoordinator) SendSyncRequestByGettySession(session getty.Session, message interface{}) (interface{},error) {
+	return coordinator.SendSyncRequestByGettySessionWithTimeout(session,message,RPC_REQUEST_TIMEOUT)
+}
+
+
+func (coordinator *DefaultCoordinator) SendSyncRequestByGettySessionWithTimeout(session getty.Session, message interface{}, timeout time.Duration) (interface{},error) {
+	if session == nil {
+		return nil,errors.New("rm client is not connected")
+	}
+	return coordinator.sendAsyncRequestWithResponse("",session,message,timeout)
+}
+
+
+func (coordinator *DefaultCoordinator) SendASyncRequest(session getty.Session, message interface{}) error {
+	return coordinator.sendAsyncRequestWithoutResponse(session,message)
+}
+
+func (coordinator *DefaultCoordinator) sendAsyncRequestWithResponse(address string,session getty.Session,msg interface{},timeout time.Duration) (interface{},error) {
+	if timeout <= time.Duration(0) {
+		return nil,errors.New("timeout should more than 0ms")
+	}
+	return coordinator.sendAsyncRequest(address,session,msg,timeout)
+}
+
+func (coordinator *DefaultCoordinator) sendAsyncRequestWithoutResponse(session getty.Session,msg interface{}) error {
+	_,err := coordinator.sendAsyncRequest("",session,msg,time.Duration(0))
+	return err
+}
+
+func (coordinator *DefaultCoordinator) sendAsyncRequest(address string,session getty.Session,msg interface{},timeout time.Duration) (interface{},error) {
+	var err error
+	if session == nil {
+		logging.Logger.Warn("sendAsyncRequestWithResponse nothing, caused by null channel.")
+	}
+	rpcMessage := protocal.RpcMessage{
+		Id:          int32(coordinator.idGenerator.Inc()),
+		MessageType: protocal.MSGTYPE_RESQUEST_ONEWAY,
+		Codec:       codec.SEATA,
+		Compressor:  0,
+		Body:        msg,
+	}
+	resp := NewMessageFuture(rpcMessage)
+	coordinator.futures.Store(rpcMessage.Id, resp)
+	//config timeout
+	err = session.WritePkg(rpcMessage, 60000)
+	if err != nil {
+		coordinator.futures.Delete(rpcMessage.Id)
+	}
+
+	if timeout > time.Duration(0) {
+		select {
+		case <-getty.GetTimeWheel().After(timeout):
+			coordinator.futures.Delete(rpcMessage.Id)
+			return nil, errors.Errorf("wait response timeout,ip:%s,request:%v", address, rpcMessage)
+		case <-resp.done:
+			err = resp.err
+		}
+		return resp.response, err
+	}
+	return nil,err
+}
+
+func (coordinator *DefaultCoordinator) defaultSendResponse(request protocal.RpcMessage, session getty.Session, msg interface{}) {
+	resp := protocal.RpcMessage{
+		Id:          request.Id,
+		Codec:       request.Codec,
+		Compressor:  request.Compressor,
+		Body:        msg,
+	}
+	_,ok := msg.(protocal.HeartBeatMessage)
+	if ok {
+		resp.MessageType = protocal.MSGTYPE_HEARTBEAT_RESPONSE
+	} else {
+		resp.MessageType = protocal.MSGTYPE_RESPONSE
+	}
+	session.WritePkg(resp,time.Duration(0))
+}
+
+/////////////////////////////////////////////////////////////
+// TCInboundHandler
+/////////////////////////////////////////////////////////////
+func (coordinator *DefaultCoordinator) doGlobalBegin(request protocal.GlobalBeginRequest,ctx RpcContext) protocal.GlobalBeginResponse {
+	var resp = protocal.GlobalBeginResponse{}
+	xid,err := coordinator.core.Begin(ctx.ApplicationId,ctx.TransactionServiceGroup,request.TransactionName,request.Timeout)
+	if err != nil {
+		trxException, ok := err.(meta.TransactionException)
+		resp.ResultCode = protocal.ResultCodeFailed
+		if ok {
+			resp.TransactionExceptionCode = trxException.Code
+			resp.Msg = fmt.Sprintf("TransactionException[%s]",err.Error())
+			logging.Logger.Errorf("Catch TransactionException while do RPC, request: %v", request)
+			return resp
+		}
+		resp.Msg = fmt.Sprintf("RuntimeException[%s]",err.Error())
+		logging.Logger.Errorf("Catch RuntimeException while do RPC, request: %v", request)
+		return resp
+	}
+	resp.Xid = xid
+	resp.ResultCode = protocal.ResultCodeSuccess
+	return resp
+}
+
+func (coordinator *DefaultCoordinator) doGlobalStatus(request protocal.GlobalStatusRequest,ctx RpcContext) protocal.GlobalStatusResponse {
+	var resp = protocal.GlobalStatusResponse{}
+	globalStatus,err := coordinator.core.GetStatus(request.Xid)
+	if err != nil {
+		trxException, ok := err.(meta.TransactionException)
+		resp.ResultCode = protocal.ResultCodeFailed
+		if ok {
+			resp.TransactionExceptionCode = trxException.Code
+			resp.Msg = fmt.Sprintf("TransactionException[%s]",err.Error())
+			logging.Logger.Errorf("Catch TransactionException while do RPC, request: %v", request)
+			return resp
+		}
+		resp.Msg = fmt.Sprintf("RuntimeException[%s]",err.Error())
+		logging.Logger.Errorf("Catch RuntimeException while do RPC, request: %v", request)
+		return resp
+	}
+	resp.GlobalStatus = globalStatus
+	resp.ResultCode = protocal.ResultCodeSuccess
+	return resp
+}
+
+func (coordinator *DefaultCoordinator) doGlobalReport(request protocal.GlobalReportRequest,ctx RpcContext) protocal.GlobalReportResponse {
+	var resp = protocal.GlobalReportResponse{}
+	globalStatus,err := coordinator.core.GlobalReport(request.Xid,request.GlobalStatus)
+	if err != nil {
+		trxException, ok := err.(meta.TransactionException)
+		resp.ResultCode = protocal.ResultCodeFailed
+		if ok {
+			resp.TransactionExceptionCode = trxException.Code
+			resp.Msg = fmt.Sprintf("TransactionException[%s]",err.Error())
+			logging.Logger.Errorf("Catch TransactionException while do RPC, request: %v", request)
+			return resp
+		}
+		resp.Msg = fmt.Sprintf("RuntimeException[%s]",err.Error())
+		logging.Logger.Errorf("Catch RuntimeException while do RPC, request: %v", request)
+		return resp
+	}
+	resp.GlobalStatus = globalStatus
+	resp.ResultCode = protocal.ResultCodeSuccess
+	return resp
+}
+
+
+func (coordinator *DefaultCoordinator) doGlobalCommit(request protocal.GlobalCommitRequest,ctx RpcContext) protocal.GlobalCommitResponse {
+	var resp = protocal.GlobalCommitResponse{}
+	globalStatus,err := coordinator.core.Commit(request.Xid)
+	if err != nil {
+		trxException, ok := err.(meta.TransactionException)
+		resp.ResultCode = protocal.ResultCodeFailed
+		if ok {
+			resp.TransactionExceptionCode = trxException.Code
+			resp.Msg = fmt.Sprintf("TransactionException[%s]",err.Error())
+			logging.Logger.Errorf("Catch TransactionException while do RPC, request: %v", request)
+			return resp
+		}
+		resp.Msg = fmt.Sprintf("RuntimeException[%s]",err.Error())
+		logging.Logger.Errorf("Catch RuntimeException while do RPC, request: %v", request)
+		return resp
+	}
+	resp.GlobalStatus = globalStatus
+	resp.ResultCode = protocal.ResultCodeSuccess
+	return resp
+}
+
+func (coordinator *DefaultCoordinator) doGlobalRollback(request protocal.GlobalRollbackRequest,ctx RpcContext) protocal.GlobalRollbackResponse {
+	var resp = protocal.GlobalRollbackResponse{}
+	globalStatus,err := coordinator.core.Rollback(request.Xid)
+	if err != nil {
+		trxException, ok := err.(meta.TransactionException)
+		resp.ResultCode = protocal.ResultCodeFailed
+		globalSession := holder.GetSessionHolder().FindGlobalSessionWithBranchSessions(request.Xid,false)
+		if globalSession == nil {
+			resp.GlobalStatus = meta.GlobalStatusFinished
+		} else {
+			resp.GlobalStatus = globalSession.Status
+		}
+		if ok {
+			resp.TransactionExceptionCode = trxException.Code
+			resp.Msg = fmt.Sprintf("TransactionException[%s]",err.Error())
+			logging.Logger.Errorf("Catch TransactionException while do RPC, request: %v", request)
+			return resp
+		}
+		resp.Msg = fmt.Sprintf("RuntimeException[%s]",err.Error())
+		logging.Logger.Errorf("Catch RuntimeException while do RPC, request: %v", request)
+		return resp
+	}
+	resp.GlobalStatus = globalStatus
+	resp.ResultCode = protocal.ResultCodeSuccess
+	return resp
+}
+
+func (coordinator *DefaultCoordinator) doBranchRegister(request protocal.BranchRegisterRequest,ctx RpcContext) protocal.BranchRegisterResponse {
+	var resp = protocal.BranchRegisterResponse{}
+	branchId,err := coordinator.core.BranchRegister(request.BranchType,request.ResourceId,ctx.ClientId,request.Xid,request.ApplicationData,request.LockKey)
+	if err != nil {
+		trxException, ok := err.(meta.TransactionException)
+		resp.ResultCode = protocal.ResultCodeFailed
+		if ok {
+			resp.TransactionExceptionCode = trxException.Code
+			resp.Msg = fmt.Sprintf("TransactionException[%s]",err.Error())
+			logging.Logger.Errorf("Catch TransactionException while do RPC, request: %v", request)
+			return resp
+		}
+		resp.Msg = fmt.Sprintf("RuntimeException[%s]",err.Error())
+		logging.Logger.Errorf("Catch RuntimeException while do RPC, request: %v", request)
+		return resp
+	}
+	resp.BranchId = branchId
+	resp.ResultCode = protocal.ResultCodeSuccess
+	return resp
+}
+
+func (coordinator *DefaultCoordinator) doBranchReport(request protocal.BranchReportRequest,ctx RpcContext) protocal.BranchReportResponse {
+	var resp = protocal.BranchReportResponse{}
+	err := coordinator.core.BranchReport(request.BranchType,request.Xid,request.BranchId,request.Status,request.ApplicationData)
+	if err != nil {
+		trxException, ok := err.(meta.TransactionException)
+		resp.ResultCode = protocal.ResultCodeFailed
+		if ok {
+			resp.TransactionExceptionCode = trxException.Code
+			resp.Msg = fmt.Sprintf("TransactionException[%s]",err.Error())
+			logging.Logger.Errorf("Catch TransactionException while do RPC, request: %v", request)
+			return resp
+		}
+		resp.Msg = fmt.Sprintf("RuntimeException[%s]",err.Error())
+		logging.Logger.Errorf("Catch RuntimeException while do RPC, request: %v", request)
+		return resp
+	}
+	resp.ResultCode = protocal.ResultCodeSuccess
+	return resp
+}
+
+func (coordinator *DefaultCoordinator) doLockCheck(request protocal.GlobalLockQueryRequest,ctx RpcContext) protocal.GlobalLockQueryResponse {
+	var resp = protocal.GlobalLockQueryResponse{}
+	result, err := coordinator.core.LockQuery(request.BranchType,request.ResourceId,request.Xid,request.LockKey)
+	if err != nil {
+		trxException, ok := err.(meta.TransactionException)
+		resp.ResultCode = protocal.ResultCodeFailed
+		if ok {
+			resp.TransactionExceptionCode = trxException.Code
+			resp.Msg = fmt.Sprintf("TransactionException[%s]",err.Error())
+			logging.Logger.Errorf("Catch TransactionException while do RPC, request: %v", request)
+			return resp
+		}
+		resp.Msg = fmt.Sprintf("RuntimeException[%s]",err.Error())
+		logging.Logger.Errorf("Catch RuntimeException while do RPC, request: %v", request)
+		return resp
+	}
+	resp.Lockable = result
+	resp.ResultCode = protocal.ResultCodeSuccess
+	return resp
+}
+
+func (coordinator *DefaultCoordinator) processTimeoutCheck() {
+	for {
+		<- coordinator.timeoutCheckTicker.C
+		coordinator.timeoutCheck()
+	}
+}
+
+func (coordinator *DefaultCoordinator) processRetryRollbacking() {
+	for {
+		<- coordinator.retryRollbackingTicker.C
+		coordinator.handleRetryRollbacking()
+	}
+}
+
+func (coordinator *DefaultCoordinator) processRetryCommitting() {
+	for {
+		<- coordinator.retryCommittingTicker.C
+		coordinator.handleRetryCommitting()
+	}
+}
+
+func (coordinator *DefaultCoordinator) processAsyncCommitting() {
+	for {
+		<- coordinator.asyncCommittingTicker.C
+		coordinator.handleAsyncCommitting()
+	}
+}
+
+func (coordinator *DefaultCoordinator) processUndoLogDelete() {
+	for {
+		<- coordinator.undoLogDeleteTicker.C
+		coordinator.undoLogDelete()
+	}
+}
+
+func (coordinator *DefaultCoordinator) timeoutCheck() {
+	allSessions := holder.GetSessionHolder().RootSessionManager.AllSessions()
+	if allSessions == nil && len(allSessions) <= 0 {
+		return
+	}
+	logging.Logger.Debugf("Transaction Timeout Check Begin: %d",len(allSessions))
+	for _,globalSession := range allSessions {
+		logging.Logger.Debugf("%s %s %d %d",globalSession.Xid,globalSession.Status.String(),globalSession.BeginTime,globalSession.Timeout)
+		shouldTimout := func (gs *session.GlobalSession) bool {
+			globalSession.Lock()
+			defer globalSession.Unlock()
+			if globalSession.Status != meta.GlobalStatusBegin || !globalSession.IsTimeout() {
+				return false
+			}
+
+			if globalSession.Active {
+				globalSession.Active = false
+			}
+			changeGlobalSessionStatus(globalSession, meta.GlobalStatusTimeoutRollbacking)
+			evt := event.NewGlobalTransactionEvent(globalSession.TransactionId, event.RoleTC, globalSession.TransactionName, globalSession.BeginTime, 0, globalSession.Status)
+			event.EventBus.GlobalTransactionEventChannel <- evt
+			return true
+		}(globalSession)
+		if !shouldTimout {
+			continue
+		}
+		logging.Logger.Infof("Global transaction[%s] is timeout and will be rolled back.",globalSession.Status)
+		holder.GetSessionHolder().RetryRollbackingSessionManager.AddGlobalSession(globalSession)
+	}
+	logging.Logger.Debug("Transaction Timeout Check End.")
+}
+
+func (coordinator *DefaultCoordinator) handleRetryRollbacking() {
+	rollbackingSessions := holder.GetSessionHolder().RetryRollbackingSessionManager.AllSessions()
+	if rollbackingSessions == nil && len(rollbackingSessions) <= 0 {
+		return
+	}
+	now := util.CurrentTimeMillis()
+	for _,rollbackingSession := range rollbackingSessions {
+		if rollbackingSession.Status == meta.GlobalStatusRollbacking && !rollbackingSession.IsRollbackingDead() {
+			continue
+		}
+		if isRetryTimeout(int64(now),coordinator.conf.MaxRollbackRetryTimeout,rollbackingSession.BeginTime){
+			if coordinator.conf.RollbackRetryTimeoutUnlockEnable {
+				lock.GetLockManager().ReleaseGlobalSessionLock(rollbackingSession)
+			}
+			holder.GetSessionHolder().RetryRollbackingSessionManager.RemoveGlobalSession(rollbackingSession)
+			logging.Logger.Errorf("GlobalSession rollback retry timeout and removed [%s]", rollbackingSession.Xid)
+			continue
+		}
+		_, err := coordinator.core.doGlobalRollback(rollbackingSession,true)
+		if err != nil {
+			logging.Logger.Infof("Failed to retry rollbacking [%s]",rollbackingSession.Xid)
+		}
+	}
+}
+
+func isRetryTimeout(now int64,timeout int64,beginTime int64) bool {
+ 	if timeout >= ALWAYS_RETRY_BOUNDARY && now - beginTime > timeout {
+ 		return true
+	}
+	return false
+}
+
+func (coordinator *DefaultCoordinator) handleRetryCommitting() {
+	committingSessions := holder.GetSessionHolder().RetryCommittingSessionManager.AllSessions()
+	if committingSessions == nil && len(committingSessions) <= 0 {
+		return
+	}
+	now := util.CurrentTimeMillis()
+	for _,committingSession := range committingSessions {
+		if isRetryTimeout(int64(now),coordinator.conf.MaxCommitRetryTimeout,committingSession.BeginTime) {
+			holder.GetSessionHolder().RetryCommittingSessionManager.RemoveGlobalSession(committingSession)
+			logging.Logger.Errorf("GlobalSession commit retry timeout and removed [%s]", committingSession.Xid)
+			continue
+		}
+		_,err := coordinator.core.doGlobalCommit(committingSession,true)
+		if err != nil {
+			logging.Logger.Infof("Failed to retry committing [%s]",committingSession.Xid)
+		}
+	}
+}
+
+func (coordinator *DefaultCoordinator) handleAsyncCommitting() {
+	asyncCommittingSessions := holder.GetSessionHolder().AsyncCommittingSessionManager.AllSessions()
+	if asyncCommittingSessions == nil && len(asyncCommittingSessions) <= 0 {
+		return
+	}
+	for _,asyncCommittingSession := range asyncCommittingSessions {
+		if asyncCommittingSession.Status != meta.GlobalStatusAsyncCommitting {
+			continue
+		}
+		_,err := coordinator.core.doGlobalCommit(asyncCommittingSession,true)
+		if err != nil {
+			logging.Logger.Infof("Failed to async committing [%s]",asyncCommittingSession.Xid)
+		}
+	}
+}
+
+func (coordinator *DefaultCoordinator) undoLogDelete() {
+	saveDays := coordinator.conf.UndoConfig.LogSaveDays
+	for key,session := range SessionManager.GetRmSessions() {
+		resourceId := key
+		deleteRequest := protocal.UndoLogDeleteRequest{
+			ResourceId: resourceId,
+			SaveDays:   saveDays,
+		}
+		err := coordinator.SendASyncRequest(session,deleteRequest)
+		if err != nil {
+			logging.Logger.Errorf("Failed to async delete undo log resourceId = %s", resourceId)
+		}
+	}
+}
+
+func (coordinator *DefaultCoordinator) Stop() {
+	coordinator.timeoutCheckTicker.Stop()
+	coordinator.retryRollbackingTicker.Stop()
+	coordinator.retryCommittingTicker.Stop()
+	coordinator.asyncCommittingTicker.Stop()
+	coordinator.undoLogDeleteTicker.Stop()
+}
\ No newline at end of file
diff --git a/tc/server/default_core.go b/tc/server/default_core.go
new file mode 100644
index 0000000..0feb584
--- /dev/null
+++ b/tc/server/default_core.go
@@ -0,0 +1,584 @@
+package server
+
+import (
+	"fmt"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/protocal"
+	"github.com/dk-lockdown/seata-golang/tc/event"
+	"github.com/dk-lockdown/seata-golang/tc/holder"
+	"github.com/dk-lockdown/seata-golang/tc/lock"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"github.com/dk-lockdown/seata-golang/util"
+)
+
+/**
+ *  +--------------------+-----------------------+--------------------+
+ *  |                    |Method(InBound)        |Method(OutBound)    |
+ *  +--------------------+-----------------------+--------------------+
+ *  |	                 |Begin                  |                    |
+ *  |                    |BranchRegister         |                    |
+ *  |         TC         |BranchReport           |                    |
+ *  |      (AT&TCC)      |(GlobalReport)         |branchCommit        |
+ *  |    (DefaultCore)   |Commit                 |branchRollback      |
+ *  |                    |Rollback               |                    |
+ *  |                    |GetStatus              |                    |
+ *  +--------------------+-----------------------+--------------------+
+ *  |	      AT         |LockQuery              |                    |
+ *  +--------------------+-----------------------+--------------------+
+ *  |                    |doGlobalCommit         |                    |
+ *  |        SAGA        |doGlobalRollBack       |                    |
+ *  |                    |doGlobalReport         |                    |
+ *  +--------------------+-----------------------+--------------------+
+ *
+ * 参考 [effective go 之 Embedding](#https://my.oschina.net/pengfeix/blog/109967)
+ * Go does not provide the typical, type-driven notion of subclassing,
+ * but it does have the ability to “borrow” pieces of an implementation
+ * by embedding types within a struct or interface.
+ * Go 没有像其它面向对象语言中的类继承概念,但是,它可以通过在结构体或者接口中嵌入
+ * 其它的类型,来使用被嵌入类型的功能。
+ *
+ * 原本 JAVA 版 Seata Sever 设计了 Core 接口,AbstractCore 实现该接口,ATCore、
+ * TccCore、SagaCore 都继承 AbstractCore。使 ATCore、TccCore、SagaCore 每一
+ * 个类单独拿出来都是 Core 接口的实现。但 Go 版的 Seata 我不打算这样设计。我们将
+ * Core 接口里定义的接口方法拿出来,如上面的表格所示,一个全局事务的周期分别对应 Begin、
+ * BranchRegister、BranchReport、Commit、Rollback 接口方法,这些接口方法适用于
+ * AT 模式和 TCC 模式(SAGA 模式暂不了解,先不考虑)。AT 模式会多一个 LockQuery
+ * 的接口。另外 OutBound 方向上有两个接口 branchCommit、branchRollback。JAVA 版
+ * 的设计中 doGlobalCommit、doGlobalRollBack、doGlobalReport 其实是私有方法,
+ * 这里用首字母小些开头的方法区分。那么 Go 版本的 DefaultCore 设计就出来了(暂不考虑 SAGA),
+ * DefaultCore 内嵌入 ATCore。
+ *
+ */
+
+type AbstractCore struct {
+	MessageSender IServerMessageSender
+}
+
+type ATCore struct {
+	AbstractCore
+}
+
+type SAGACore struct {
+	AbstractCore
+}
+
+type DefaultCore struct {
+	AbstractCore
+	ATCore
+	SAGACore
+	coreMap map[meta.BranchType]interface{}
+}
+
+func NewCore(sender IServerMessageSender) ITransactionCoordinator {
+	return &DefaultCore{
+		AbstractCore: AbstractCore{ MessageSender: sender },
+		ATCore:       ATCore{},
+		SAGACore:     SAGACore{},
+		coreMap:      make(map[meta.BranchType]interface{}),
+	}
+}
+
+func (core *ATCore) branchSessionLock(globalSession *session.GlobalSession,branchSession *session.BranchSession) error {
+	result,err :=lock.GetLockManager().AcquireLock(branchSession)
+	if err != nil {
+		return err
+	}
+	if !result {
+		return &meta.TransactionException{
+			Code:    meta.TransactionExceptionCodeLockKeyConflict,
+			Message: fmt.Sprintf("Global lock acquire failed xid = %s branchId = %s",
+				globalSession.Xid,branchSession.BranchId),
+		}
+	}
+	return nil
+}
+
+func (core *ATCore) branchSessionUnlock(branchSession *session.BranchSession) error {
+	_, err := lock.GetLockManager().ReleaseLock(branchSession)
+	return err
+}
+
+func (core *ATCore) LockQuery(branchType meta.BranchType,
+	resourceId string,
+	xid string,
+	lockKeys string) bool {
+	return lock.GetLockManager().IsLockable(xid,resourceId,lockKeys)
+}
+
+func (core *SAGACore) doGlobalCommit(globalSession *session.GlobalSession, retrying bool) (bool, error) {
+	return true,nil
+}
+
+func (core *SAGACore) doGlobalRollback(globalSession *session.GlobalSession, retrying bool) (bool, error) {
+	return true,nil
+}
+
+func (core *SAGACore) doGlobalReport(globalSession *session.GlobalSession, xid string, param meta.GlobalStatus) error {
+	return nil
+}
+
+func (core *DefaultCore) Begin(applicationId string, transactionServiceGroup string, name string, timeout int32) (string, error) {
+	gs := session.NewGlobalSession().
+		SetApplicationId(applicationId).
+		SetTransactionServiceGroup(transactionServiceGroup).
+		SetTransactionName(name).
+		SetTimeout(timeout)
+
+	gs.Begin()
+	err := holder.GetSessionHolder().RootSessionManager.AddGlobalSession(gs)
+	if err != nil {
+		return "",err
+	}
+
+	evt := event.NewGlobalTransactionEvent(gs.TransactionId, event.RoleTC,gs.TransactionName,gs.BeginTime,0,gs.Status)
+	event.EventBus.GlobalTransactionEventChannel <- evt
+
+	logging.Logger.Infof("Successfully begin global transaction xid = {}",gs.Xid)
+	return gs.Xid, nil
+}
+
+
+func (core *DefaultCore) BranchRegister(branchType meta.BranchType,
+	resourceId string,
+	clientId string,
+	xid string,
+	applicationData []byte,
+	lockKeys string) (int64, error) {
+	gs,err := assertGlobalSessionNotNull(xid,false)
+	if err != nil {
+		return 0,err
+	}
+	defer gs.Unlock()
+	gs.Lock()
+
+	err1 := globalSessionStatusCheck(gs)
+	if err1 != nil {
+		return 0,err
+	}
+
+	bs := session.NewBranchSessionByGlobal(*gs,branchType,resourceId,applicationData,lockKeys,clientId)
+
+	if branchType == meta.BranchTypeAT {
+		core.ATCore.branchSessionLock(gs, bs)
+	}
+	gs.Add(bs)
+
+	logging.Logger.Infof("Successfully register branch xid = %s, branchId = %d",gs.Xid,bs.BranchId)
+	return bs.BranchId,nil
+}
+
+func globalSessionStatusCheck(globalSession *session.GlobalSession) error {
+	if !globalSession.Active {
+		return &meta.TransactionException{
+			Code:    meta.TransactionExceptionCodeGlobalTransactionNotActive,
+			Message: fmt.Sprintf("Could not register branch into global session xid = %s status = %d",globalSession.Xid,globalSession.Status),
+		}
+	}
+	if globalSession.Status != meta.GlobalStatusBegin {
+		return &meta.TransactionException{
+			Code:    meta.TransactionExceptionCodeGlobalTransactionStatusInvalid,
+			Message: fmt.Sprintf("Could not register branch into global session xid = %s status = %d while expecting %d",
+				globalSession.Xid,globalSession.Status,meta.GlobalStatusBegin),
+		}
+	}
+	return nil
+}
+
+func assertGlobalSessionNotNull(xid string, withBranchSessions bool) (*session.GlobalSession,error) {
+	gs := holder.GetSessionHolder().FindGlobalSessionWithBranchSessions(xid,withBranchSessions)
+	if gs == nil {
+		logging.Logger.Errorf("Could not found global transaction xid = %s",gs.Xid)
+		return nil,&meta.TransactionException{
+			Code:    meta.TransactionExceptionCodeGlobalTransactionNotExist,
+			Message: fmt.Sprintf("Could not found global transaction xid = %s",gs.Xid),
+		}
+	}
+	return gs,nil
+}
+
+func (core *DefaultCore) BranchReport(branchType meta.BranchType,
+	xid string,
+	branchId int64,
+	status meta.BranchStatus,
+	applicationData []byte) error {
+	gs,err := assertGlobalSessionNotNull(xid,true)
+	if err != nil {
+		return nil
+	}
+
+	bs := gs.GetBranch(branchId)
+	if bs == nil {
+		return &meta.TransactionException{
+			Code:    meta.TransactionExceptionCodeBranchTransactionNotExist,
+			Message: fmt.Sprintf("Could not found branch session xid = %s branchId = %d",
+				xid,branchId),
+		}
+	}
+
+	bs.Status = status
+	holder.GetSessionHolder().RootSessionManager.UpdateBranchSessionStatus(bs,status)
+
+	logging.Logger.Infof("Successfully branch report xid = %s, branchId = %d",xid,bs.BranchId)
+	return nil
+}
+
+func (core *DefaultCore) LockQuery(branchType meta.BranchType, resourceId string, xid string, lockKeys string) (bool, error) {
+	return true,nil
+}
+
+func (core *DefaultCore) branchCommit(globalSession *session.GlobalSession, branchSession *session.BranchSession) (meta.BranchStatus, error) {
+	request := protocal.BranchCommitRequest{}
+	request.Xid = branchSession.Xid
+	request.BranchId = branchSession.BranchId
+	request.ResourceId = branchSession.ResourceId
+	request.ApplicationData = branchSession.ApplicationData
+	request.BranchType = branchSession.BranchType
+
+	resp, err := core.branchCommitSend(request,globalSession,branchSession)
+	if err != nil {
+		return 0,&meta.TransactionException{
+			Code:    meta.TransactionExceptionCodeBranchTransactionNotExist,
+			Message: fmt.Sprintf("Send branch commit failed, xid = %s branchId = %d",
+				branchSession.Xid,branchSession.BranchId),
+		}
+	}
+	return resp,err
+}
+
+func (core *DefaultCore) branchCommitSend(request protocal.BranchCommitRequest,
+	globalSession *session.GlobalSession, branchSession *session.BranchSession) (meta.BranchStatus,error) {
+	resp,err := core.MessageSender.SendSyncRequest(branchSession.ResourceId,branchSession.ClientId,request)
+	if err != nil {
+		return 0,err
+	}
+	response := resp.(protocal.BranchCommitResponse)
+	return response.BranchStatus, nil
+}
+
+func (core *DefaultCore) branchRollback(globalSession *session.GlobalSession, branchSession *session.BranchSession) (meta.BranchStatus, error) {
+	request := protocal.BranchRollbackRequest{}
+	request.Xid = branchSession.Xid
+	request.BranchId = branchSession.BranchId
+	request.ResourceId = branchSession.ResourceId
+	request.ApplicationData = branchSession.ApplicationData
+	request.BranchType = branchSession.BranchType
+
+	resp, err := core.branchRollbackSend(request,globalSession,branchSession)
+	if err != nil {
+		return 0,&meta.TransactionException{
+			Code:    meta.TransactionExceptionCodeBranchTransactionNotExist,
+			Message: fmt.Sprintf("Send branch rollback failed, xid = %s branchId = %d",
+				branchSession.Xid,branchSession.BranchId),
+		}
+	}
+	return resp,err
+}
+
+func (core *DefaultCore) branchRollbackSend(request protocal.BranchRollbackRequest,
+	globalSession *session.GlobalSession, branchSession *session.BranchSession) (meta.BranchStatus,error) {
+	resp,err := core.MessageSender.SendSyncRequest(branchSession.ResourceId,branchSession.ClientId,request)
+	if err != nil {
+		return 0,err
+	}
+	response := resp.(protocal.BranchRollbackResponse)
+	return response.BranchStatus, nil
+}
+
+func (core *DefaultCore) Commit(xid string) (meta.GlobalStatus, error) {
+	globalSession := holder.GetSessionHolder().RootSessionManager.FindGlobalSession(xid)
+	if globalSession == nil {
+		return meta.GlobalStatusFinished, nil
+	}
+	shouldCommit := func (gs *session.GlobalSession) bool {
+		gs.Lock()
+		defer gs.Unlock()
+		if gs.Active {
+			gs.Active = false
+		}
+		lock.GetLockManager().ReleaseGlobalSessionLock(gs)
+		if gs.Status == meta.GlobalStatusBegin {
+			changeGlobalSessionStatus(gs,meta.GlobalStatusCommitting)
+			return true
+		}
+		return false
+	}(globalSession)
+
+	if !shouldCommit {
+		return globalSession.Status,nil
+	}
+
+	if globalSession.CanBeCommittedAsync() {
+		asyncCommit(globalSession)
+		return meta.GlobalStatusCommitted, nil
+	} else {
+		_,err := core.doGlobalCommit(globalSession,false)
+		if err != nil {
+			return 0,err
+		}
+	}
+
+	return globalSession.Status,nil
+}
+
+func (core *DefaultCore) doGlobalCommit(globalSession *session.GlobalSession, retrying bool) (bool, error) {
+	var (
+		success = true
+		err error
+	)
+
+	evt := event.NewGlobalTransactionEvent(globalSession.TransactionId, event.RoleTC,globalSession.TransactionName,globalSession.BeginTime,0,globalSession.Status)
+	event.EventBus.GlobalTransactionEventChannel <- evt
+
+	if globalSession.IsSaga() {
+		success,err = core.SAGACore.doGlobalCommit(globalSession,retrying)
+	} else {
+		for _,bs := range globalSession.GetSortedBranches() {
+			if bs.Status == meta.BranchStatusPhaseoneFailed {
+				removeBranchSession(globalSession,bs)
+				continue
+			}
+			branchStatus,err1 := core.branchCommit(globalSession,bs)
+			if err1 != nil {
+				logging.Logger.Errorf("Exception committing branch %v", bs)
+				if !retrying {
+					queueToRetryCommit(globalSession)
+				}
+				return false,err1
+			}
+			switch branchStatus {
+			case meta.BranchStatusPhasetwoCommitted:
+				removeBranchSession(globalSession,bs)
+				continue
+			case meta.BranchStatusPhasetwoCommitFailedUnretryable:
+				{
+					// 二阶段提交失败且不能 Retry,不能异步提交,则移除 GlobalSession,Why?
+					if globalSession.CanBeCommittedAsync() {
+						logging.Logger.Errorf("By [%s], failed to commit branch %v",bs.Status.String(),bs)
+						continue
+					} else {
+						endCommitFailed(globalSession)
+						logging.Logger.Errorf("Finally, failed to commit global[%d] since branch[%d] commit failed",globalSession.Xid,bs.BranchId)
+						return false,nil
+					}
+				}
+			default:
+				{
+					if !retrying {
+						queueToRetryCommit(globalSession)
+						return false,nil
+					}
+					if globalSession.CanBeCommittedAsync() {
+						logging.Logger.Errorf("By [%s], failed to commit branch %v",bs.Status.String(),bs)
+						continue
+					} else {
+						logging.Logger.Errorf("ResultCodeFailed to commit global[%d] since branch[%d] commit failed, will retry later.",globalSession.Xid,bs.BranchId)
+						return false,nil
+					}
+				}
+			}
+		}
+		if globalSession.HasBranch() {
+			logging.Logger.Infof("Global[%d] committing is NOT done.", globalSession.Xid)
+			return false,nil
+		}
+	}
+	if success {
+		endCommitted(globalSession)
+
+		evt := event.NewGlobalTransactionEvent(globalSession.TransactionId, event.RoleTC,globalSession.TransactionName,globalSession.BeginTime,
+			int64(util.CurrentTimeMillis()),globalSession.Status)
+		event.EventBus.GlobalTransactionEventChannel <- evt
+
+		logging.Logger.Infof("Global[%d] committing is successfully done.", globalSession.Xid)
+	}
+	return success,err
+}
+
+func (core *DefaultCore) Rollback(xid string) (meta.GlobalStatus, error) {
+	globalSession := holder.GetSessionHolder().RootSessionManager.FindGlobalSession(xid)
+	if globalSession == nil {
+		return meta.GlobalStatusFinished, nil
+	}
+	shouldRollBack := func (gs *session.GlobalSession) bool {
+		gs.Lock()
+		defer gs.Unlock()
+		if gs.Active {
+			gs.Active = false  // Highlight: Firstly, close the session, then no more branch can be registered.
+		}
+		lock.GetLockManager().ReleaseGlobalSessionLock(gs)
+		if gs.Status == meta.GlobalStatusBegin {
+			changeGlobalSessionStatus(gs,meta.GlobalStatusRollbacking)
+			return true
+		}
+		return false
+	}(globalSession)
+
+	if !shouldRollBack {
+		return globalSession.Status,nil
+	}
+
+	core.doGlobalRollback(globalSession,false)
+	return globalSession.Status,nil
+}
+
+func (core *DefaultCore) doGlobalRollback(globalSession *session.GlobalSession, retrying bool) (bool, error) {
+	var (
+		success = true
+		err error
+	)
+
+	evt := event.NewGlobalTransactionEvent(globalSession.TransactionId, event.RoleTC,globalSession.TransactionName,globalSession.BeginTime, 0,globalSession.Status)
+	event.EventBus.GlobalTransactionEventChannel <- evt
+
+	if globalSession.IsSaga() {
+		success,err = core.SAGACore.doGlobalRollback(globalSession,retrying)
+	} else {
+		for _,bs := range globalSession.GetSortedBranches() {
+			if bs.Status == meta.BranchStatusPhaseoneFailed {
+				removeBranchSession(globalSession, bs)
+				continue
+			}
+			branchStatus,err1 := core.branchRollback(globalSession,bs)
+			if err1 != nil {
+				logging.Logger.Errorf("Exception rollbacking branch xid=%d branchId=%d", globalSession.Xid,bs.BranchId)
+				if !retrying {
+					queueToRetryRollback(globalSession)
+				}
+				return false,err1
+			}
+			switch branchStatus {
+			case meta.BranchStatusPhasetwoRollbacked:
+				removeBranchSession(globalSession,bs)
+				logging.Logger.Infof("Successfully rollback branch xid=%d branchId=%d", globalSession.Xid,bs.BranchId)
+				continue
+			case meta.BranchStatusPhasetwoRollbackFailedUnretryable:
+				endRollBackFailed(globalSession)
+				logging.Logger.Infof("ResultCodeFailed to rollback branch and stop retry xid=%d branchId=%d",globalSession.Xid,bs.BranchId)
+				return false,nil
+			default:
+				logging.Logger.Infof("ResultCodeFailed to rollback branch xid=%d branchId=%d", globalSession.Xid,bs.BranchId)
+				if !retrying {
+					queueToRetryRollback(globalSession)
+				}
+				return false,nil
+			}
+		}
+
+		// In db mode, there is a problem of inconsistent data in multiple copies, resulting in new branch
+		// transaction registration when rolling back.
+		// 1. New branch transaction and rollback branch transaction have no data association
+		// 2. New branch transaction has data association with rollback branch transaction
+		// The second query can solve the first problem, and if it is the second problem, it may cause a rollback
+		// failure due to data changes.
+		gs := holder.GetSessionHolder().RootSessionManager.FindGlobalSession(globalSession.Xid)
+		if gs != nil && gs.HasBranch() {
+			logging.Logger.Infof("Global[%d] rollbacking is NOT done.", globalSession.Xid)
+			return false, nil
+		}
+	}
+	if success {
+		endRollbacked(globalSession)
+
+		evt := event.NewGlobalTransactionEvent(globalSession.TransactionId, event.RoleTC,globalSession.TransactionName,globalSession.BeginTime,
+			int64(util.CurrentTimeMillis()),globalSession.Status)
+		event.EventBus.GlobalTransactionEventChannel <- evt
+
+		logging.Logger.Infof("Successfully rollback global, xid = %d", globalSession.Xid)
+	}
+	return success,err
+}
+
+func (core *DefaultCore) GetStatus(xid string) (meta.GlobalStatus, error) {
+	gs := holder.GetSessionHolder().RootSessionManager.FindGlobalSession(xid)
+	if gs == nil {
+		return meta.GlobalStatusFinished,nil
+	} else {
+		return gs.Status,nil
+	}
+}
+
+func (core *DefaultCore) GlobalReport(xid string, globalStatus meta.GlobalStatus) (meta.GlobalStatus, error) {
+	gs := holder.GetSessionHolder().RootSessionManager.FindGlobalSession(xid)
+	if gs == nil {
+		return globalStatus,nil
+	}
+	core.doGlobalReport(gs,xid,globalStatus)
+	return gs.Status,nil
+}
+
+func (core *DefaultCore) doGlobalReport(globalSession *session.GlobalSession,xid string,globalStatus meta.GlobalStatus) error {
+	if globalSession.IsSaga() {
+		return core.SAGACore.doGlobalReport(globalSession,xid,globalStatus)
+	}
+	return nil
+}
+
+func endRollbacked(globalSession *session.GlobalSession) {
+	if isTimeoutGlobalStatus(globalSession.Status) {
+		changeGlobalSessionStatus(globalSession,meta.GlobalStatusTimeoutRollbacked)
+	} else {
+		changeGlobalSessionStatus(globalSession,meta.GlobalStatusRollbacked)
+	}
+	lock.GetLockManager().ReleaseGlobalSessionLock(globalSession)
+	holder.GetSessionHolder().RootSessionManager.RemoveGlobalSession(globalSession)
+}
+
+func endRollBackFailed(globalSession *session.GlobalSession) {
+	if isTimeoutGlobalStatus(globalSession.Status) {
+		changeGlobalSessionStatus(globalSession,meta.GlobalStatusTimeoutRollbackFailed)
+	} else {
+		changeGlobalSessionStatus(globalSession,meta.GlobalStatusRollbackFailed)
+	}
+	lock.GetLockManager().ReleaseGlobalSessionLock(globalSession)
+	holder.GetSessionHolder().RootSessionManager.RemoveGlobalSession(globalSession)
+}
+
+func queueToRetryRollback(globalSession *session.GlobalSession) {
+	holder.GetSessionHolder().RetryRollbackingSessionManager.AddGlobalSession(globalSession)
+	if isTimeoutGlobalStatus(globalSession.Status) {
+		changeGlobalSessionStatus(globalSession,meta.GlobalStatusTimeoutRollbackRetrying)
+	} else {
+		changeGlobalSessionStatus(globalSession,meta.GlobalStatusRollbackRetrying)
+	}
+}
+
+func isTimeoutGlobalStatus(status meta.GlobalStatus) bool {
+	return status == meta.GlobalStatusTimeoutRollbacked ||
+		status == meta.GlobalStatusTimeoutRollbackFailed ||
+		status == meta.GlobalStatusTimeoutRollbacking ||
+		status == meta.GlobalStatusTimeoutRollbackRetrying
+}
+
+func endCommitted(globalSession *session.GlobalSession) {
+	changeGlobalSessionStatus(globalSession,meta.GlobalStatusCommitted)
+	lock.GetLockManager().ReleaseGlobalSessionLock(globalSession)
+	holder.GetSessionHolder().RootSessionManager.RemoveGlobalSession(globalSession)
+}
+
+func queueToRetryCommit(globalSession *session.GlobalSession) {
+	holder.GetSessionHolder().RetryCommittingSessionManager.AddGlobalSession(globalSession)
+	changeGlobalSessionStatus(globalSession,meta.GlobalStatusCommitRetrying)
+}
+
+func endCommitFailed(globalSession *session.GlobalSession) {
+	changeGlobalSessionStatus(globalSession,meta.GlobalStatusCommitFailed)
+	lock.GetLockManager().ReleaseGlobalSessionLock(globalSession)
+	holder.GetSessionHolder().RootSessionManager.RemoveGlobalSession(globalSession)
+}
+
+func asyncCommit(globalSession *session.GlobalSession) {
+	holder.GetSessionHolder().AsyncCommittingSessionManager.AddGlobalSession(globalSession)
+	changeGlobalSessionStatus(globalSession,meta.GlobalStatusAsyncCommitting)
+}
+
+func changeGlobalSessionStatus(globalSession *session.GlobalSession, status meta.GlobalStatus) {
+	globalSession.Status = status
+	holder.GetSessionHolder().RootSessionManager.UpdateGlobalSessionStatus(globalSession,meta.GlobalStatusAsyncCommitting)
+}
+
+func removeBranchSession(globalSession *session.GlobalSession,branchSession *session.BranchSession) {
+	lock.GetLockManager().ReleaseLock(branchSession)
+	globalSession.Remove(branchSession)
+	holder.GetSessionHolder().RootSessionManager.RemoveBranchSession(globalSession,branchSession)
+}
\ No newline at end of file
diff --git a/tc/server/getty_session_manager.go b/tc/server/getty_session_manager.go
new file mode 100644
index 0000000..127add3
--- /dev/null
+++ b/tc/server/getty_session_manager.go
@@ -0,0 +1,372 @@
+package server
+
+import (
+	"github.com/pkg/errors"
+	"github.com/dubbogo/getty"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/model"
+	"github.com/dk-lockdown/seata-golang/protocal"
+	"strconv"
+	"strings"
+	"sync"
+)
+
+var (
+	/**
+	 * resourceId -> applicationId -> ip -> port -> RpcContext
+	 */
+	rm_sessions = sync.Map{}
+
+	/**
+	 * ip+appname -> port -> RpcContext
+	 */
+	tm_sessions = sync.Map{}
+)
+
+const (
+	ClientIdSplitChar = ":"
+	DbkeysSplitChar   = ","
+)
+
+type GettySessionManager struct {
+	IdentifiedSessions *sync.Map
+}
+
+var SessionManager GettySessionManager
+
+func init() {
+	SessionManager = GettySessionManager{IdentifiedSessions:&sync.Map{}}
+}
+
+func (manager *GettySessionManager) IsRegistered(session getty.Session) bool {
+	_,ok := manager.IdentifiedSessions.Load(session)
+	return ok
+}
+
+func (manager *GettySessionManager) GetRoleFromGettySession(session getty.Session) meta.TransactionRole {
+	context, ok := manager.IdentifiedSessions.Load(session)
+	if ok {
+		return context.(*RpcContext).ClientRole
+	}
+	return 0
+}
+
+func (manager *GettySessionManager)  GetContextFromIdentified(session getty.Session) *RpcContext {
+	context, ok := manager.IdentifiedSessions.Load(session)
+	if ok {
+		rpcContext := context.(*RpcContext)
+		return rpcContext
+	}
+	return nil
+}
+
+func (manager *GettySessionManager) RegisterTmGettySession(request protocal.RegisterTMRequest,session getty.Session) {
+	//todo check version
+	rpcContext := buildGettySessionHolder(meta.TMROLE,request.Version,request.ApplicationId,request.TransactionServiceGroup,"",session)
+	rpcContext.HoldInIdentifiedGettySessions(manager.IdentifiedSessions)
+	clientIdentified := rpcContext.ApplicationId + ClientIdSplitChar + getClientIpFromGettySession(session)
+	clientIdentifiedMap,_ := tm_sessions.LoadOrStore(clientIdentified,&sync.Map{})
+	cMap := clientIdentifiedMap.(*sync.Map)
+	rpcContext.HoldInClientGettySessions(cMap)
+}
+
+func (manager *GettySessionManager) RegisterRmGettySession(resourceManagerRequest protocal.RegisterRMRequest,session getty.Session){
+	//todo check version
+	var rpcContext *RpcContext
+	dbKeySet := dbKeyToSet(resourceManagerRequest.ResourceIds)
+	context,ok := manager.IdentifiedSessions.Load(session)
+	if ok {
+		rpcContext = context.(*RpcContext)
+		rpcContext.AddResources(dbKeySet)
+	} else {
+		rpcContext = buildGettySessionHolder(meta.RMROLE,resourceManagerRequest.Version,resourceManagerRequest.ApplicationId,
+			resourceManagerRequest.TransactionServiceGroup,resourceManagerRequest.ResourceIds,session)
+		rpcContext.HoldInIdentifiedGettySessions(manager.IdentifiedSessions)
+	}
+	if dbKeySet == nil || dbKeySet.IsEmpty() { return }
+	for _,resourceId := range dbKeySet.List() {
+		applicationMap,_ := rm_sessions.LoadOrStore(resourceId,&sync.Map{})
+		aMap,_ := applicationMap.(*sync.Map)
+		ipMap,_ := aMap.LoadOrStore(resourceManagerRequest.ApplicationId,&sync.Map{})
+		iMap,_ := ipMap.(*sync.Map)
+		clientIp := getClientIpFromGettySession(session)
+		portMap,_ := iMap.LoadOrStore(clientIp,&sync.Map{})
+		pMap,_ := portMap.(*sync.Map)
+
+		rpcContext.HoldInResourceManagerGettySessions(resourceId,pMap)
+		// 老实讲,我不知道为什么要写这么一个方法,双重保证?
+		manager.updateGettySessionsResource(resourceId,clientIp,resourceManagerRequest.ApplicationId)
+	}
+}
+
+func (manager *GettySessionManager) updateGettySessionsResource(resourceId string,clientIp string,applicationId string) {
+	applicationMap,_ := rm_sessions.Load(resourceId)
+	aMap,_ := applicationMap.(*sync.Map)
+	ipMap,_ := aMap.Load(applicationId)
+	iMap,_ := ipMap.(*sync.Map)
+	portMap,_ := iMap.Load(clientIp)
+	pMap,_ := portMap.(*sync.Map)
+
+	rm_sessions.Range(func (key interface{},value interface{}) bool {
+		resourceKey,ok := key.(string)
+		if ok && resourceKey != resourceId {
+			appMap,_ := value.(*sync.Map)
+
+			clientIpMap,clientIpMapLoaded := appMap.Load(applicationId)
+			if clientIpMapLoaded {
+				cipMap,_ := clientIpMap.(*sync.Map)
+				clientPortMap, clientPortMapLoaded := cipMap.Load(clientIp)
+				if clientPortMapLoaded {
+					cpMap := clientPortMap.(*sync.Map)
+					cpMap.Range(func (key interface{},value interface{}) bool{
+						port,_ := key.(int)
+						rpcContext,_ := value.(*RpcContext)
+						_, ok := pMap.LoadOrStore(port,rpcContext)
+						if ok {
+							rpcContext.HoldInResourceManagerGettySessionsWithoutPortMap(resourceId,port)
+						}
+						return true
+					})
+				}
+			}
+		}
+		return true
+	})
+}
+
+func (manager *GettySessionManager) GetSameClientGettySession(session getty.Session) getty.Session {
+	if !session.IsClosed() {
+		return session
+	}
+
+	rpcContext := manager.GetContextFromIdentified(session)
+	if rpcContext == nil {
+		logging.Logger.Errorf("rpcContext is null,channel:{%v},active:{%t}",session,!session.IsClosed())
+	}
+	if !rpcContext.session.IsClosed() {
+		return rpcContext.session
+	}
+
+	clientPort := getClientPortFromGettySession(session)
+	if rpcContext.ClientRole == meta.TMROLE {
+		clientIdentified := rpcContext.ApplicationId + ClientIdSplitChar + getClientIpFromGettySession(session)
+		clientRpcMap, ok := tm_sessions.Load(clientIdentified)
+		if !ok {
+			return nil
+		}
+		clientMap := clientRpcMap.(*sync.Map)
+		return getGettySessionFromSameClientMap(clientMap,clientPort)
+	} else if rpcContext.ClientRole == meta.RMROLE {
+		var sameClientSession getty.Session
+		rpcContext.ClientRMHolderMap.Range(func (key interface{},value interface{}) bool {
+			clientRmMap := value.(*sync.Map)
+			sameClientSession = getGettySessionFromSameClientMap(clientRmMap,clientPort)
+			if sameClientSession != nil {
+				return false
+			}
+			return true
+		})
+		return sameClientSession
+	}
+	return nil
+}
+
+func getGettySessionFromSameClientMap(clientGettySessionMap *sync.Map,exclusivePort int) getty.Session {
+	var session getty.Session
+	if clientGettySessionMap != nil {
+		clientGettySessionMap.Range(func (key interface{},value interface{}) bool {
+			port,ok := key.(int)
+			if ok {
+				if port == exclusivePort {
+					clientGettySessionMap.Delete(key)
+					return true
+				}
+			}
+
+			context := value.(*RpcContext)
+			session = context.session
+			if !session.IsClosed() {
+				return false
+			}
+			clientGettySessionMap.Delete(key)
+			return true
+		})
+	}
+	return session
+}
+
+func (manager *GettySessionManager) GetGettySession(resourceId string,clientId string) (getty.Session,error) {
+	var resultSession getty.Session
+
+	clientIdInfo := strings.Split(clientId,ClientIdSplitChar)
+	if clientIdInfo == nil || len(clientIdInfo) != 3 {
+		return nil,errors.Errorf("Invalid Client ID:%d",clientId)
+	}
+	targetApplicationId := clientIdInfo[0]
+	targetIP := clientIdInfo[1]
+	targetPort,_ := strconv.Atoi(clientIdInfo[2])
+
+	applicationMap,ok := rm_sessions.Load(resourceId)
+	if targetApplicationId == "" || !ok || applicationMap == nil {
+		logging.Logger.Infof("No channel is available for resource[%s]",resourceId)
+	}
+	appMap,_ := applicationMap.(*sync.Map)
+
+	clientIpMap,clientIpMapLoaded := appMap.Load(targetApplicationId)
+	if clientIpMapLoaded {
+		ipMap,_ := clientIpMap.(*sync.Map)
+
+		portMap,portMapLoaded := ipMap.Load(targetIP)
+		if portMapLoaded {
+			pMap,_ := portMap.(*sync.Map)
+			context,contextLoaded := pMap.Load(targetPort)
+			// Firstly, try to find the original channel through which the branch was registered.
+			if contextLoaded {
+				rpcContext := context.(*RpcContext)
+				if !rpcContext.session.IsClosed() {
+					resultSession = rpcContext.session
+					logging.Logger.Debugf("Just got exactly the one %v for %s",rpcContext.session,clientId)
+				} else {
+					pMap.Delete(targetPort)
+					logging.Logger.Infof("Removed inactive %d",rpcContext.session)
+				}
+			}
+
+			// The original channel was broken, try another one.
+			if resultSession == nil {
+				pMap.Range(func (key interface{},value interface{}) bool {
+					rpcContext := value.(*RpcContext)
+
+					if !rpcContext.session.IsClosed() {
+						resultSession = rpcContext.session
+						logging.Logger.Infof("Choose %v on the same IP[%s] as alternative of %s",rpcContext.session,targetIP,clientId)
+						//跳出 range 循环
+						return false
+					} else {
+						pMap.Delete(key)
+						logging.Logger.Infof("Removed inactive %d",rpcContext.session)
+					}
+					return true
+				})
+			}
+		}
+
+		// No channel on the this app node, try another one.
+		if resultSession == nil {
+			ipMap.Range(func (key interface{},value interface{}) bool {
+				ip := key.(string)
+				if ip == targetIP { return true }
+
+				portMapOnOtherIP,_ := value.(*sync.Map)
+				if portMapOnOtherIP == nil { return true }
+
+				portMapOnOtherIP.Range(func (key interface{},value interface {}) bool {
+					rpcContext := value.(*RpcContext)
+
+					if !rpcContext.session.IsClosed() {
+						resultSession = rpcContext.session
+						logging.Logger.Infof("Choose %v on the same application[%s] as alternative of %s",rpcContext.session,targetApplicationId,clientId)
+						//跳出 range 循环
+						return false
+					} else {
+						portMapOnOtherIP.Delete(key)
+						logging.Logger.Infof("Removed inactive %d",rpcContext.session)
+					}
+					return true
+				})
+
+				if resultSession != nil { return false }
+				return true
+			})
+		}
+	}
+
+	if resultSession == nil {
+		resultSession = tryOtherApp(appMap,targetApplicationId)
+		if resultSession == nil {
+			logging.Logger.Infof("No channel is available for resource[%s] as alternative of %s",resourceId,clientId)
+		} else {
+			logging.Logger.Infof("Choose %v on the same resource[%s] as alternative of %s", resultSession, resourceId, clientId)
+		}
+	}
+	return resultSession,nil
+}
+
+func tryOtherApp(applicationMap *sync.Map,myApplicationId string) getty.Session {
+	var chosenChannel getty.Session
+	applicationMap.Range(func (key interface{},value interface{}) bool {
+		applicationId := key.(string)
+		if myApplicationId != "" && applicationId == myApplicationId {return true}
+
+		targetIPMap,_ := value.(*sync.Map)
+		targetIPMap.Range(func (key interface{},value interface{}) bool {
+			if value == nil { return true }
+			portMap,_ := value.(*sync.Map)
+
+			portMap.Range(func (key interface{},value interface{}) bool {
+				rpcContext := value.(*RpcContext)
+				if !rpcContext.session.IsClosed() {
+					chosenChannel = rpcContext.session
+					return false
+				} else {
+					portMap.Delete(key)
+					logging.Logger.Infof("Removed inactive %d",rpcContext.session)
+				}
+				return true
+			})
+			if chosenChannel != nil { return false }
+			return true
+		})
+		if chosenChannel != nil { return false }
+		return true
+	})
+	return chosenChannel
+}
+
+
+
+func buildGettySessionHolder(role meta.TransactionRole,version string,applicationId string,
+	txServiceGroup string,dbKeys string,session getty.Session) *RpcContext {
+	return &RpcContext{
+		ClientRole:              role,
+		Version:                 version,
+		ApplicationId:           applicationId,
+		TransactionServiceGroup: txServiceGroup,
+		ClientId:                buildClientId(applicationId,session),
+		session:                 session,
+		ResourceSets:            dbKeyToSet(dbKeys),
+	}
+}
+
+func dbKeyToSet(dbKey string) *model.Set {
+	if dbKey == "" {
+		return nil
+	}
+	keys := strings.Split(dbKey,DbkeysSplitChar)
+	set := model.NewSet()
+	for _,key := range keys {
+		set.Add(key)
+	}
+	return set
+}
+
+func buildClientId(applicationId string, session getty.Session) string {
+	return applicationId + ClientIdSplitChar + session.RemoteAddr()
+}
+
+
+func (manager *GettySessionManager) GetRmSessions() map[string]getty.Session {
+	sessions := make(map[string]getty.Session)
+	rm_sessions.Range(func (key interface{},value interface{}) bool {
+		resourceId,_ := key.(string)
+		applicationMap := value.(*sync.Map)
+		session := tryOtherApp(applicationMap,"")
+		if session == nil {
+			return false
+		}
+		sessions[resourceId] = session
+		return true
+	})
+	return sessions
+}
\ No newline at end of file
diff --git a/tc/server/readwriter.go b/tc/server/readwriter.go
new file mode 100644
index 0000000..e5acff5
--- /dev/null
+++ b/tc/server/readwriter.go
@@ -0,0 +1,190 @@
+package server
+
+import (
+	"bytes"
+	"github.com/dubbogo/getty"
+	"github.com/pkg/errors"
+	"github.com/dk-lockdown/seata-golang/protocal"
+	"github.com/dk-lockdown/seata-golang/protocal/codec"
+	"vimagination.zapto.org/byteio"
+)
+
+/**
+ * <pre>
+ * 0     1     2     3     4     5     6     7     8     9    10     11    12    13    14    15    16
+ * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * |   magic   |Proto|     Full length       |    Head   | Msg |Seria|Compr|     RequestId         |
+ * |   code    |colVer|    (head+body)       |   Length  |Type |lizer|ess  |                       |
+ * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
+ * |                                                                                               |
+ * |                                   Head Map [Optional]                                         |
+ * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
+ * |                                                                                               |
+ * |                                         body                                                  |
+ * |                                                                                               |
+ * |                                        ... ...                                                |
+ * +-----------------------------------------------------------------------------------------------+
+ * </pre>
+ * <p>
+ * <li>Full Length: include all data </li>
+ * <li>Head Length: include head data from magic code to head map. </li>
+ * <li>Body Length: Full Length - Head Length</li>
+ * </p>
+ * https://github.com/seata/seata/issues/893
+ */
+
+var (
+	RpcServerPkgHandler = &RpcServerPackageHandler{}
+)
+
+type RpcServerPackageHandler struct{}
+
+func (p *RpcServerPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(data)}
+
+	b0,_ := r.ReadByte()
+	b1,_ := r.ReadByte()
+
+	if b0 != protocal.MAGIC_CODE_BYTES[0] || b1 != protocal.MAGIC_CODE_BYTES[1] {
+		return nil,0,errors.Errorf("Unknown magic code: %b,%b",b0,b1)
+	}
+
+	r.ReadByte()
+	// TODO  check version compatible here
+
+	fullLength,_,_ := r.ReadInt32()
+	headLength,_,_ := r.ReadInt16()
+	messageType,_ := r.ReadByte()
+	codecType,_ := r.ReadByte()
+	compressorType,_ := r.ReadByte()
+	requestId,_,_ := r.ReadInt32()
+
+	rpcMessage := protocal.RpcMessage{
+		Codec:codecType,
+		Id:requestId,
+		Compressor:compressorType,
+		MessageType:messageType,
+	}
+
+	headMapLength := headLength - protocal.V1_HEAD_LENGTH
+	if headMapLength > 0 {
+		rpcMessage.HeadMap = headMapDecode(data[protocal.V1_HEAD_LENGTH+1:headMapLength])
+	}
+
+	if messageType == protocal.MSGTYPE_HEARTBEAT_REQUEST {
+		rpcMessage.Body = protocal.HeartBeatMessagePing
+	} else if messageType == protocal.MSGTYPE_HEARTBEAT_RESPONSE {
+		rpcMessage.Body = protocal.HeartBeatMessagePong
+	} else {
+		bodyLength := fullLength - int32(headLength)
+		if bodyLength > 0 {
+			//todo compress
+
+			msg,_ := codec.MessageDecoder(codecType,data[headLength:])
+			rpcMessage.Body = msg
+		}
+	}
+
+	return rpcMessage, int(fullLength), nil
+}
+
+func (p *RpcServerPackageHandler) Write(ss getty.Session, pkg interface{})  ([]byte, error) {
+	var result = make([]byte,0)
+	msg := pkg.(protocal.RpcMessage)
+
+	fullLength := protocal.V1_HEAD_LENGTH
+	headLength := protocal.V1_HEAD_LENGTH
+
+	var b bytes.Buffer
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	result = append(result, protocal.MAGIC_CODE_BYTES[:2]...)
+	result = append(result, protocal.VERSION)
+
+	w.WriteByte(msg.MessageType)
+	w.WriteByte(msg.Codec)
+	w.WriteByte(msg.Compressor)
+	w.WriteInt32(msg.Id)
+
+	if msg.HeadMap != nil && len(msg.HeadMap) > 0 {
+		headMapBytes,headMapLength := headMapEncode(msg.HeadMap)
+		headLength += headMapLength
+		fullLength += headMapLength
+		w.Write(headMapBytes)
+	}
+
+	if msg.MessageType != protocal.MSGTYPE_HEARTBEAT_REQUEST &&
+		msg.MessageType != protocal.MSGTYPE_HEARTBEAT_RESPONSE {
+		bodyBytes := codec.MessageEncoder(msg.Codec,msg.Body)
+		fullLength += len(bodyBytes)
+		w.Write(bodyBytes)
+	}
+
+	fullLen := int32(fullLength)
+	headLen := int16(headLength)
+	result = append(result, []byte{ byte(fullLen>>26),byte(fullLen>>16),byte(fullLen>>8),byte(fullLen) }...)
+	result = append(result, []byte{ byte(headLen>>8),byte(headLen) }...)
+	result = append(result,b.Bytes()...)
+
+	return result, nil
+}
+
+
+func headMapDecode(data []byte) map[string]string {
+	mp := make(map[string]string)
+	size := len(data)
+	if size == 0 {
+		return mp
+	}
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(data)}
+
+	readLength := 0
+	for {
+		if readLength >= size { break }
+
+		var key, value string
+		lengthK,_,_ := r.ReadUint16()
+		if lengthK < 0 {
+			break
+		} else if lengthK == 0 {
+			key = ""
+		} else {
+			key,_,_ = r.ReadString(int(lengthK))
+		}
+
+		lengthV,_,_ := r.ReadUint16()
+		if lengthV < 0 {
+			break
+		} else if lengthV == 0 {
+			value = ""
+		} else {
+			value,_,_ = r.ReadString(int(lengthV))
+		}
+
+		mp[key] = value
+		readLength += int(lengthK + lengthV)
+	}
+	return mp
+}
+
+func headMapEncode(data map[string]string) ([]byte,int) {
+	var b bytes.Buffer
+
+	w := byteio.BigEndianWriter{Writer: &b}
+	for k,v := range data{
+		if k == "" {
+			w.WriteUint16(0)
+		} else {
+			w.WriteUint16(uint16(len(k)))
+			w.WriteString(k)
+		}
+
+		if v == "" {
+			w.WriteUint16(0)
+		} else {
+			w.WriteUint16(uint16(len(v)))
+			w.WriteString(v)
+		}
+	}
+	return b.Bytes(),b.Len()
+}
\ No newline at end of file
diff --git a/tc/server/rpc_context.go b/tc/server/rpc_context.go
new file mode 100644
index 0000000..11ac2eb
--- /dev/null
+++ b/tc/server/rpc_context.go
@@ -0,0 +1,136 @@
+package server
+
+import (
+	"errors"
+	"github.com/dubbogo/getty"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/model"
+	"strconv"
+	"strings"
+	"sync"
+)
+
+const IpPortSplitChar = ":"
+
+type RpcContext struct {
+	ClientRole meta.TransactionRole
+	Version string
+	ApplicationId string
+	TransactionServiceGroup string
+	ClientId string
+	session getty.Session
+	ResourceSets *model.Set
+
+	/**
+	 * <getty.Session,*RpcContext>
+	 */
+	ClientIDHolderMap *sync.Map
+
+	/**
+	 * <int,RpcContext>
+	 */
+	ClientTMHolderMap *sync.Map
+
+	/**
+	 * resourceId -> int -> RpcContext>
+	 */
+	ClientRMHolderMap *sync.Map
+}
+
+func (context *RpcContext) Release() {
+	clientPort := getClientPortFromGettySession(context.session)
+	if context.ClientIDHolderMap != nil {
+		context.ClientIDHolderMap = nil
+	}
+	if context.ClientRole == meta.TMROLE && context.ClientTMHolderMap != nil {
+		context.ClientTMHolderMap.Delete(clientPort)
+		context.ClientTMHolderMap = nil
+	}
+	if context.ClientRole == meta.RMROLE && context.ClientRMHolderMap != nil {
+		context.ClientRMHolderMap.Range(func (key interface{}, value interface{}) bool {
+			m := value.(*sync.Map)
+			m.Delete(clientPort)
+			return true
+		})
+		context.ClientRMHolderMap = nil
+	}
+	if context.ResourceSets != nil {
+		context.ResourceSets.Clear()
+	}
+}
+
+func (context *RpcContext) HoldInClientGettySessions(clientTMHolderMap *sync.Map) error {
+	if context.ClientTMHolderMap != nil {
+		return errors.New("illegal state")
+	}
+	context.ClientTMHolderMap = clientTMHolderMap
+	clientPort := getClientPortFromGettySession(context.session)
+	context.ClientTMHolderMap.Store(clientPort,context)
+	return nil
+}
+
+func (context *RpcContext) HoldInIdentifiedGettySessions(clientIDHolderMap *sync.Map) error {
+	if context.ClientIDHolderMap != nil {
+		return errors.New("illegal state")
+	}
+	context.ClientIDHolderMap = clientIDHolderMap
+	context.ClientIDHolderMap.Store(context.session,context)
+	return nil
+}
+
+func (context *RpcContext) HoldInResourceManagerGettySessions(resourceId string,portMap *sync.Map) {
+	if context.ClientRMHolderMap == nil {
+		context.ClientRMHolderMap = &sync.Map{}
+	}
+	clientPort := getClientPortFromGettySession(context.session)
+	portMap.Store(clientPort,context)
+	context.ClientRMHolderMap.Store(resourceId,portMap)
+}
+
+func (context *RpcContext) HoldInResourceManagerGettySessionsWithoutPortMap(resourceId string,clientPort int) {
+	if context.ClientRMHolderMap == nil {
+		context.ClientRMHolderMap = &sync.Map{}
+	}
+	portMap,_ := context.ClientRMHolderMap.LoadOrStore(resourceId,&sync.Map{})
+	pm := portMap.(*sync.Map)
+	pm.Store(clientPort,context)
+}
+
+func (context *RpcContext) AddResource(resource string) {
+	if resource != "" {
+		if context.ResourceSets == nil {
+			context.ResourceSets = model.NewSet()
+		}
+		context.ResourceSets.Add(resource)
+	}
+}
+
+func (context *RpcContext) AddResources(resources *model.Set) {
+	if resources != nil {
+		if context.ResourceSets == nil {
+			context.ResourceSets = model.NewSet()
+		}
+		for _,resource := range resources.List() {
+			context.ResourceSets.Add(resource)
+		}
+	}
+}
+
+func getClientIpFromGettySession(session getty.Session) string {
+	clientIp := session.RemoteAddr()
+	if strings.Contains(clientIp,IpPortSplitChar) {
+		idx := strings.Index(clientIp,IpPortSplitChar)
+		clientIp = clientIp[:idx]
+	}
+	return clientIp
+}
+
+func getClientPortFromGettySession(session getty.Session) int {
+	address := session.RemoteAddr()
+	port := 0
+	if strings.Contains(address,IpPortSplitChar) {
+		idx := strings.LastIndex(address,IpPortSplitChar)
+		port,_ = strconv.Atoi(address[idx+1:])
+	}
+	return port
+}
\ No newline at end of file
diff --git a/tc/server/server.go b/tc/server/server.go
new file mode 100644
index 0000000..1aecd88
--- /dev/null
+++ b/tc/server/server.go
@@ -0,0 +1,121 @@
+package server
+
+import (
+	"fmt"
+	"net"
+	"os"
+	"os/signal"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/tc/config"
+	"syscall"
+	"time"
+)
+
+import (
+	"github.com/dubbogo/getty"
+	"github.com/dubbogo/gost/sync"
+)
+
+var (
+	srvGrpool *gxsync.TaskPool
+)
+
+
+func SetServerGrpool() {
+	srvConf := config.GetServerConfig()
+	if srvConf.GettyConfig.GrPoolSize > 1 {
+		srvGrpool = gxsync.NewTaskPool(gxsync.WithTaskPoolTaskPoolSize(srvConf.GettyConfig.GrPoolSize),
+			gxsync.WithTaskPoolTaskQueueLength(srvConf.GettyConfig.QueueLen),
+			gxsync.WithTaskPoolTaskQueueNumber(srvConf.GettyConfig.QueueNumber))
+	}
+}
+
+type Server struct {
+	conf       config.ServerConfig
+	tcpServer  getty.Server
+	rpcHandler *DefaultCoordinator
+}
+
+func NewServer() *Server {
+
+	s := &Server{
+		conf: config.GetServerConfig(),
+	}
+	coordinator := NewDefaultCoordinator(s.conf)
+	s.rpcHandler = coordinator
+
+	return s
+}
+
+func (s *Server) newSession(session getty.Session) error {
+	var (
+		ok      bool
+		tcpConn *net.TCPConn
+	)
+	conf := s.conf
+
+	if conf.GettyConfig.GettySessionParam.CompressEncoding {
+		session.SetCompressType(getty.CompressZip)
+	}
+
+	if tcpConn, ok = session.Conn().(*net.TCPConn); !ok {
+		panic(fmt.Sprintf("%s, session.conn{%#v} is not tcp connection\n", session.Stat(), session.Conn()))
+	}
+
+	tcpConn.SetNoDelay(conf.GettyConfig.GettySessionParam.TcpNoDelay)
+	tcpConn.SetKeepAlive(conf.GettyConfig.GettySessionParam.TcpKeepAlive)
+	if conf.GettyConfig.GettySessionParam.TcpKeepAlive {
+		tcpConn.SetKeepAlivePeriod(conf.GettyConfig.GettySessionParam.KeepAlivePeriod)
+	}
+	tcpConn.SetReadBuffer(conf.GettyConfig.GettySessionParam.TcpRBufSize)
+	tcpConn.SetWriteBuffer(conf.GettyConfig.GettySessionParam.TcpWBufSize)
+
+	session.SetName(conf.GettyConfig.GettySessionParam.SessionName)
+	session.SetMaxMsgLen(conf.GettyConfig.GettySessionParam.MaxMsgLen)
+	session.SetPkgHandler(RpcServerPkgHandler)
+	session.SetEventListener(s.rpcHandler)
+	session.SetWQLen(conf.GettyConfig.GettySessionParam.PkgWQSize)
+	session.SetReadTimeout(conf.GettyConfig.GettySessionParam.TcpReadTimeout)
+	session.SetWriteTimeout(conf.GettyConfig.GettySessionParam.TcpWriteTimeout)
+	session.SetCronPeriod((int)(conf.GettyConfig.SessionTimeout.Nanoseconds() / 1e6))
+	session.SetWaitTime(conf.GettyConfig.GettySessionParam.WaitTimeout)
+	logging.Logger.Debugf("app accepts new session:%s\n", session.Stat())
+
+	session.SetTaskPool(srvGrpool)
+
+	return nil
+}
+
+func (s *Server) Start(addr string) {
+	var (
+		tcpServer getty.Server
+	)
+
+	tcpServer = getty.NewTCPServer(
+		getty.WithLocalAddress(addr),
+	)
+	tcpServer.RunEventLoop(s.newSession)
+	logging.Logger.Debugf("s bind addr{%s} ok!", addr)
+	s.tcpServer = tcpServer
+
+	c := make(chan os.Signal, 1)
+	signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
+	for {
+		sig := <-c
+		logging.Logger.Info("get a signal %s", sig.String())
+		switch sig {
+		case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
+			s.Stop()
+			time.Sleep(time.Second)
+			return
+		case syscall.SIGHUP:
+		default:
+			return
+		}
+	}
+}
+
+func (s *Server) Stop() {
+	s.tcpServer.Close()
+	s.rpcHandler.Stop()
+}
diff --git a/tc/server/server_message_listener.go b/tc/server/server_message_listener.go
new file mode 100644
index 0000000..56fff60
--- /dev/null
+++ b/tc/server/server_message_listener.go
@@ -0,0 +1,16 @@
+package server
+
+import (
+	"github.com/dubbogo/getty"
+	"github.com/dk-lockdown/seata-golang/protocal"
+)
+
+type IServerMessageListener interface {
+	OnTrxMessage(rpcMessage protocal.RpcMessage, session getty.Session)
+
+	OnRegRmMessage(request protocal.RpcMessage, session getty.Session)
+
+	OnRegTmMessage(request protocal.RpcMessage, session getty.Session)
+
+	OnCheckMessage(request protocal.RpcMessage, session getty.Session)
+}
\ No newline at end of file
diff --git a/tc/server/server_message_sender.go b/tc/server/server_message_sender.go
new file mode 100644
index 0000000..94f7f3d
--- /dev/null
+++ b/tc/server/server_message_sender.go
@@ -0,0 +1,78 @@
+package server
+
+import (
+	"github.com/dubbogo/getty"
+	"github.com/dk-lockdown/seata-golang/protocal"
+	"time"
+)
+
+type IServerMessageSender interface {
+	/**
+	 * Send response.
+	 *
+	 * @param request the request
+	 * @param channel the channel
+	 * @param msg     the msg
+	 */
+
+	SendResponse(request protocal.RpcMessage, session getty.Session, msg interface{})
+
+	/**
+	 * Sync call to RM
+	 *
+	 * @param resourceId Resource ID
+	 * @param clientId   Client ID
+	 * @param message    Request message
+	 * @return Response message
+	 * @throws IOException .
+	 * @throws TimeoutException the timeout exception
+	 */
+	SendSyncRequest(resourceId string, clientId string, message interface{}) (interface{},error)
+
+	/**
+	 * Sync call to RM with timeout.
+	 *
+	 * @param resourceId Resource ID
+	 * @param clientId   Client ID
+	 * @param message    Request message
+	 * @param timeout    timeout of the call
+	 * @return Response message
+	 * @throws IOException .
+	 * @throws TimeoutException the timeout exception
+	 */
+	SendSyncRequestWithTimeout(resourceId string, clientId string, message interface{}, timeout time.Duration) (interface{},error)
+
+	/**
+	 * Send request with response object.
+	 * send syn request for rm
+	 *
+	 * @param clientChannel the client channel
+	 * @param message       the message
+	 * @return the object
+	 * @throws TimeoutException the timeout exception
+	 */
+	SendSyncRequestByGettySession(session getty.Session, message interface{}) (interface{},error)
+
+	/**
+	 * Send request with response object.
+	 * send syn request for rm
+	 *
+	 * @param clientChannel the client channel
+	 * @param message       the message
+	 * @param timeout       the timeout
+	 * @return the object
+	 * @throws TimeoutException the timeout exception
+	 */
+	SendSyncRequestByGettySessionWithTimeout(session getty.Session, message interface{}, timeout time.Duration) (interface{},error)
+
+	/**
+	 * ASync call to RM
+	 *
+	 * @param channel   channel
+	 * @param message    Request message
+	 * @return Response message
+	 * @throws IOException .
+	 * @throws TimeoutException the timeout exception
+	 */
+	SendASyncRequest(session getty.Session, message interface{}) error
+}
diff --git a/tc/server/tc_inbound_handler.go b/tc/server/tc_inbound_handler.go
new file mode 100644
index 0000000..e8395c8
--- /dev/null
+++ b/tc/server/tc_inbound_handler.go
@@ -0,0 +1,14 @@
+package server
+
+import "github.com/dk-lockdown/seata-golang/protocal"
+
+type TCInboundHandler interface {
+	doGlobalBegin(request protocal.GlobalBeginRequest,ctx RpcContext) protocal.GlobalBeginResponse
+	doGlobalStatus(request protocal.GlobalStatusRequest,ctx RpcContext) protocal.GlobalStatusResponse
+	doGlobalReport(request protocal.GlobalReportRequest,ctx RpcContext) protocal.GlobalReportResponse
+	doGlobalCommit(request protocal.GlobalCommitRequest,ctx RpcContext) protocal.GlobalCommitResponse
+	doGlobalRollback(request protocal.GlobalRollbackRequest,ctx RpcContext) protocal.GlobalRollbackResponse
+	doBranchRegister(request protocal.BranchRegisterRequest,ctx RpcContext) protocal.BranchRegisterResponse
+	doBranchReport(request protocal.BranchReportRequest,ctx RpcContext) protocal.BranchReportResponse
+	doLockCheck(request protocal.GlobalLockQueryRequest,ctx RpcContext) protocal.GlobalLockQueryResponse
+}
\ No newline at end of file
diff --git a/tc/server/transaction_coordinator.go b/tc/server/transaction_coordinator.go
new file mode 100644
index 0000000..ca1e7d1
--- /dev/null
+++ b/tc/server/transaction_coordinator.go
@@ -0,0 +1,73 @@
+package server
+
+import (
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/rm"
+	"github.com/dk-lockdown/seata-golang/tc/session"
+	"github.com/dk-lockdown/seata-golang/tm"
+)
+
+type ITransactionCoordinatorInbound interface {
+	tm.ITransactionManager
+	rm.IResourceManagerOutbound
+}
+
+type ITransactionCoordinatorOutbound interface {
+	/**
+	 * Commit a branch transaction.
+	 *
+	 * @param globalSession the global session
+	 * @param branchSession the branch session
+	 * @return Status of the branch after committing.
+	 * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
+	 *                              out.
+	 */
+	branchCommit(globalSession *session.GlobalSession, branchSession *session.BranchSession) (meta.BranchStatus, error)
+
+	/**
+	 * Rollback a branch transaction.
+	 *
+	 * @param globalSession the global session
+	 * @param branchSession the branch session
+	 * @return Status of the branch after rollbacking.
+	 * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
+	 *                              out.
+	 */
+	branchRollback(globalSession *session.GlobalSession, branchSession *session.BranchSession) (meta.BranchStatus, error)
+
+}
+
+type ITransactionCoordinator interface {
+	ITransactionCoordinatorInbound
+	ITransactionCoordinatorOutbound
+
+	/**
+	 * Do global commit.
+	 *
+	 * @param globalSession the global session
+	 * @param retrying      the retrying
+	 * @return is global commit.
+	 * @throws TransactionException the transaction exception
+	 */
+	doGlobalCommit(globalSession *session.GlobalSession, retrying bool) (bool, error)
+
+	/**
+	 * Do global rollback.
+	 *
+	 * @param globalSession the global session
+	 * @param retrying      the retrying
+	 * @return is global rollback.
+	 * @throws TransactionException the transaction exception
+	 */
+	doGlobalRollback(globalSession *session.GlobalSession, retrying bool) (bool, error)
+
+	/**
+	 * Do global report.
+	 *
+	 * @param globalSession the global session
+	 * @param xid           Transaction id.
+	 * @param param         the global status
+	 * @throws TransactionException the transaction exception
+	 */
+	doGlobalReport(globalSession *session.GlobalSession, xid string, param meta.GlobalStatus) error
+}
diff --git a/tc/session/branch_session.go b/tc/session/branch_session.go
new file mode 100644
index 0000000..881c562
--- /dev/null
+++ b/tc/session/branch_session.go
@@ -0,0 +1,230 @@
+package session
+
+import (
+	"bytes"
+	"github.com/pkg/errors"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/tc/config"
+	"github.com/dk-lockdown/seata-golang/util"
+	"vimagination.zapto.org/byteio"
+)
+
+type BranchSession struct{
+	Xid string
+
+	TransactionId int64
+
+	BranchId int64
+
+	ResourceGroupId string
+
+	ResourceId string
+
+	LockKey string
+
+	BranchType meta.BranchType
+
+	Status meta.BranchStatus
+
+	ClientId string
+
+	ApplicationData []byte
+}
+
+func NewBranchSession() *BranchSession {
+	return &BranchSession{}
+}
+
+func NewBranchSessionByGlobal(gs GlobalSession,
+								branchType meta.BranchType,
+								resourceId string,
+								applicationData []byte,
+								lockKeys string,
+								clientId string) *BranchSession {
+	bs := NewBranchSession()
+	bs.SetXid(gs.Xid)
+	bs.SetTransactionId(gs.TransactionId)
+	bs.SetBranchId(util.GeneratorUUID())
+	bs.SetBranchType(branchType)
+	bs.SetResourceId(resourceId)
+	bs.SetLockKey(lockKeys)
+	bs.SetClientId(clientId)
+	bs.SetApplicationData(applicationData)
+	return bs
+}
+
+
+func (bs *BranchSession) SetXid(xid string) *BranchSession {
+	bs.Xid = xid
+	return bs
+}
+
+func (bs *BranchSession) SetTransactionId(transactionId int64) *BranchSession {
+	bs.TransactionId = transactionId
+	return bs
+}
+
+func (bs *BranchSession) SetBranchId(branchId int64) *BranchSession {
+	bs.BranchId = branchId
+	return bs
+}
+
+
+func (bs *BranchSession) SetResourceGroupId(ResourceGroupId string) *BranchSession {
+	bs.ResourceGroupId = ResourceGroupId
+	return bs
+}
+
+func (bs *BranchSession) SetResourceId(resourceId string) *BranchSession {
+	bs.ResourceId = resourceId
+	return bs
+}
+
+func (bs *BranchSession) SetLockKey(lockKey string) *BranchSession {
+	bs.LockKey = lockKey
+	return bs
+}
+
+func (bs *BranchSession) SetBranchType(branchType meta.BranchType) *BranchSession {
+	bs.BranchType = branchType
+	return bs
+}
+
+func (bs *BranchSession) SetStatus(status meta.BranchStatus) *BranchSession {
+	bs.Status = status
+	return bs
+}
+
+func (bs *BranchSession) SetClientId(clientId string) *BranchSession {
+	bs.ClientId = clientId
+	return bs
+}
+
+func (bs *BranchSession) SetApplicationData(applicationData []byte) *BranchSession {
+	bs.ApplicationData = applicationData
+	return bs
+}
+
+func (bs *BranchSession) CompareTo(session *BranchSession) int {
+	return int(bs.BranchId - session.BranchId)
+}
+
+func (bs *BranchSession) Encode() ([]byte, error) {
+	var (
+		zero32 int32 = 0
+		zero16 int16 = 0
+	)
+
+	size := calBranchSessionSize(len(bs.ResourceId),len(bs.LockKey),len(bs.ClientId),len(bs.ApplicationData),len(bs.Xid))
+
+	if size > config.GetStoreConfig().MaxBranchSessionSize {
+		if bs.LockKey == "" {
+			logging.Logger.Errorf("branch session size exceeded, size : %d maxBranchSessionSize : %d", size, config.GetStoreConfig().MaxBranchSessionSize)
+			//todo compress
+			return nil, errors.New("branch session size exceeded.")
+		}
+	}
+
+	var b bytes.Buffer
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	w.WriteInt64(bs.TransactionId)
+	w.WriteInt64(bs.BranchId)
+	if bs.ResourceId != "" {
+		w.WriteUint32(uint32(len(bs.ResourceId)))
+		w.WriteString( bs.ResourceId)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	if bs.LockKey != "" {
+		w.WriteUint32(uint32(len(bs.LockKey)))
+		w.WriteString( bs.LockKey)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	if bs.ClientId != "" {
+		w.WriteUint16(uint16(len(bs.ClientId)))
+		w.WriteString(bs.ClientId)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if bs.ApplicationData != nil {
+		w.WriteUint32(uint32(len(bs.ApplicationData)))
+		w.Write(bs.ApplicationData)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	if bs.Xid != "" {
+		w.WriteUint32(uint32(len(bs.Xid)))
+		w.WriteString( bs.Xid)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	w.WriteByte(byte(bs.BranchType))
+	w.WriteByte(byte(bs.Status))
+
+	return b.Bytes(), nil
+}
+
+func (bs *BranchSession) Decode(b []byte) {
+	var length32 uint32 = 0
+	var length16 uint16 = 0
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(b)}
+
+	bs.TransactionId, _, _ = r.ReadInt64()
+	bs.BranchId, _, _ = r.ReadInt64()
+
+	length32, _, _ = r.ReadUint32()
+	if length32 > 0 { bs.ResourceId, _, _ = r.ReadString(int(length32)) }
+
+	length32, _, _ = r.ReadUint32()
+	if length32 > 0 { bs.LockKey, _, _ = r.ReadString(int(length32)) }
+
+	length16, _, _ = r.ReadUint16()
+	if length16 > 0 { bs.ClientId, _, _ = r.ReadString(int(length16)) }
+
+	length32, _, _ = r.ReadUint32()
+	if length32 > 0 {
+		bs.ApplicationData = make([]byte,int(length32))
+		r.Read(bs.ApplicationData)
+	}
+
+	length32, _, _ = r.ReadUint32()
+	if length32 > 0 { bs.Xid, _, _ = r.ReadString(int(length32)) }
+
+	branchType, _ := r.ReadByte()
+	bs.BranchType = meta.BranchType(branchType)
+
+	status, _ := r.ReadByte()
+	bs.Status = meta.BranchStatus(status)
+}
+
+func calBranchSessionSize(resourceIdLen int,
+	lockKeyLen int,
+	clientIdLen int,
+	applicationDataLen int,
+	xidLen int) int{
+
+	size := 8 + // transactionId
+		8  + // branchId
+		4  + // resourceIdBytes.length
+		4  + // lockKeyBytes.length
+		2  + // clientIdBytes.length
+		4  + // applicationDataBytes.length
+		4  + // xidBytes.size
+		1  + // statusCode
+		resourceIdLen +
+		lockKeyLen +
+		clientIdLen +
+		applicationDataLen +
+		xidLen +
+		1
+
+	return size
+}
diff --git a/tc/session/branch_session_test.go b/tc/session/branch_session_test.go
new file mode 100644
index 0000000..9df8d23
--- /dev/null
+++ b/tc/session/branch_session_test.go
@@ -0,0 +1,37 @@
+package session
+
+import (
+	"github.com/stretchr/testify/assert"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/util"
+	"testing"
+)
+
+func TestBranchSession_Encode_Decode(t *testing.T) {
+	bs := branchSessionProvider()
+	result,_ := bs.Encode()
+	newBs := &BranchSession{}
+	newBs.Decode(result)
+
+	assert.Equal(t,bs.TransactionId,newBs.TransactionId)
+	assert.Equal(t,bs.BranchId,newBs.BranchId)
+	assert.Equal(t,bs.ResourceId,newBs.ResourceId)
+	assert.Equal(t,bs.LockKey,newBs.LockKey)
+	assert.Equal(t,bs.ClientId,newBs.ClientId)
+	assert.Equal(t,bs.ApplicationData,newBs.ApplicationData)
+}
+
+func branchSessionProvider() *BranchSession {
+	bs := NewBranchSession().
+		SetTransactionId(util.GeneratorUUID()).
+		SetBranchId(1).
+		SetResourceGroupId("my_test_tx_group").
+		SetResourceId("tb_1").
+		SetLockKey("t_1").
+		SetBranchType(meta.BranchTypeAT).
+		SetStatus(meta.BranchStatusUnknown).
+		SetClientId("c1").
+		SetApplicationData([]byte("{\"data\":\"test\"}"))
+
+	return bs
+}
\ No newline at end of file
diff --git a/tc/session/global_session.go b/tc/session/global_session.go
new file mode 100644
index 0000000..8109470
--- /dev/null
+++ b/tc/session/global_session.go
@@ -0,0 +1,297 @@
+package session
+
+import (
+	"bytes"
+	"github.com/pkg/errors"
+	"github.com/dk-lockdown/seata-golang/common"
+	"github.com/dk-lockdown/seata-golang/logging"
+	"github.com/dk-lockdown/seata-golang/meta"
+	"github.com/dk-lockdown/seata-golang/tc/config"
+	"github.com/dk-lockdown/seata-golang/util"
+	"sort"
+	"sync"
+	"vimagination.zapto.org/byteio"
+)
+
+type GlobalSession struct {
+	sync.Mutex
+
+	Xid string
+
+	TransactionId int64
+
+	Status meta.GlobalStatus
+
+	ApplicationId string
+
+	TransactionServiceGroup string
+
+	TransactionName string
+
+	Timeout int32
+
+	BeginTime int64
+
+	ApplicationData []byte
+
+	Active bool
+
+	BranchSessions map[*BranchSession]bool
+}
+
+func NewGlobalSession() *GlobalSession {
+	gs := &GlobalSession{
+		BranchSessions: make(map[*BranchSession]bool),
+	}
+	gs.TransactionId = util.GeneratorUUID()
+	gs.Xid = common.XID.GenerateXID(gs.TransactionId)
+	return gs
+}
+
+func (gs *GlobalSession) SetXid(xid string) *GlobalSession {
+	gs.Xid = xid
+	return gs
+}
+
+func (gs *GlobalSession) SetTransactionId(transactionId int64) *GlobalSession {
+	gs.TransactionId = transactionId
+	return gs
+}
+
+func (gs *GlobalSession) SetStatus(status meta.GlobalStatus) *GlobalSession {
+	gs.Status = status
+	return gs
+}
+
+func (gs *GlobalSession) SetApplicationId(applicationId string) *GlobalSession {
+	gs.ApplicationId = applicationId
+	return gs
+}
+
+func (gs *GlobalSession) SetTransactionServiceGroup(transactionServiceGroup string) *GlobalSession {
+	gs.TransactionServiceGroup = transactionServiceGroup
+	return gs
+}
+
+func (gs *GlobalSession) SetTransactionName(transactionName string) *GlobalSession {
+	gs.TransactionName = transactionName
+	return gs
+}
+
+func (gs *GlobalSession) SetTimeout(timeout int32) *GlobalSession {
+	gs.Timeout = timeout
+	return gs
+}
+
+func (gs *GlobalSession) SetBeginTime(beginTime int64) *GlobalSession {
+	gs.BeginTime = beginTime
+	return gs
+}
+
+func (gs *GlobalSession) SetApplicationData(applicationData []byte) *GlobalSession {
+	gs.ApplicationData = applicationData
+	return gs
+}
+
+func (gs *GlobalSession) SetActive(active bool) *GlobalSession {
+	gs.Active = active
+	return gs
+}
+
+func (gs *GlobalSession) Add(branchSession *BranchSession) {
+	branchSession.Status = meta.BranchStatusRegistered
+	gs.BranchSessions[branchSession] = true
+}
+
+func (gs *GlobalSession) Remove(branchSession *BranchSession) {
+	delete(gs.BranchSessions, branchSession)
+}
+
+func (gs *GlobalSession) CanBeCommittedAsync() bool {
+	for branchSession := range gs.BranchSessions {
+		if branchSession.BranchType == meta.BranchTypeTCC {
+			return false
+		}
+	}
+	return true
+}
+
+func (gs *GlobalSession) IsSaga() bool {
+	for branchSession := range gs.BranchSessions {
+		if branchSession.BranchType == meta.BranchTypeSAGA {
+			return true
+		} else {
+			return false
+		}
+	}
+	return false
+}
+
+func (gs *GlobalSession) IsTimeout() bool {
+	return (util.CurrentTimeMillis() - uint64(gs.BeginTime)) > uint64(gs.Timeout)
+}
+
+func (gs *GlobalSession) IsRollbackingDead() bool {
+	return (util.CurrentTimeMillis() - uint64(gs.BeginTime)) > uint64(2 * 6000)
+}
+
+func (gs *GlobalSession) GetSortedBranches() []*BranchSession {
+	var branchSessions = make([]*BranchSession, 0)
+
+	for branchSession := range gs.BranchSessions {
+		branchSessions = append(branchSessions, branchSession)
+	}
+	return branchSessions
+}
+
+func (gs *GlobalSession) GetReverseSortedBranches() []*BranchSession {
+	var branchSessions = gs.GetSortedBranches()
+	sort.Reverse(BranchSessionSlice(branchSessions))
+	return branchSessions
+}
+
+type BranchSessionSlice []*BranchSession
+
+func (p BranchSessionSlice) Len() int           { return len(p) }
+func (p BranchSessionSlice) Less(i, j int) bool { return p[i].CompareTo(p[j]) > 0 }
+func (p BranchSessionSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+func (gs *GlobalSession) GetBranch(branchId int64) *BranchSession {
+	gs.Lock()
+	defer gs.Unlock()
+	for branchSession := range gs.BranchSessions {
+		if branchSession.BranchId == branchId {
+			return branchSession
+		}
+	}
+	return nil
+}
+
+func (gs *GlobalSession) HasBranch() bool {
+	return len(gs.BranchSessions) > 0
+}
+
+func (gs *GlobalSession) Begin() {
+	gs.Status = meta.GlobalStatusBegin
+	gs.BeginTime = int64(util.CurrentTimeMillis())
+	gs.Active = true
+}
+
+func (gs *GlobalSession) Encode() ([]byte, error) {
+	var (
+		zero32 int32 = 0
+		zero16 int16 = 0
+	)
+
+	size := calGlobalSessionSize(len(gs.ApplicationId),len(gs.TransactionServiceGroup),len(gs.TransactionName),len(gs.Xid),len(gs.ApplicationData))
+
+	if size > config.GetStoreConfig().MaxGlobalSessionSize {
+		logging.Logger.Errorf("global session size exceeded, size : %d maxBranchSessionSize : %d", size, config.GetStoreConfig().MaxGlobalSessionSize)
+		//todo compress
+		return nil, errors.New("global session size exceeded.")
+	}
+
+	var b bytes.Buffer
+	w := byteio.BigEndianWriter{Writer: &b}
+
+	w.WriteInt64(gs.TransactionId)
+	w.WriteInt32(gs.Timeout)
+
+	// applicationId 长度不会超过 256
+	if gs.ApplicationId != "" {
+		w.WriteUint16(uint16(len(gs.ApplicationId)))
+		w.WriteString(gs.ApplicationId)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if gs.TransactionServiceGroup != "" {
+		w.WriteUint16(uint16(len(gs.TransactionServiceGroup)))
+		w.WriteString(gs.TransactionServiceGroup)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if gs.TransactionName != "" {
+		w.WriteUint16(uint16(len(gs.TransactionName)))
+		w.WriteString(gs.TransactionName)
+	} else {
+		w.WriteInt16(zero16)
+	}
+
+	if gs.Xid != "" {
+		w.WriteUint32(uint32(len(gs.Xid)))
+		w.WriteString(gs.Xid)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	if gs.ApplicationData != nil {
+		w.WriteUint32(uint32(len(gs.ApplicationData)))
+		w.Write(gs.ApplicationData)
+	} else {
+		w.WriteInt32(zero32)
+	}
+
+	w.WriteInt64(gs.BeginTime)
+	w.WriteByte(byte(gs.Status))
+
+	return b.Bytes(), nil
+}
+
+func (gs *GlobalSession) Decode(b []byte) {
+	var length32 uint32 = 0
+	var length16 uint16 = 0
+	r := byteio.BigEndianReader{Reader:bytes.NewReader(b)}
+
+	gs.TransactionId, _, _ = r.ReadInt64()
+	gs.Timeout, _, _ = r.ReadInt32()
+
+	length16, _, _ = r.ReadUint16()
+	if length16 > 0 { gs.ApplicationId, _, _ = r.ReadString(int(length16)) }
+
+	length16, _, _ = r.ReadUint16()
+	if length16 > 0 { gs.TransactionServiceGroup, _, _ = r.ReadString(int(length16)) }
+
+	length16, _, _ = r.ReadUint16()
+	if length16 > 0 { gs.TransactionName, _, _ = r.ReadString(int(length16)) }
+
+	length32, _, _ = r.ReadUint32()
+	if length32 > 0 { gs.Xid, _, _ = r.ReadString(int(length32)) }
+
+	length32, _, _ = r.ReadUint32()
+	if length32 > 0 {
+		gs.ApplicationData = make([]byte,length32,length32)
+		r.Read(gs.ApplicationData)
+	}
+
+	gs.BeginTime, _, _ = r.ReadInt64()
+
+	status, _ := r.ReadByte()
+	gs.Status = meta.GlobalStatus(status)
+}
+
+func calGlobalSessionSize(	applicationIdLen int,
+	serviceGroupLen int,
+	txNameLen int,
+	xidLen int,
+	applicationDataLen int,
+	) int{
+
+	size := 8 + // transactionId
+		4  + // timeout
+		2  + // byApplicationIdBytes.length
+		2  + // byServiceGroupBytes.length
+		2  + // byTxNameBytes.length
+		4  + // xidBytes.length
+		4  + // applicationDataBytes.length
+		8  + // beginTime
+		1  + // statusCode
+		applicationIdLen +
+		serviceGroupLen +
+		txNameLen +
+		xidLen +
+		applicationDataLen
+
+	return size
+}
\ No newline at end of file
diff --git a/tc/session/global_session_test.go b/tc/session/global_session_test.go
new file mode 100644
index 0000000..d28e936
--- /dev/null
+++ b/tc/session/global_session_test.go
@@ -0,0 +1,31 @@
+package session
+
+import (
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestGlobalSession_Encode_Decode(t *testing.T) {
+	gs := globalSessionProvider()
+	result, _ := gs.Encode()
+
+	newGs := &GlobalSession{}
+	newGs.Decode(result)
+
+	assert.Equal(t,newGs.TransactionId,gs.TransactionId)
+	assert.Equal(t,newGs.Timeout,gs.Timeout)
+	assert.Equal(t,newGs.ApplicationId,gs.ApplicationId)
+	assert.Equal(t,newGs.TransactionServiceGroup,gs.TransactionServiceGroup)
+	assert.Equal(t,newGs.TransactionName,gs.TransactionName)
+}
+
+func globalSessionProvider() *GlobalSession{
+	gs := NewGlobalSession().
+		SetApplicationId("demo-app").
+		SetTransactionServiceGroup("my_test_tx_group").
+		SetTransactionName("test").
+		SetTimeout(6000).
+		SetActive(true)
+
+	return gs
+}
\ No newline at end of file
diff --git a/tc/session/session_storable.go b/tc/session/session_storable.go
new file mode 100644
index 0000000..b2a8b45
--- /dev/null
+++ b/tc/session/session_storable.go
@@ -0,0 +1,17 @@
+package session
+
+type SessionStorable interface {
+	/**
+	 * Encode byte [ ].
+	 *
+	 * @return the byte [ ]
+	 */
+	Encode() ([]byte, error)
+
+	/**
+	 * Decode.
+	 *
+	 * @param src the src
+	 */
+	Decode(src []byte)
+}
diff --git a/tm/transaction_manager.go b/tm/transaction_manager.go
new file mode 100644
index 0000000..635444e
--- /dev/null
+++ b/tm/transaction_manager.go
@@ -0,0 +1,59 @@
+package tm
+
+import "github.com/dk-lockdown/seata-golang/meta"
+
+type ITransactionManager interface {
+	/**
+	 * GlobalStatus_Begin a new global transaction.
+	 *
+	 * @param applicationId           ID of the application who begins this transaction.
+	 * @param transactionServiceGroup ID of the transaction service group.
+	 * @param name                    Give a name to the global transaction.
+	 * @param timeout                 Timeout of the global transaction.
+	 * @return XID of the global transaction
+	 * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
+	 * out.
+	 */
+	Begin(applicationId string, transactionServiceGroup string, name string, timeout int32) (string, error)
+
+	/**
+	 * Global commit.
+	 *
+	 * @param xid XID of the global transaction.
+	 * @return Status of the global transaction after committing.
+	 * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
+	 * out.
+	 */
+	Commit(xid string) (meta.GlobalStatus, error)
+
+	/**
+	 * Global rollback.
+	 *
+	 * @param xid XID of the global transaction
+	 * @return Status of the global transaction after rollbacking.
+	 * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
+	 * out.
+	 */
+	Rollback(xid string) (meta.GlobalStatus, error)
+
+	/**
+	 * Get current status of the give transaction.
+	 *
+	 * @param xid XID of the global transaction.
+	 * @return Current status of the global transaction.
+	 * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
+	 * out.
+	 */
+	GetStatus(xid string) (meta.GlobalStatus, error)
+
+	/**
+	 * Global report.
+	 *
+	 * @param xid XID of the global transaction.
+	 * @param globalStatus Status of the global transaction.
+	 * @return Status of the global transaction.
+	 * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
+	 * out.
+	 */
+	GlobalReport(xid string, globalStatus meta.GlobalStatus) (meta.GlobalStatus, error)
+}
diff --git a/util/hashcode.go b/util/hashcode.go
new file mode 100644
index 0000000..00055f0
--- /dev/null
+++ b/util/hashcode.go
@@ -0,0 +1,35 @@
+package util
+
+import (
+	"bytes"
+	"fmt"
+	"hash/crc32"
+)
+
+// String hashes a string to a unique hashcode.
+//
+// crc32 returns a uint32, but for our use we need
+// and non negative integer. Here we cast to an integer
+// and invert it if the result is negative.
+func String(s string) int {
+	v := int(crc32.ChecksumIEEE([]byte(s)))
+	if v >= 0 {
+		return v
+	}
+	if -v >= 0 {
+		return -v
+	}
+	// v == MinInt
+	return 0
+}
+
+// Strings hashes a list of strings to a unique hashcode.
+func Strings(strings []string) string {
+	var buf bytes.Buffer
+
+	for _, s := range strings {
+		buf.WriteString(fmt.Sprintf("%s-", s))
+	}
+
+	return fmt.Sprintf("%d", String(buf.String()))
+}
diff --git a/util/time.go b/util/time.go
new file mode 100644
index 0000000..8641936
--- /dev/null
+++ b/util/time.go
@@ -0,0 +1,33 @@
+package util
+
+import (
+	"time"
+)
+
+const (
+	TimeFormat         = "2006-01-02 15:04:05"
+	DateFormat         = "2006-01-02"
+	UnixTimeUnitOffset = uint64(time.Millisecond / time.Nanosecond)
+)
+
+// FormatTimeMillis converts Millisecond to time string
+// tsMillis accurates to millisecond,otherwise, an exception will occur
+func FormatTimeMillis(tsMillis uint64) string {
+	return time.Unix(0, int64(tsMillis*UnixTimeUnitOffset)).Format(TimeFormat)
+}
+
+// FormatDate converts to date string
+// tsMillis accurates to millisecond,otherwise, an exception will occur
+func FormatDate(tsMillis uint64) string {
+	return time.Unix(0, int64(tsMillis*UnixTimeUnitOffset)).Format(DateFormat)
+}
+
+// Returns the current Unix timestamp in milliseconds.
+func CurrentTimeMillis() uint64 {
+	return uint64(time.Now().UnixNano()) / UnixTimeUnitOffset
+}
+
+// Returns the current Unix timestamp in nanoseconds.
+func CurrentTimeNano() uint64 {
+	return uint64(time.Now().UnixNano())
+}
diff --git a/util/uuid_generator.go b/util/uuid_generator.go
new file mode 100644
index 0000000..ffb7871
--- /dev/null
+++ b/util/uuid_generator.go
@@ -0,0 +1,46 @@
+package util
+
+import (
+	"sync/atomic"
+)
+
+var (
+	UUID int64 = 1000
+	serverNodeId = 1
+	UUID_INTERNAL int64 = 2000000000
+	initUUID int64 = 0
+)
+
+func GeneratorUUID() int64 {
+	id := atomic.AddInt64(&UUID,1)
+	if id >= getMaxUUID() {
+		if UUID >= id {
+			newId := id - UUID_INTERNAL
+			atomic.CompareAndSwapInt64(&UUID,id, newId)
+			return newId
+		}
+	}
+	return id
+}
+
+func SetUUID(expect int64, update int64) bool {
+	return atomic.CompareAndSwapInt64(&UUID,expect, update)
+}
+
+func getMaxUUID() int64 {
+	return UUID_INTERNAL * (int64(serverNodeId) +1)
+}
+
+func GetInitUUID() int64 {
+	return initUUID
+}
+
+func Init(svrNodeId int) {
+	// 2019-01-01 与 java 版 seata 一致
+	var base uint64 = 1546272000000
+	serverNodeId = svrNodeId
+	atomic.CompareAndSwapInt64(&UUID,UUID,UUID_INTERNAL*int64(serverNodeId))
+	current := CurrentTimeMillis()
+	id := atomic.AddInt64(&UUID, int64((current - base)/UnixTimeUnitOffset))
+	initUUID = id
+}
\ No newline at end of file