用PHP寫一個Redis客戶端

用PHP寫一個Redis客戶端

自己挖的坑,不僅要自己跳,更要帶上別人 —— Jun Feng

Redis客戶端的核心就是實現RESP協議,在Redis 2.0中,RESP協議已經成爲和Redis服務通信的標準協議。

關於RESP協議的具體內容可以去看官方的文檔或者我的博客

在編寫代碼的過程中,只需要完成以下步驟,一個簡單的Redis客戶端就算是實現了:

  • 使用socket連接Redis服務器
  • 將命令序列化爲RESP協議中的數據結構,併發送給Redis服務器
  • 接收Redis服務器返回的數據,並解析成PHP中的數據結構

完成了核心功能,我們就需要對代碼進行優化了

面向對象

採用面向對象的思想進行編程好處有許多,就這個項目本身來說,主要是以下幾點:

  • 對數據進行封裝,類似於連接Redis服務器的套接字、連接默認最長等待時間這些數據不應該暴露在外
  • 方便用戶調用,用戶只需實例化一個對象,就可以通過這個對象來使用Redis,簡單方便
  • 隱藏內部實現的細節,提供統一的接口,編寫的Redis客戶端是作爲一個庫來讓第三方進行調用的,這需要編寫的程序即使內部代碼做了修改,對用戶卻沒有影響

魔術方法

巧妙的使用了__call()這個魔術方法,使得整個代碼變得簡潔而優雅

class Redis{
    public function __call($name, $args)
    {
        $flatten = '';
        array_walk_recursive($args, function ($value) use (&$flatten) {
            $flatten .= ' ' . $value;
        });
        return $name, ' ', $flatten;
    }
}
$redis = new Redis();
$redis->set("key", "value"); // set key value
$redis->get("key"); //get key

Redis的命令繁多,如果一一在對象中去定義,不僅麻煩,而且很難維護。這不僅讓我感慨動態語言的強大

異常處理

拋出不同的異常類使得異常處理更具有針對性。目前我所想到的會產生異常的場景如下:

  • 網絡連接過程產生的異常
  • 發送非法命令產生的異常
  • 對Redis服務器端返回的數據進行解碼時產生的異常

懶連接

只有在需要發送命令的時候纔會與服務器端建立socket連接,盡力減少資源損耗

流水線技術

通過將命令暫時緩存,從而一次性發送多條命令,達到減少RTT以及IO操作,提高效率的目的

  • pipeline_start:開啓pipline
  • pipeline_end:發送命令,得到命令返回值,關閉pipline
  • pipeline_discard:丟棄緩衝區中的命令,關閉pipeline
  • pipeline_rollback:清空pipline中緩存的命令

自動加載

代碼遵循PSR4規範,可使用通用的自動加載器進行加載,比如說composer中的自動加載器

未來計劃

  • 對於SCAN, SSCAN, ZSCAN and HSCAN等命令,加入PHP迭代器
  • 支持Redis發佈訂閱
  • 支持Redis集羣
  • 支持Redis的主從複製和sentinel機制

下載

使用composer

composer require flagupdown/fjredis

github

https://github.com/flagUpDown/fjredis
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章