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采用Slab Allocation机制基于hashmap来实现对内存对象的创建与管理,容量(哈希表中桶的数量)和加载因子(容量自动增加之前可以达到多满的一种尺度)影响其性能。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash (重建内部数据结构),从而哈希表将具有大约两倍的桶数。在Java编程语言中,加载因子默认值为0.75,默认哈希表元为101。
    《Docker笔记二:Lumen + Redis》
  • memcached如果运行在默认状态下,应放置在防火墙后端;
  • 在内置空间被占满之后,memcached采用惰性失效(Lazy Expiration)机制和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, 远程字典服务器)SSDB支持LevelDB,是Redis的替代品,且与其兼容。

  • 运行单线程(多核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部署

  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> 可按组查询命令列表

    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项目

  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");
    });

     

    原文作者:熊猫猛男
    原文地址: https://www.cnblogs.com/XiongMaoMengNan/p/6505621.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞