用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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章