在開源項目https://github.com/syndtr/goleveldb中,存在大量的管道通信,而沒有使用類似于鎖之類的操作,在寫法上是一件特別麻煩的事情。不過這也是項目高性能的一大原因。
管道匯總
寫相關管道
writeMergeC/writeMergedC
這是一對通信方式,當寫入時,判斷writeMergeC是能夠寫入,能寫入表示搶到了鎖操作,并繼續往下執行,等待拿到writeMergedC消息,說明自己的寫入已經被人合并,并不需要處理。
當然如果當前處理未成功,則會繼續往下處理,由另外一個協程進行合并操作。
writeLockC
這個管道和上述的writeMerge是并集操作,當寫入成功該管道,則認為搶鎖成功,繼續往下執行寫入操作。當寫入完成后,則會釋放鎖資源。
writeAckC
ack的管道則是表示當前的操作結果,前2者表示的當前處理流程是否成功。
三者使用了管道來完成了一個隊列的功能
壓縮相關管道
tcompCmdC
該管道表示寫入一個cCmd,用于觸發壓縮操作,這個是由于壓縮是一個單獨的協程來循環處理,所以需要管道通信
tcompPauseC
這個則是為了快速暫停table的壓縮流程,通過管道傳入一個管道來讓壓縮流程停止。當然,如果已經開始進行實際的壓縮操作,這個流程是無法終止的。
mcompCmdC
這個管道和tcompCmdC同理,也是用于觸發壓縮操作,只不過,這個操作是用于mem落入table文件時觸發。
錯誤相關管道
compErrC\compPerErrC\compErrSetC
這三者構成了一個錯誤升級的結構,在壓縮時,如果出現異常,則會寫入compErrSetC,
而如果當前compErrSetC管道堵住,且已經有compPerErrC產生,那直接panic,主要是因為compPerErrC是由于多次的compErrSetC錯誤導致寫入。
當然,如果compErrSetC成功過一次,則會降級等待,否則連續失敗,且compErrC一直沒人處理,則表示錯誤無法處理,并需要終止服務。
closeC
這個管道則是在db調用關閉操作時觸發,在等待操作中都有監聽。
總結
可以看出,Golang管道不僅僅是一個通信工具,還能實現各類的加鎖操作,包括鎖升級。