<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      redis client原理分析

      • 1:連接池
      • 2:發送命令
      • 3:解析結果

      1:連接池
      連接池結構體如下:
      type Pool struct {
         // Dial is an application supplied function for creating and configuring a
         // connection.
         //
         // The connection returned from Dial must not be in a special state
         // (subscribed to pubsub channel, transaction started, ...).
         Dial func() (Conn, error)  //生成網絡連接對象
      
         // TestOnBorrow is an optional application supplied function for checking
         // the health of an idle connection before the connection is used again by
         // the application. Argument t is the time that the connection was returned
         // to the pool. If the function returns an error, then the connection is
         // closed.
         TestOnBorrow func(c Conn, t time.Time) error  //測試連接是否通暢
      
         // Maximum number of idle connections in the pool.
         MaxIdle int  //最大空閑連接數
      
         // Maximum number of connections allocated by the pool at a given time.
         // When zero, there is no limit on the number of connections in the pool.
         MaxActive int //最大活動(正在執行任務)連接數
      
         // Close connections after remaining idle for this duration. If the value
         // is zero, then idle connections are not closed. Applications should set
         // the timeout to a value less than the server's timeout.
         IdleTimeout time.Duration //空閑連接超時時間,超時會釋放
      
         // If Wait is true and the pool is at the MaxActive limit, then Get() waits
         // for a connection to be returned to the pool before returning.
         Wait bool //當到達最大活動連接時,是否阻塞
      
         chInitialized uint32 // set to 1 when field ch is initialized 初始化標記
      
         mu     sync.Mutex    // mu protects the following fields 鎖
         closed bool          // set to true when the pool is closed. 連接池關閉標記
         active int           // the number of open connections in the pool 連接總數
         ch     chan struct{} // limits open connections when p.Wait is true 用于實現阻塞邏輯
         idle   idleList      // idle connections 雙向鏈表,存放空閑連接
      }
      
      type idleList struct { //空閑連接鏈表
         count       int //空閑連接數
         front, back *idleConn //空閑連接信息
      }
      
      type idleConn struct {  //空閑連接信息
         c          Conn      //連接接口
         t          time.Time //加入空閑隊列的時間,用于判斷空閑超時
         next, prev *idleConn //雙向鏈表指針
      }

      1:空閑連接池實現
      空閑連接池存在一個雙向鏈表中,一個連接用完后回收,就會從表頭插入這個鏈表,當需要一個連接時也是從鏈表的表頭取,從表頭插入的時候會寫入當前時間,所以鏈表是一個按時間倒序的鏈表,判斷一個連接有沒有空閑超時,就從鏈表表尾開始判斷,如果空閑超時,就從表尾移除并關閉連接。從表頭插入一個元素后,如果空閑數量超過閾值,會從表尾移除一個元素,保證空閑的連接數不超過指定的值,防止空閑的連接過多浪費系統資源
       
      獲取可用連接過程
      對應方法:Pool.Get
      1:刪除超時空閑連接。從鏈表的表尾開始往表頭判斷,如果到達空閑超時時間,從鏈表中移除并釋放連接
      2:從空閑鏈表中獲取可用連接。從鏈表表頭往表尾查找可用的連接,如果連接能ping通,將當前連接從鏈表中移除,返回當前連接
      3:建立一個新的連接。如果空閑連接為空,或者空閑鏈表中的所有連接都不可用,則從新建立一個新的連接并返回
      在獲取連接的時候刪除超時空閑連接,這是一種惰性刪除的方式
       
      以上實現方式同時解決了斷開重連的問題。
      如在某一時刻redis server重啟了,那么空閑鏈表中的連接都會變得不可用,由于在獲取可用連接前會先ping一下,但是所有連接都ping不通,最后只能重新建立,而空閑連接會在空閑時間超時后自動釋放,于是很好的解決了斷開重連的問題,同時也做了一些犧牲,不ping一下怎么知道連接是否可用,每次獲取可用連接的時候都ping了一下,但是大部分時候連接都是可用的。
       
      回收可用連接:
      對應方法:pooledConnection.Close  -> Pool.put
      1:終止相關操作,如果是事務/監聽/訂閱,停止相關操作
      2:將連接放入空閑鏈表。將連接存入鏈表表頭,如果空閑連接數量超過閾值,就將表尾元素移除并關閉連接
       
       
      2:發送命令&接收回復并解析
      func (c *conn) Do(cmd string, args ...interface{}) (interface{}, error) {
         return c.DoWithTimeout(c.readTimeout, cmd, args...)
      }
      
      func (c *conn) DoWithTimeout(readTimeout time.Duration, cmd string, args ...interface{}) (interface{}, error) {
         c.mu.Lock()
         pending := c.pending
         c.pending = 0
         c.mu.Unlock()
      
         if cmd == "" && pending == 0 {
            return nil, nil
         }
      
         //設置寫超時時間
         if c.writeTimeout != 0 {
            c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
         }
         //發送命令內容
         if cmd != "" {
            if err := c.writeCommand(cmd, args); err != nil {
               return nil, c.fatal(err)
            }
         }
      
         if err := c.bw.Flush(); err != nil {
            return nil, c.fatal(err)
         }
      
         var deadline time.Time
         if readTimeout != 0 {
            deadline = time.Now().Add(readTimeout)
         }
         //設置讀超時時間
         c.conn.SetReadDeadline(deadline)
      
         if cmd == "” {
            //獲取server回復信息并解析
            reply := make([]interface{}, pending)
            for i := range reply {
               r, e := c.readReply()
               if e != nil {
                  return nil, c.fatal(e)
               }
               reply[i] = r
            }
            return reply, nil
         }
      
         var err error
         var reply interface{}
         for i := 0; i <= pending; i++ {
            var e error
            if reply, e = c.readReply(); e != nil {
               return nil, c.fatal(e)
            }
            if e, ok := reply.(Error); ok && err == nil {
               err = e
            }
         }
         return reply, err
      }

      redis請求協議格式

      set命令消息格式:
      *3\r\n$3\r\nSET\r\n$4\r\nhlxs\r\n$28\r\nhttps://www.rzrgm.cn/hlxs\r\n
      
      注釋如下:
      *3        //參數個數是*開頭,3個參數
      $3        //參數長度是$開頭,命令長度
      SET       //命令名稱SET
      $5        //參數長度是$開頭,key長度
      mykey     //key的內容
      $28       //參數長度是$開頭,value長度
      https://www.rzrgm.cn/hlxs      //value內容

      參數個數是*開頭,參數長度是$開頭,每個參數通過\r\n隔開
      redis協議格式特點:1易于實現,2可以高效地被計算機分析,3可以很容易地被人類讀懂
      發送命令其實就是構造請求協議格式,以二進制的方式發送出去
       
      redis回復協議格式
      * 狀態回復(status reply)的第一個字節是 “+”,如:+ok\r\n
      * 錯誤回復(error reply)的第一個字節是 “-“,如:-ERR unknown command xxx\r\n
        在 "-" 之后,直到遇到第一個空格或新行為止,這中間的內容表示所返回錯誤的類型
      * 整數回復(integer reply)的第一個字節是 “:”,如::1000\r\n
      * 批量回復(bulk reply)的第一個字節是 “$”,如:$6\r\nfoobar\r\n,也是長度加內容的風格
      * 多條批量回復(multi bulk reply)的第一個字節是 “*”,如:*5\r\n:1\r\n:2\r\n:3\r\n:4\r\n$6\r\nfoobar\r\n,前面多了數量

      接收命令其實就是解析以上格式

       

       

       

       

       

      posted @ 2020-10-28 11:47  古文觀芷  閱讀(878)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲成人av在线系列| 亚洲永久精品免费在线看| 亚洲国产午夜精品福利| 中文乱码人妻系列一区二区| 日韩av一中美av一中文字慕| 国产日韩精品一区二区在线观看播放| 日韩在线观看 一区二区| 欧美国产精品不卡在线观看| 成在线人永久免费视频播放 | 国产中文字幕精品喷潮| 自拍日韩亚洲一区在线| 日韩精品无遮挡在线观看| 久久先锋男人AV资源网站| 伊人久久精品久久亚洲一区 | 国产精品中文字幕免费| 国内精品久久人妻无码不卡| 国产精品多p对白交换绿帽| 久久人体视频| 国产永久免费高清在线| 国产成人精品久久一区二| 日日碰狠狠添天天爽超碰97| 国产超碰无码最新上传| 车致| 久久亚洲美女精品国产精品| 天堂中文8资源在线8| 国产精品ⅴ无码大片在线看 | 亚洲中文字幕有综合久久| 亚洲二区中文字幕在线| 国产精品国三级国产av| 东乡族自治县| 激情在线网| 性一交一乱一乱一视频| 国产AV影片麻豆精品传媒| 日本欧美大码aⅴ在线播放| 午夜精品福利亚洲国产| 国产精品色悠悠在线观看| 久久精品国产成人午夜福利| 久久国产精品波多野结衣| 日日麻批免费40分钟无码| 久久久久久久一线毛片| 999国产精品999久久久久久|