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库)。php

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

  关于Memcached:laravel

  • memcached采用Slab Allocation机制基于hashmap来实现对内存对象的建立与管理,容量(哈希表中桶的数量)和加载因子(容量自动增长以前能够达到多满的一种尺度)影响其性能。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash (重建内部数据结构),从而哈希表将具备大约两倍的桶数。在Java编程语言中,加载因子默认值为0.75,默认哈希表元为101。
  • memcached若是运行在默认状态下,应放置在防火墙后端;
  • 在内置空间被占满以后,memcached采用惰性失效(Lazy Expiration)机制和Least Recently Used(LRU)机制来作淘汰管理;
  • 基于libevent的事件处理,运行多线程处理多客户端并发链接请求,虽然说也支持分布式,但服务端并无分布式功能,彼此不能互相通讯,彻底依赖于客户端实现,故障转移也不提供冗余节点,一旦某节点发生故障将致使相应的数据不可用;
  • 客户端libmemcached可采用多种哈希算法(MD五、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”的描述,同时建议使用二进制协议:git

    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”的描述:github

    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, 远程字典服务器)SSDB支持LevelDB,是Redis的替代品,且与其兼容。web

  • 运行单线程(多核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;
  • 支持Cache-Only、Persistence两种存储模式,Persistence可分AOF(Append-Only File)、RDB(Redis Database)两种机制(但官方建议两种模式同时开启,参考Redis Persistence),可用于crash后从磁盘恢复,可是都存在可能丢失数据(数据可靠性)问题。从读缓存这个角度讲,一般咱们的应用能够接受这种数据丢失带来的影响,若是应用要求更高的数据可靠性,那就不该该对该类数据使用缓存服务;
    RDB:在save、shutdown、slave时触发写二进制文件,粒度大,若是这些操做未完成以前crash可能致使丢失一部分数据。
    经过fork一个进程,copy-on-write把整个db保存下来,而主进程不会进行任何IO操做,保证了redis的高性能。

    AOF:持续把写操做命令格式化后追加到日志文件的尾部,粒度较小,crash以后数据丢失小。AOF支持不一样的fsync策略,
    包括无fsync、每秒fsync、请求时fsync,默认为每秒fsync策略。fsync是由后台线程完成的,主线程继续努
    力地执行写请求。AOF是文本文件,一般也比RDB文件大,恢复速度慢。
  • Redis支持Cluster、Master-Slave replication,因为Redis的高性能,replication基本没有延迟,这样达到了防止单点故障及实现了高可用;
  • Redis支持事务:watch/multi/exec(discard、unwatch);
  • list可用来实现队列;
  • Redis pipeline技术能够在服务端未响应时,客户端能够继续向服务端发送请求,并最终一次性读取全部服务端的响应。

 

一. Redis的Docker部署redis

  1. 建立Dockerfile-Redis(参考https://github.com/dockerfile/redis/blob/master/Dockerfile ):
    FROM ubuntu
    MAINTAINER cenze <272666745@qq.com>
    
    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测试部署:redis-cli下输入 help <Tab> 可按组查询命令列表sql

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

     

 二.建立Lumen项目docker

  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:这是其官方参考文档 https://github.com/phpredis/phpredis#usage,某些用法可能与Illuminate\Redis不一样
    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");
    });
相关文章
相关标签/搜索