讓我們聊一聊分散式事務
一個複雜的系統往往都是從一個小而簡的系統發展衍化而來,為了滿足日益增長的業務需求,不斷的增加系統的複雜度,從單體架構逐步發展為分散式架構,而分散式系統架構的設計主要關注:高效能,高可用,高拓展
分散式事務
高可用是指系統無中斷的執行功能的能了,代表了系統的可用程度,是進行系統設計時必須要遵守的準則之一。
而高可用的實現方案,無外乎就是冗餘,就儲存的高可用而言,問題不在於如何進行資料備份,而在於如何規避資料不一致對業務造成的影響
對於分散式系統而言,要保證分散式系統中的資料一致性就需要一種方案,可以保證資料在子系統中始終保持一致,避免業務出現問題,這種實現方案就叫做分散式事務,要麼一起成功,要麼一起失敗,必須是一個整體性的事務
理論基礎
在講解具體方案之前,有必要了解一下分散式中資料設計需要遵循的理論基礎,CAP理論和BACS理論,為後面的實踐鋪平道路
CAP理論
CAP:Consistency Acailability Partition tolerance 的簡寫
Consistency:一致性
對某個客戶端來說,讀操作能夠返回最新的寫操作結果
Acailability:可用性
非故障節點在合理的時間內返回合理的響應
Partition tolerance:分割槽容錯性
當出現網路分割槽後,系統能夠繼續提供服務 你知道什麼是網路分割槽嗎 ~~
因為分散式系統中系統肯定部署在多臺機器上,無法保證網路做到100%的可靠,所以網路分割槽一定存在,即P一定存在;
在出現網路分割槽後,就出現了可用性和一致性的問題,我們必須要在這兩者之間進行取捨,因此就有了兩種架構:CP架構,AP架構;
CP架構
當網路分割槽出現後,為了保證一致性,就必須拒接請求,否則無法保證一致性
- 當沒有出網路分割槽時,系統A與系統B的資料一致,X=1
- 將系統A的X修改為2,X=2
- 當出現網路分割槽後,系統A與系統B之間的資料同步資料失敗,系統B的X=1
- 當客戶端請求系統B時,為了保證一致性,此時系統B應拒絕服務請求,返回錯誤碼或錯誤資訊
上面這種方式就違背了可用性的要求,只滿足一致性和分割槽容錯,即CP
CAP理論是忽略網路延遲,從系統A同步資料到系統B的網路延遲是忽略的
CP架構保證了客戶端在獲取資料時一定是最近的寫操作,或者獲取到異常資訊,絕不會出現資料不一致的情況
AP架構
當網路分割槽出現後,為了保證可用性,系統B可以返回舊值,保證系統的可用性
- 當沒有出網路分割槽時,系統A與系統B的資料一致,X=1
- 將系統A的X修改為2,X=2
- 當出現網路分割槽後,系統A與系統B之間的資料同步資料失敗,系統B的X=1
- 當客戶端請求系統B時,為了保證可用性,此時系統B應返回舊值,X=1
上面這種方式就違背了一致性的要求,只滿足可用性和分割槽容錯,即AP
AP架構保證了客戶端在獲取資料時無論返回的是最新值還是舊值,系統一定是可用的
CAP理論關注粒度是資料,而不是整體系統設計的策略
BASE理論
BASE理論指的是基本可用 Basically Available,軟狀態 Soft Stat,最終一致性 Eventual Consistency,核心思想是即便無法做到強一致性,但應該可以有采用適合的方式保證最終一致性
BASE:Basically Available Soft Stat Eventual Consistency的簡寫
BA:Basically Available 基本可用
分散式系統在出現故障的時候,允許損失部分可用性,即保證核心可用
S:Soft Stat 軟狀態
允許系統存在中間狀態,而該中間狀態不會影響系統整體可用性
E:Consistency 最終一致性
系統中的所有資料副本經過一定時間後,最終能夠達到一致的狀態
BASE理論本質上是對CAP理論的延伸,是對 CAP 中 AP 方案的一個補充
分散式事務協議
X/Open XA 協議
XA是一個分散式事務協議,由Tuxedo提出。XA規範主要定義了(全域性)事務管理器(Transaction Manager)和(區域性)資源管理器(Resource Manager)之間的介面。XA介面是雙向的系統介面,在事務管理器Transaction Manager)以及一個或多個資源管理器(Resource Manager)之間形成通訊橋樑
XA協議採用兩階段提交方式來管理分散式事務。XA介面提供資源管理器與事務管理器之間進行通訊的標準介面
2PC 二階段提交 協議
二階段提交(Two-phase Commit),是指,為了使基於分散式系統架構下的所有節點在進行事務提交時保持一致性而設計的一種演算法(Algorithm)。通常,二階段提交也被稱為是一種協議(Protocol)。在分散式系統中,每個節點雖然可以知曉自己的操作時成功或者失敗,卻無法知道其他節點的操作的成功或失敗。當一個事務跨越多個節點時,為了保持事務的ACID特性,需要引入一個作為協調者的元件來統一掌控所有節點(稱作參與者)的操作結果並最終指示這些節點是否要把操作結果進行真正的提交(比如將更新後的資料寫入磁碟等等)。因此,二階段提交的演算法思路可以概括為: 參與者將操作成敗通知協調者,再由協調者根據所有參與者的反饋情報決定各參與者是否要提交操作還是中止操作
二階段提交演算法的成立基於以下假設:
- 該分散式系統中,存在一個節點作為協調者(Coordinator),其他節點作為參與者(Cohorts)。且節點之間可以進行網路通訊。
- 所有節點都採用預寫式日誌,且日誌被寫入後即被保持在可靠的儲存裝置上,即使節點損壞不會導致日誌資料的消失。
- 所有節點不會永久性損壞,即使損壞後仍然可以恢復
二階段提交分為兩階段:第一階段:投票階段,第二階段:提交階段
投票階段 Prepares
- 協調者向所有參與者詢問是否可以執行提交操作,並開始等待各參與者的響應
- 參與者執行事務操作,如果執行成功就返回Yes響應,如果執行失敗就返回No響應
- 如果協調者接受參與者響應超時,也會認為執行事務操作失敗
提交階段 commit
- 如果第一階段匯中所有參與者都返回yes響應,協調者向所有參與者發出提交請求,所有參與者提交事務
- 如果第一階段中有一個或者多個參與者返回no響應,協調者向所有參與者發出回滾請求,所有參與者進行回滾操作
二階段提交優點:儘量保證了資料的強一致,但不是100%一致
缺點:
單點故障
由於協調者的重要性,一旦協調者發生故障,參與者會一直阻塞,尤其時在第二階段,協調者發生故障,那麼所有的參與者都處於鎖定事務資源的狀態中,而無法繼續完成事務操作
同步阻塞
由於所有節點在執行操作時都是同步阻塞的,當參與者佔有公共資源時,其他第三方節點訪問公共資源不得不處於阻塞狀態
資料不一致
在第二階段中,當協調者想參與者傳送提交事務請求之後,發生了局部網路異常或者在傳送提交事務請求過程中協調者發生了故障,這會導致只有一部分參與者接收到了提交事務請求。而在這部分參與者接到提交事務請求之後就會執行提交事務操作。但是其他部分未接收到提交事務請求的參與者則無法提交事務。從而導致分散式系統中的資料不一致
二階段提交的問題
如果協調者在第二階段傳送提交請求之後掛掉,而唯一接受到這條訊息的參與者執行之後也掛掉了,即使協調者通過選舉協議產生了新的協調者並通知其他參與者進行提交或回滾操作的話,都可能會與這個已經執行的參與者執行的操作不一樣,當這個掛掉的參與者恢復之後,就會產生資料不一致的問題
3PC 三階段提交 協議
三階段提交(Three-phase commit),三階段提交是為解決兩階段提交協議|的缺點而設計的。 與兩階段提交不同的是,三階段提交是“非阻塞”協議。三階段提交在兩階段提交的第一階段與第二階段之間插入了一個準備階段,使得原先在兩階段提交中,參與者在投票之後,由於協調者發生崩潰或錯誤,而導致參與者處於無法知曉是否提交或者中止的“不確定狀態”所產生的可能相當長的延時的問題得以解決
三階段提交的三個階段:CanCommit,PreCommit,DoCommit三個階段
詢問階段 CanCommit
協調者向參與者傳送commit請求,參與者如果可以提交就返回Yes響應,否則返回No響應
準備階段 PreCommit
協調者根據參與者在詢問階段的響應判斷是否執行事務還是中斷事務
- 如果所有參與者都返回Yes,則執行事務
- 如果參與者有一個或多個參與者返回No或者超時,則中斷事務
參與者執行完操作之後返回ACK響應,同時開始等待最終指令
提交階段 DoCommit
協調者根據參與者在準備階段的響應判斷是否執行事務還是中斷事務
- 如果所有參與者都返回正確的ACK響應,則提交事務
- 如果參與者有一個或多個參與者收到錯誤的ACK響應或者超時,則中斷事務
- 如果參與者無法及時接收到來自協調者的提交或者中斷事務請求時,會在等待超時之後,會繼續進行事務提交
協調者收到所有參與者的ACK響應,完成事務
解決二階段提交時的問題
在三階段提交中,如果在第三階段協調者傳送提交請求之後掛掉,並且唯一的接受的參與者執行提交操作之後也掛掉了,這時協調者通過選舉協議產生了新的協調者,在二階段提交時存在的問題就是新的協調者不確定已經執行過事務的參與者是執行的提交事務還是中斷事務,但是在三階段提交時,肯定得到了第二階段的再次確認,那麼第二階段必然是已經正確的執行了事務操作,只等待提交事務了,所以新的協調者可以從第二階段中分析出應該執行的操作,進行提交或者中斷事務操作,這樣即使掛掉的參與者恢復過來,資料也是一致的。
所以,三階段提交解決了二階段提交中存在的由於協調者和參與者同時掛掉可能導致的資料一致性問題和單點故障問題,並減少阻塞,因為一旦參與者無法及時收到來自協調者的資訊之後,他會預設執行提交事務,而不會一直持有事務資源並處於阻塞狀態。
三階段提交的問題
在提交階段如果傳送的是中斷事務請求,但是由於網路問題,導致部分參與者沒有接到請求,那麼參與者會在等待超時之後執行提交事務操作,這樣這些由於網路問題導致提交事務的參與者的資料就與接受到中斷事務請求的參與者存在資料不一致的問題。
所以無論是2PC還是3PC都不能保證分散式系統中的資料100%一致
解決方案
舉個栗子:
在電商網站中,使用者對商品進行下單,需要在訂單表中建立一條訂單資料,同時需要在庫存表中修改當前商品的剩餘庫存數量,兩步操作一個新增,一個修改,我們一定要保證這兩步操作一定同時操作成功或失敗,否則業務就會出現問題
建立時:
業務量不大,使用者少,系統只是一個單體架構,訂單表與庫存表都在一個數據庫中,這時可以使用mysql的本地事務保證資料一致性
發展期:
業務發展迅速,使用者量變多,單資料已經出現了效能瓶頸,按照業務緯度進行分庫,分為訂單庫和庫存庫,由於跨庫跨機器,mysql的本地事務不能再保證訂單庫和庫存庫的資料一致性
成熟期:
業務拓展,單體架構已經滿足不了需求,進而衍化成了分散式系統,這時的訂單和庫存已經拆分為了兩個子系統提供服務,子系統間使用rpc進行通訊,但是無論系統發展成什麼樣,我們都要保證業務不出問題,保證訂單和庫存的資料一致,這時候要思考下在服務之間我們應如何保證資料一致
強一致性分散式事務
單體架構多資料來源,在業務開發中,肯定是先執行對訂單庫的操作,但是不提交事務,再執行對庫存庫的操作,也不提交事務,如果兩個操作都成功,在一起提交事務,如果有一個操作失敗,則兩個都進行回滾
基於2PC/XA協議實現的JTA
我們已經知道了2PC和XA協議的原理,而JTA是java規範,是XA在java上的實現
JTA(Java Transaction Manager) :
- TransactionManager : 常用方法,可以開啟,回滾,獲取事務. begin(),rollback()...
- XAResouce : 資源管理,通過Session來進行事務管理,commit(xid)...
- XID : 每一個事務都分配一個特定的XID
JTA主要的原理是二階段提交,當整個業務完成了之後只是第一階段提交,在第二階段提交之前會檢查其他所有事務是否已經提交,如果前面出現了錯誤或是沒有提交,那麼第二階段就不會提交,而是直接回滾,這樣所有的事務都會做回滾操作
基於JTA這種方案實現分散式事務的強一致性
JTA的特點:
- 基於兩階段提交,有可能會出現資料不一致的情況
- 事務時間過長,阻塞
- 效能低,吞吐量低
實現可以使用基於JTA實現的jar包Atomikos 使用例子可以自己百度一下
正常架構設計中是否應該出現這種跨庫的操作,我覺得是不應該的,如果過按業務拆分將資料來源進行分庫,我們應該同時將服務也拆分出去才合適,應遵循一個系統只操作一個數據源(主從沒關係),避免後續可能會出現的多個系統呼叫一個數據源的情況
最終一致性分散式事務方案(柔性事務)
JTA方案適用於單體架構多資料來源時實現分散式事務,但對於微服務間的分散式事務就無能為力了,我們需要使用其他的方案實現分散式事務
本地訊息表
本地訊息表的核心思想是將分散式事務拆分成本地事務進行處理
以本文中例子,在訂單系統新增一條訊息表,將新增訂單和新增訊息放到一個事務裡完成,然後通過輪詢的方式去查詢訊息表,將訊息推送到mq,庫存系統去消費mq
執行流程:
- 訂單系統,新增一條訂單和一條訊息,在一個事務裡提交
- 訂單系統,使用定時任務輪詢查詢狀態為未同步的訊息表,傳送到mq,如果傳送失敗,就重試傳送
- 庫存系統,接收mq訊息,修改庫存表,需要保證冪等操作
- 如果修改成功,呼叫rpc介面修改訂單系統訊息表的狀態為已完成或者直接刪除這條訊息
- 如果修改失敗,可以不做處理,等待重試
訂單系統中的訊息有可能由於業務問題會一直重複傳送,所以為了避免這種情況可以記錄一下 傳送次數,當達到次數限制之後報警,人工接入處理;庫存系統需要保證冪等,避免同一條訊息被多次消費造成資料一致;
本地訊息表這種方案實現了最終一致性,需要在業務系統裡增加訊息表,業務邏輯中多一次插入的DB操作,所以效能會有損耗,而且最終一致性的間隔主要有定時任務的間隔時間決定
MQ訊息事務
訊息事務的原理是將兩個事務通過訊息中介軟體進行非同步解耦
訂單系統執行自己的本地事務,併發送mq訊息,庫存系統接收訊息,執行自己的本地事務,乍一看,好像跟本地訊息表的實現方案類似,只是省去 了對本地訊息表的操作和輪詢傳送mq的操作,但實際上兩種方案的實現是不一樣的
訊息事務一定要保證業務操作與訊息傳送的一致性,如果業務操作成功,這條訊息也一定投遞成功
訊息事務依賴於訊息中介軟體的事務訊息,基於訊息中介軟體的二階段提交實現的,RocketMQ就支援事務訊息
執行流程:
- 傳送prepare訊息到訊息中介軟體
- 傳送成功後,執行本地事務
- 如果事務執行成功,則commit,訊息中介軟體將訊息下發至消費端
- 如果事務執行失敗,則回滾,訊息中介軟體將這條prepare訊息刪除
- 消費端接收到訊息進行消費,如果消費失敗,則不斷重試
這種方案也是實現了最終一致性,對比本地訊息表實現方案,不需要再建訊息表,不再依賴本地資料庫事務了,所以這種方案更適用於高併發的場景
最大努力通知
最大努力通知相比前兩種方案實現簡單,適用於一些最終一致性要求較低的業務,比如支付通知,簡訊通知這種業務
以支付通知為例,業務系統呼叫支付平臺進行支付,支付平臺進行支付,進行操作支付之後支付平臺會盡量去通知業務系統支付操作是否成功,但是會有一個最大通知次數,如果超過這個次數後還是通知失敗,就不再通知,業務系統自行呼叫支付平臺提供一個查詢介面,供業務系統進行查詢支付操作是否成功
執行流程:
- 業務系統呼叫支付平臺支付介面, 並在本地進行記錄,支付狀態為支付中
- 支付平臺進行支付操作之後,無論成功還是失敗,都需要給業務系統一個結果通知
- 如果通知一直失敗則根據重試規則進行重試,達到最大通知次數後,不在通知
- 支付平臺提供查詢訂單支付操作結果介面
- 業務系統根據一定業務規則去支付平臺查詢支付結果
這種方案也是實現了最終一致性
補償事務TCC
TCC Try-Confirm-Cancel的簡稱,針對每個操作,都需要有一個其對應的確認和取消操作,當操作成功時呼叫確認操作,當操作失敗時呼叫取消操作,類似於二階段提交,只不過是這裡的提交和回滾是針對業務上的,所以基於TCC實現的分散式事務也可以看做是對業務的一種補償機制
TCC的三階段:
- Try 階段:對業務系統做檢測及資源預留
- Confirm 階段:對業務系統做確認提交,Try階段執行成功並開始執行 Confirm階段時,預設 Confirm階段是不會出錯的。即:只要Try成功,Confirm一定成功
- Cancel 階段:在業務執行錯誤,需要回滾的狀態下執行的業務取消,預留資源釋放
在try階段,是對業務系統進行檢查及資源預覽,比如訂單和儲存操作,需要檢查庫存剩餘數量是否夠用,並進行預留,預留操作的話就是新建一個可用庫存數量欄位,Try階段操作是對這個可用庫存數量進行操作
比如下一個訂單減一個庫存:
執行流程:
- Try階段:訂單系統將當前訂單狀態設定為支付中,庫存系統校驗當前剩餘庫存數量是否大於1,然後將可用庫存數量設定為庫存剩餘數量-1,
- 如果Try階段執行成功,執行Confirm 階段,將訂單狀態修改為支付成功,庫存剩餘數量修改為可用庫存數量
- 如果Try階段執行失敗,執行Cancel 階段,將訂單狀態修改為支付失敗,可用庫存數量修改為庫存剩餘數量
基於TCC實現分散式事務,程式碼邏輯想對複雜一些,需要將原來的介面的邏輯拆分為:try,confirm ,cancel 三個介面的邏輯
基於TCC實現的分散式事務框架:ByteTCC,tcc-transaction
ByteTCC:https://github.com/liuyangming/ByteTCC
tcc-transaction:https://github.com/changmingxie/tcc-transaction
讀完之後應該對分散式事務有了一個大致的瞭解,在實際生產中我們要儘量避免使用分散式事務,能轉化為本地事務就用本地事務,如果必須使用分散式事務,還需要從業務角度多思考使用哪種方案更適合
總之行動之前多思考
推薦閱讀:
23種設計模式詳解
淺析網路協議
java併發程式設計 | 鎖詳解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock
java併發程式設計 | 執行緒池詳解
參考:
百度百科
分散式事務解決方案
深入理解分散式事務
深入理解分散式系統的2PC和3PC
柔性事務:最大努力通知
相關推薦
讓我們聊一聊分散式事務
一個複雜的系統往往都是從一個小而簡的系統發展衍化而來,為了滿足日益增長的業務需求,不斷的增加系統的複雜度,從單體架構逐步發展為分散式架構,而分散式系統架構的設計主要關注:高效能,高可用,高拓展 分散式事務 高可用是指系統無中斷的執行功能的能了,代表了系統的可用程度,是進行系統設計時必須要遵守的準則之一。
讓我們來聊一聊外掛化吧---高深莫測
現如今外掛化的思想和應用在Android上越來越多了,各式各樣的方案也是層出不窮,這篇文章旨在告訴大家外掛化的核心思想是什麼,又有什麼樣的實現方式。 前言 首先,這篇文章的題目為什麼不沿用我之前xxxx!xxxxx這樣的風格呢,因為我覺得這樣風格太中二了。。
聊一聊分散式鎖的設計
起因 前段時間,看到redis作者釋出的一篇文章《Is Redlock safe?》,Redlock是redis作者基於redis設計的分散式鎖的演算法。文章起因是有一位分散式的專家寫了一篇文章《How to do distributed locking》,質疑Re
聊一聊分散式物件儲存
1. 前言 今天來聊聊我正在讀的一本分散式物件儲存的書籍。 前天11月10號,想著京東有滿200-100的活動,就買了一些書,準備沉澱一下。自己打算在分散式系統上搞幾年,所以買的書基本上都是關於分散式儲存的。本身也沒想著買一些分散式系統的經典教材,就隨便選了幾本
不吹不黑,今天我們來聊一聊 Kubernetes 落地的三種方式
作者 | 王國樑 Kubernetes 社群成員與專案維護者原文標題《Kubernetes 應用之道:讓 Kubernetes落地的“三板斧”》,首發於知乎專欄:進擊的雲端計算原文地址:https://zhuanlan.zhihu.com/p/82666719 出身豪門、大廠背書的 Ku
聊一聊 MySQL 中的事務及其實現原理
說到資料庫,那就一定會聊到事務,事務也是面試中常問的問題,我們先來一個面試場景: 面試官:"事務的四大特性是什麼?" 我:"ACID,即原子性(Atomicity)、隔離性(Isolation)、永續性(Durability)、一致性(Consistency)!" 面試官:"在 MySQL 資料庫的 Inno
聊一聊啥都不會的我自學Linux系統的歷程
計算機專業 linux論壇 服務器 知識點 嵌入式 Linux大家都不陌生,我是在大三的時候開始接觸Linux,上課的時候一位給我們上課的老師閑聊的時候說,你們計算機專業的學生要好好去學Linux,對於你們以後發展或者是就業都很有幫助。 開始的時候是一種從眾心理,慢慢的學習中發現自己越來越
聊一聊Vue實例與生命周期運行機制
思維 mod images mic import mvvm 方法 add char Vue的實例是Vue框架的入口,擔任MVVM中的ViewModel角色,所有功能的實現都是圍繞其生命周期進行的,在生命周期的不同階段調用對應的鉤子函數可以實現組件數據管理和DOM渲染兩大重要
從明天起,讓我們做一名調包俠
center alt 基礎設施 深入 程序包 images 反饋 learning 這樣的 原文首發於我的微信公眾號:GeekArtT。 從明天起,做一個幸福的人,餵馬、劈柴,周遊世界,然後做一名合格的調包俠。不再基礎設施上糾結不已,而是在前人的基礎上,進行地春暖花開
很認真的聊一聊程序員的自我修養
很大的 溝通 數據庫查詢 職業 xxx 話題 必備 小學 lol 首先要談的是,今天的話題所聊的程序員包含哪些人? 在中國,寫程序,不僅僅是一種興趣,更多的時候,還是一種普通職業和謀生工具 大公司有厲害的程序員,優秀的架構師,但大量的小公司也有很多普通的程序員。在我這些
[聊一聊系列]聊一聊前端存儲那些事兒
我們 老朋友 必須 獲取 sql 壓力 做了 lan read https://segmentfault.com/a/1190000005927232 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://seg
聊一聊共享單車
高峰 地鐵站 中學生 電商 吐槽 活動 存在 http ... 1.共享單車的模式用戶交押金,然後騎車,按照騎車時間進行計費。其實,嚴格意義上來講,這還並不屬於共享經濟,更像分時租賃。 2、共享單車的用戶人群 & 特征用戶人群:80後、90後的低頻打車人群,
聊一聊分布式鎖的設計
src set 可用性 slave 共享資源 get 處理過程 res 指定 起因 前段時間,看到redis作者發布的一篇文章《Is Redlock safe?》,Redlock是redis作者基於redis設計的分布式鎖的算法。文章起因是有一位分布式的專家寫了一篇文章《H
聊一聊我的阿裏雲ECS雲主機
工作者 資料 linux系統 tom ecs 進行 http 感覺 com javaweb學習有段時間了,期間也編寫了一些自己的小webapp應用,但是都是發布在我們自己的個人pc上的. 於是我在想:怎麽樣讓自己的項目可以發到公網上面去,讓朋友們能夠來訪問? 我首先想到
聊一聊 Android 6.0 的運行時權限
con alert 打電話 target 告訴 分享 ttf alt toast 聊一聊 Android 6.0 的運行時權限 權限一刀切 棉花糖運行時權限 權限的分組 正常權限 正常權限列表 特殊權限 請求SYSTEM_ALERT_WINDOW 請求WRITE
【轉載】聊一聊C#的Equals()和GetHashCode()方法
table rule != tle 繼承 操作符 內存 png blog 首先先談一下Equals()這個方法: Equals()方法,來自於Object,是我們經常需要重寫的方法。此方法的默認實現大概是這樣的: public virtual bool Equals(obj
聊一聊Javasript繼承
兩個 || this指向 type屬性 中國 什麽 aso ldo markdown ??前前後後已經快寫了2年左右javaScript,剛開始只是簡單用於一些表單驗證和操作dom節點,並沒有深入的使用,隨著漸漸的深入,開始不想去寫重復的代碼(懶的開始),從而寫簡單的繼承,
(五)聊一聊深Copy與淺Copy
otto list int print 技術分享 作用 code height 工廠 一、關於淺copy與深copy 首先說明一下: 在python中,賦值其實就是對象的引用,變量就是對象的一個標簽,如果把內存對象比喻成一個個房間,那麽變量就是門牌號。 深copy與淺
聊一聊2D地圖的迷霧效果
png char 一段 行數據 編程經驗 lan get 第一個 色值 在經歷了17年諸般變動後,現在到了2018年。懷舊是因為之前幾年發生太多,好與不好都已過去,17年迎來新的開始,所以也就有了後來些許感慨,有機會再說說這些行業感受了。今天先讓我們專註於川最新解決的實際項
( 轉 ) 聊一聊C#的Equals()和GetHashCode()方法
不同 持久性 自己 今天 特殊 周期 htm type eth 博客創建一年多,還是第一次寫博文,有什麽不對的地方還請多多指教。 關於這次寫的內容可以說是老生長談,百度一搜一大堆。大神可自行繞路。 最近在看Jeffrey Richter的CLR Via C#,在看到Get