學習RadonDB源碼(二)

来源:https://www.cnblogs.com/wingsless/archive/2019/05/20/10896517.html
-Advertisement-
Play Games

1. 為我新的一天沒有放棄而喝彩 學習是一件很容易放棄的事情,因為就算是不學,我也能在現在的崗位上發光發熱。可是人不就是一個熱愛折騰的種群嗎? 今天沒有放棄不代表明天沒有放棄,也許放棄的可能性大於堅持的可能性,不管怎樣,堅持一天算一天。 RadonDB面對著TiDB,OceanBase等等資料庫的競 ...


1. 為我新的一天沒有放棄而喝彩

學習是一件很容易放棄的事情,因為就算是不學,我也能在現在的崗位上發光發熱。可是人不就是一個熱愛折騰的種群嗎?

今天沒有放棄不代表明天沒有放棄,也許放棄的可能性大於堅持的可能性,不管怎樣,堅持一天算一天。

RadonDB面對著TiDB,OceanBase等等資料庫的競爭,都是分散式資料庫,為什麼要首先學習RadonDB呢?畢竟這是一款真的基於MySQL而不是相容MySQL的產品,通過學習RadonDB,也許有一天我能在其源碼上做出點什麼貢獻也未可知,我起碼對MySQL的熟悉程度更高。

2. 繼續昨天的話題

昨天我寫到了程式的主入口,註意其最重要的一句:

    // Proxy.
    proxy := proxy.NewProxy(log, flagConf, build.Tag, conf)
    proxy.Start()

一切都是從這裡開始的,為什麼這麼說呢?

這一啟動,就好像啟動了一個mysqld一樣,可以正常的接收mysql客戶端的連接請求。

根據昨天講述的,proxy的啟動實際上是執行了Accept方法,而Accept則是以服務形式啟動起來,並且監聽了幾個埠的。

那我們再來看看Accept方法:

// Accept runs an accept loop until the listener is closed.
func (l *Listener) Accept() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    for {
        conn, err := l.listener.Accept()
        if err != nil {
            // Close() was probably called.
            return
        }
        ID := l.connectionID
        l.connectionID++
        go l.handle(conn, ID, l.serverVersion)
    }
}

從代碼邏輯上看,只要沒有執行Close,就會一直迴圈監聽下去,監聽的就是一個一個的網路連接請求。

我猜測這裡的連接就好像是我們在MySQL中執行“show processlist”的時候,顯示的信息,每來一個連接,就會給它分配一個ID,並啟動一個監聽器的handler goroutine,可以理解為啟動了一個線程,這個線程專門負責該連接。

到這裡我們就可以肯定,RadonDB也是一個單進程多線程的架構,和MySQL並無二致。

現在就可以分析分析handler方法到底做了什麼。這個方法很長很長,我實在是不能一行一行的粘貼過來,只是撿一些有代表性的講講。

// handle is called in a go routine for each client connection.
func (l *Listener) handle(conn net.Conn, ID uint32, serverVersion string) {}

首先映入眼帘的一定是註釋,良好的代碼一定擁有良好的註釋。註釋告訴我們,這個handler方法是處理每個客戶端連接的。

客戶端連接嘛,每個DBA都知道,連接上來就是為了執行SQL的命令的,有一般的DDL,DML還有些指令性命令。

那麼我推斷代碼里一定有一個switch分支用於對每種命令進行處理:

for {
        if data, err = session.packets.Next(); err != nil {
            return
        }

        // Update the session last query time for session idle.
        session.updateLastQueryTime(time.Now())
        switch data[0] {
        // COM_QUIT
        case sqldb.COM_QUIT:
            return
            // COM_INIT_DB
        case sqldb.COM_INIT_DB:
            db := l.parserComInitDB(data)
            if err = l.handler.ComInitDB(session, db); err != nil {
                if werr := session.writeErrFromError(err); werr != nil {
                    return
                }
            } else {
                session.SetSchema(db)
                if err = session.packets.WriteOK(0, 0, session.greeting.Status(), 0); err != nil {
                    return
                }
            }
            // COM_PING
        case sqldb.COM_PING:
            if err = session.packets.WriteOK(0, 0, session.greeting.Status(), 0); err != nil {
                return
            }
            // COM_QUERY
        case sqldb.COM_QUERY:
            query := l.parserComQuery(data)
            if err = l.handler.ComQuery(session, query, nil, func(qr *sqltypes.Result) error {
                return session.writeTextRows(qr)
            }); err != nil {
                log.Error("server.handle.query.from.session[%v].error:%+v.query[%s]", ID, err, query)
                if werr := session.writeErrFromError(err); werr != nil {
                    return
                }
            }
//省略其他

還真的是有,邏輯也不複雜,其實剛纔的代碼里沒有展現出session的概念,先講講session在回過頭來講剛纔的代碼:

session := newSession(log, ID, l.serverVersion, conn)
//省略一些session的檢查等操作

l.handler.SessionInc(session)
defer l.handler.SessionDec(session)

// Reset packet sequence ID.
session.packets.ResetSeq()

核心思想就是新建了一個session,之後,才有了剛纔的操作,要從session中拿出用戶操作來,放在一個叫做data的切片中,然後判斷切片中具體的操作類型。

到這裡應該很多人都會知道,RadonDB到底做了一個什麼樣的入口了,其實就是做了一個自己的MySQL服務,監聽特定的埠,接收用戶的操作。

這裡所有的代碼都可以參考以下這個github項目:

go-mysqlstack

作者也是RadonDB的作者之一。這個go-mysqlstack的目的也很簡單,就是實現一個mysqld:

簡介

官方給的示例,就是啟動了一個服務端:

示例

對於交付的客戶來說,其實就是在用MySQL,只不過埠有變,服務的啟動方式和配置方式不太一樣,但是寫代碼還是用jdbc-driver,對於開發者來說沒有任何變化。

3. 小結

Go語言真有意思,利用已經成熟的項目來學習Go語言,我覺得比一點一點看書來的快一些。

當然了,學會了寫之後就要思考,思考這門語言,真的做到Thinking in Go。

真是學而不思則罔。


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

-Advertisement-
Play Games
更多相關文章
  • 話不多說,直接進入正題 第一步查看是否能ping通,第二步就是掃描埠,開放了埠才能進行攻擊 linux進入msfconsole,搜索03_026 等待一會,返回漏洞的全名,exploit是一個攻擊模塊 接下來就是使用這個漏洞(在linux里複製快捷鍵是ctrl+shift+c,粘貼快捷鍵是ctr ...
  • 1.當執行一個指令的時候,舉例來說【ls】,系統會依照PATH的設定去每個PATH定義的目錄下搜尋文件名為ls的可執行文件,如果在PATH定義的目錄中含有多個文件名為ls的可執行文件,那麼先搜尋到的同名指令先被執行! 2.使用echo $PATH可以查看那些目錄被定義了。echo 有【顯示、印出】的 ...
  • 文章大綱 一、Linux發展史二、Linux系統的安裝三、Linux系統的文件四、學習資料下載五、參考文章 一、Linux發展史 1. Linux前身-Unix 1968年 Multics項目MIT、Bell實驗室、美國通用電氣有限公司走到了一起,致力於開發Multics項目。到後期由於開發進度不是 ...
  • 基本網路拓撲圖 1. 準備階段。配置雲主機,模擬簡單的ssh登錄爆破入侵行為 步驟一:登錄阿裡雲管理控制台。打開雲主機。 步驟二:打開VMware,將kali虛擬機的網卡模式設置為NAT,打開kali。打開終端,測試ping雲主機,需成功ping通,如下圖所示 步驟三:通過SSH訪問雲主機,通過ro ...
  • stm32F4系列DSP和FPU指令高性能的MCU-arm Cortex基於M4 STM32F4系列MCU利用ST的NVM技術和ART加速器™達到了業界最高的測試分數為基礎的Cortex-M微控制器具有高達225 DMIPS / 608 CoreMark以高達180 MHz的工作頻率從快閃記憶體執行。 通 ...
  • Docker簡介 Docker是一個開源的容器引擎,它有助於更快地交付應用。Docker可將應用程式和基礎設施層隔離,並且能將基礎設施當作程式一樣進行管理。 使用Docker可更快地打包、測試以及部署應用程式,並可以縮短從編寫到部署運行代碼的周期。 Docker的優點如下: 1、簡化程式 Docke ...
  • 導出表數據和表結構sql文件 在工作中,經常需要導出某個資料庫中,某些表數據;或者,需要對某個表的結構,數據進行修改的時候,就需要在資料庫中導出表的sql結構,包括該表的建表語句和數據存儲語句!在這個時候,就可以利用本方法來操作! 一.工具 1.1 sql server 2008 二.方法 2.1 ...
  • 視圖 1 提高重用性; 2 可用於資料庫重構; 3 可用於不同用戶,提高安全性; 定義視圖: create view 視圖name as select語句; 查看視圖: show tables; 使用: select * from 視圖name; 刪除: drop view 視圖name; ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...