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

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