天天看點

Nginx與Redis解決高并發問題

近期剛改版了上月上線的一個産品應用,以應對将來可能的高并發問題。

       第一版産品采用的是Jquery,Nginx,PHP(CI架構),Memcache,Mysql這種常用的架構。作為一名PHP工程師對于這種架構已經非常的熟悉了,目前站點并發并不是很高,線上環境使用的是阿裡雲主機,1.5G的記憶體,PHP并發能支援400~500左右。因為使用memcache的原因,如果在并發特别高的情況下,除了帶寬瓶頸以外就可能會是一直引以為傲PHP瓶頸了。增加機器便會增加成本,對于一個剛剛上線運作的項目,要求公司擴大投入是不合理的。

     于是在第二次改版的過程中我們嘗試放棄PHP,采用OpenResty中的LuaJit子產品直接讀取redis中的資料以Json的格式傳回給前端頁面展示,使用PHP腳本定時執行向redis裡面更新内容。這樣整合個前端過程就沒啥php與mysql哈事了(除後端定時執行腳本之外)。憑着nginx與redis的高并發,還怕啥呀!。下圖為新的架構主要結構。

        Redis是一個高性能的key-value資料庫。redis的出現,很大程度補償了memcache這類key-value存儲的不足,在部分場合可以對關系資料庫起到很好的補充作用。它提供了Python,Ruby,Erlang,PHP用戶端,使用很友善。

性能測試結果:SET操作每秒鐘110000 次,GET操作每秒鐘81000 次

        有了Redis作為保障,新架構就可以開搞了,使用到的主要關鍵詞由openResty,LuaJit,Lua,Redis,PHP,PHPRedis,JSon,JQuery等組成。讀者可以搜尋下各名詞了解它們的功能。下面是openResty中的Nginx配置:

nginx.conf

server {

        listen   80;

        root/home/boolean/Htdocs/lib.bincent.com;

        index index.htmlindex.htm;

        server_namelib.bincent.cn;

        #預設請求Html轉發到apache,這裡你可以根據自己情況配置

        location /

        {

                proxy_redirect off; 

                proxy_set_header HOST$host;  

                proxy_set_headerSERVER_ADDR $server_addr;  

                proxy_set_headerSERVER_PORT $server_port;  

                proxy_set_headerREMOTE_ADDR $remote_addr;  

                proxy_set_headerREMOTE_PORT $remote_port;  

        }

           #更新redis

        location /set_redis

            internal;

            set_unescape_uri$key $arg_key;

                set_unescape_uri$val $arg_val;

                redis2_queryset $key $val;

            redis2_pass127.0.0.1:6379;

           #讀取redis

        location /get_redis

        {

            internal;

            set_unescape_uri$key $arg_key;

            redis2_queryget $key;

            redis2_pass127.0.0.1:6379;

        }

           # 模拟的簡單請求

        location /json

            default_typetext/html;

                 content_by_lua_file/home/boolean/Htdocs/lib.bincent.com/lua/redis.lua;

}

redis.lua檔案

#通過URL更新redis

functionsetRedis(key, val)

    localres = ngx.location.capture('/set_redis', {

                args= {

                     key= key,

                     val= val

                    }

                })

    ifres.status == 200 then

        returntrue

    else

        returnfalse

    end

end

#通過URL讀取redis

functiongetRedis(key)

    localcapture = ngx.location.capture('/get_redis', {

                    key= key

    localparser = require 'redis.parser' --require redis.parser

    localres, err = parser.parse_reply(capture.body)

    returnres

#URL參數$_GET['a']

locala = ngx.var.arg_a

if'clean' == a then

    --重置redis

    ifsetRedis('love_number', 0) then

        ngx.say("CleanRedis Is Success!")

        ngx.say("CleanRedis Is failted!")

else

    --讀取redis

    locallove_number = getRedis('love_number') + 1

    setRedis('love_number',love_number)

    ngx.say("CurrentLove Number Is: ", love_number)

end如何聯系我:【萬裡虎】www.bravetiger.cn

【QQ】3396726884 (咨詢問題100元起,幫助解決問題500元起)

【部落格】http://www.cnblogs.com/kenshinobiy/