Docker笔记二:Lumen + Redis

  Lumen 基于 Laravel 打造,专为构建微服务和 APIs 而生。Lumen与Redis服务端通信可通过Predis(PHP库)或者PhpRedis(PHP的C扩展)来实现,建议使用PhpRedis,其性能更高。Lumen下使用Predis和PhpRedis都需引入illuminate/redis(PHP库),illuminate/redis(PHP库)都对Predis和PhpRedis(Laravel 5.3以上)进行了很好的封装,但illuminate/redis(PHP库)又依赖predis/predis(PHP库),故安装 illuminate/redis时会自动引入predis/predis(PHP库)。

  Redis 与 Memcached 均为常用的 key-value 分布式内存对象缓存系统,可提供数据缓冲和数据共享能力,Redis 支持持久化,而 memcached 不支持持久化,发生重启后数据不会自动恢复。

  关于Memcached:

  • memcached基于hashmap来实现对内存对象的创建与管理,容量(哈希表中桶的数量)和加载因子(容量自动增加之前可以达到多满的一种尺度)影响其性能。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash (重建内部数据结构),从而哈希表将具有大约两倍的桶数。在Java编程语言中,加载因子默认值为0.75,默认哈希表元为101。
    Docker笔记二:Lumen + Redis_第1张图片
  • memcached如果运行在默认状态下,应放置在防火墙后端;
  • 在内置空间被占满之后,memcached采用Least Recently Used(LRU)机制替换掉旧的内容;
  • 基于libevent的事件处理,运行多线程处理多客户端并发连接请求,虽说也支持分布式,但服务端并没有分布式功能,彼此不能互相通信,完全依赖于客户端实现,故障转移也不提供冗余节点,一旦某节点发生故障将导致相应的数据不可用;
  • 客户端libmemcached可采用多种哈希算法(MD5、CRC等)计算key,对非标量类型数据如数组、对象(非资源类型才能被序列化)等将先进行序列化然后再发送给服务端,支持Multi操作;
  • CAS(Check And Set)是Memcached中比较方便的一种防止竞争修改资源的方法
    A 64bit "CAS" value, which is kept unique.
  • 支持文本协议和二进制协议两种主要的协议。此外,还支持子协议SASL Authentication、Range operations。相关信息参考 https://github.com/memcached/memcached/wiki

    下边这段是关于文本协议“noreply”的描述,同时建议使用二进制协议:

    Most ASCII commands allow a "noreply" version. One should not normally use this with the ASCII protocol, as it is impossible to align errors with requests. The intent is to avoid having to wait for a return packet after executing a mutation command (such as a set or add).
    
    The binary protocol properly implements noreply (quiet) statements. If you have a client which supports or uses the binary protocol, odds are good you may take advantage of this.

    下边这段是关于“A Well Designed Binary Protocol Client”的描述:

    With the binary protocol, it(A Well Designed Binary Protocol Client may take many application threads and use a single TCP connection back to memcached) is possible to pack requests from different client instances into the same TCP socket, then dole back results to the right owners.

  关于Redis(REmote DIctionary Server, 远程字典服务器)

  • 运行单线程(多核CPU无法充分利用)处理多客户端并发连接请求,采用了异步非阻塞 IO 模型(epoll);
  • 不依赖libevent这个追求通用而导致代码庞大的库,用libevent中的两个文件修改实现了自己的epoll event loop,小巧并去依赖,编译Redis之前并不需要执行./configure;
  • Redis 2.0增加了虚拟内存(Virtual Memory,Redis自己实现的比OS Page更细的换入出粒度)特性,实现了冷热数据分离,让数据容量突破了物理内存的限制;
  •  支持多种类型的数据结构,如strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries;
  • 多线程自然是可以比单线程有更高的性能上限,但在今天的计算环境中,即使是单机多线程的上限也不能满足实际需求了,因此单机单线程集群化部署是有效解决方案;

 

一. Redis的Docker部署

  1. 创建Dockerfile-Redis(参考https://github.com/dockerfile/redis/blob/master/Dockerfile ):
    FROM ubuntu
    MAINTAINER cenze <[email protected]>
    
    RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    ADD conf/sources.list /etc/apt/
    RUN apt-get update \
    && apt-get install -y gcc make vim
    
    ENV PKGS="/usr/local/pkgs"
    ADD packages/redis-3.2.8.tar.gz $PKGS/
    
    # install redis
    ENV PREFIX_REDIS="/usr/local/redis"
    WORKDIR $PKGS/redis-3.2.8
    RUN make \
    && make PREFIX=$PREFIX_REDIS install \
    && cp redis.conf $PREFIX_REDIS/ \
    && cp src/redis-trib.rb $PREFIX_REDIS/bin/ 
    
    VOLUME ["/data"]
    ENV PATH $PREFIX_REDIS/bin:$PATH
    
    EXPOSE 6379
    
    CMD ["redis-server","/usr/local/redis/redis.conf"]

    注意事项

    • Redis命令参考:https://redis.io/commands
    • 本人已事先下载了PhpRedis的源码安装包redis-3.2.8.tar.gz位于宿主机 ./packages目录下
    • redis.conf中注销行 bind 127.0.0.1 或明确绑定 IP地址集,其他容器才可访问 
    • redis.conf中若未设置密码,可能需设置 protected-mode 为 no以关闭保护模式,protected-mode 默认值为 yes
    • 安装目录的bin下有个redis-cli可拷到其他容器中作为命令行接口来连接管理redis服务端
    • 卷/data用于缓存数据对象的持久化存储目录
  2. 构建镜像:
    sudo docker build -t cenze/redis -f Dockerfile-Redis .
  3. 运行容器:
    sudo docker run -d --name redis cenze/redis

    redis-cli或netcat(nc)或telnet测试部署:

    root@60c9de8c01a0:/usr/local/pkgs/redis-3.2.8# redis-cli
    127.0.0.1:6379> set cache redis
    OK
    127.0.0.1:6379> get cache
    "redis"
    127.0.0.1:6379>  

     

 二.创建Lumen项目

  1. composer创建Lumen:composer无法以 root/super 用户来运行,所以需要切换到其他用户环境,比如本人会运行如下命令
    su - www-data 
    export PATH=/usr/local/php/bin:$PATH (这一条最好写进Home下的.profile, composer依赖PHP来运行) 
    composer create-project --prefer-dist laravel/lumen lumen
  2. .env参数配置:

    APP_ENV=local
    APP_DEBUG=true
    APP_KEY=bcee22b233721b47c6043e6bf35ac4ee
    APP_TIMEZONE=Asia/Shanghai
    
    DB_CONNECTION=mysql
    DB_HOST=[myDbHost]
    DB_PORT=3306
    DB_DATABASE=[myDataBase]
    DB_USERNAME=[myUser]
    DB_PASSWORD=[myPassword]
    
    CACHE_DRIVER=redis
    QUEUE_DRIVER=sync 
    
    REDIS_HOST= 172.17.0.3
    REDIS_PORT= 6379

     

三.Lumen中启用Predis

  1. 安装Predis:Lumen中使用Predis需要引入 predis/predis 和 illuminate/redis两个包
    cd /path/to/lumen
    composer require illuminate/redis (predis/predis为illuminate/redis所依赖,故将被自动安装上)
  2. redis客户端配置修改lumen/vendor/laravel/lumen-framework/config/database.php
    'redis' => [
            
            'client' => 'predis',
            //'client' => 'phpredis',
            
            'cluster' => env('REDIS_CLUSTER', false),
    
            'default' => [
                'host'     => env('REDIS_HOST', 'localhost'),
                'port'     => env('REDIS_PORT', 6379),
                'database' => env('REDIS_DATABASE', 0),
                'password' => env('REDIS_PASSWORD', null),
            ],
    
        ],
  3. 注册Illuminate\Redis\RedisServiceProvider修改lumen/bootstrap/app.php
    $app->register(Illuminate\Redis\RedisServiceProvider::class);
    
    $app->withFacades();//同时启用Facades
    
    $app->withEloquent();//同时启用Eloquent
  4. 测试Predis是否成功启用:修改lumen/routes/web.php
    $app->get('/', function () use ($app) {
        //return $app->version();
        Cache::put('lumen', 'Hello, Lumen.', 5);
        return Cache::get('lumen');
    });

    页面输出:Hello, Lumen.

四.Lumen中启用PhpRedis扩展

  1. 安装PhpRedis
    pecl install redis (有可能需要手动安装 autoconf,phpize依赖该工具)
    composer require illuminate/redis

    注意事项:该C扩展安装完后需要修改php.ini添加行extension=redis.so。如果php在cli模式下运行未发现Redis,可能是因为你的php.ini文件没有找到,该文件为安装配置项--with-config-file-path所指定,默认位于PREFIX/lib目录下,所以应在启动php时添加-c选项指定配置文件或php.ini所在目录。

  2. redis客户端配置:基本同于Predis,唯一不同之处在于lumen/vendor/laravel/lumen-framework/config/database.php中redis的client,'client' => 'phpredis'
  3. 注册Illuminate\Redis\RedisServiceProvider:同于Predis
  4. 测试PhpRedis是否成功启用:同于Predis
  5. 另外一种无需安装illuminate/redis包就能启用PhpRedis的替换方法:

    1)修改lumen/bootstrap/app.php,添加如下代码:

    $app->singleton('redis', function(){
        $redis = new Redis;
        $redis->pconnect('172.17.0.3');
        return $redis;
    });
    unset($app->availableBindings['redis']);
    2)测试PhpRedis是否成功启用,修改lumen/routes/web.php:
    $app->get('/', function () use ($app) {
        //return $app->version();
        app('redis')->set('lumen', 'Hello, Lumen.');
        return app('redis')->get("key");
    });

你可能感兴趣的:(PHP)