openresty开发系列26--openresty中使用redis模块

在一些高并发的场景中,我们常常会用到缓存技术,现在我们常用的分布式缓存redis是最知名的,

操作redis,我们需要引入redis模块 require "resty.redis";

我们现在做个可以操作redis进行赋值,读值的案例

一)连接redis服务器

---定义 redis关闭连接的方法
local function close_redis(red)  
    if not red then  
        return  
    end  
    local ok, err = red:close()  
    if not ok then  
        ngx.say("close redis error : ", err)  
    end  
end

local redis = require "resty.redis"  --引入redis模块
local red = redis:new()  --创建一个对象,注意是用冒号调用的
--设置超时(毫秒)  
red:set_timeout(1000)
--建立连接  
local ip = "10.11.0.215"  
local port = 6379
local ok, err = red:connect(ip, port)
if not ok then  
    ngx.say("connect to redis error : ", err)  
    return close_redis(red)  
end  
--调用API设置key  
ok, err = red:set("msg", "hello world")  
if not ok then  
    ngx.say("set msg error : ", err)  
    return close_redis(red)  
end  
--调用API获取key值  
local resp, err = red:get("msg")  
if not resp then  
    ngx.say("get msg error : ", err)  
    return close_redis(red)  
end

ngx.say("msg : ", resp)
close_redis(red)

请求结果   msg : hello world

--------------------------------
注意:得到的数据为空处理 ,redis返回的空 为null,所以不能用nil判断,而要用ngx.null判断
if resp == ngx.null then  
    resp = ''  --比如默认值  
end

--------------连接授权的redis-----------------
在redis.conf配置文件 配置认证密码
requirepass redis123

注意:windows 启动redis时,配置redis.windows.conf;并且不能直接 双击redis-server.exe,
如果双击启动,默认不会找此目录下的配置文件;需要指定配置文件
解决方案:
1)cmd窗口中 运行 redis-server.exe redis.windows.conf
2)新建一个bat批处理文件  文件内容 redis-server.exe redis.windows.conf

连接报错set msg error : NOAUTH Authentication required.因为认证出错
在red:connect成功后,调用red:auth认证密码

ok, err = red:auth("redis123")
if not ok then
    ngx.say("failed to auth: ", err)
    return close_redis(red)
end

二)redis连接池

redis的连接是tcp连接,建立TCP连接需要三次握手,而释放TCP连接需要四次握手,而这些往返时延仅需要一次,
以后应该复用TCP连接,此时就可以考虑使用连接池,即连接池可以复用连接。
我们需要把close_redis函数改造一下

local function close_redis(red)  
    if not red then  
        return  
    end  
    --释放连接(连接池实现)  
    local pool_max_idle_time = 10000 --毫秒  
    local pool_size = 100 --连接池大小  
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)  
    if not ok then  
        ngx.say("set keepalive error : ", err)  
    end
end

即设置空闲连接超时时间防止连接一直占用不释放;设置连接池大小来复用连接。
注意:
1、连接池是每Worker进程的,而不是每Server的;
2、当连接超过最大连接池大小时,会按照LRU算法回收空闲连接为新连接使用;
3、连接池中的空闲连接出现异常时会自动被移除;
4、连接池是通过ip和port标识的,即相同的ip和port会使用同一个连接池(即使是不同类型的客户端);
5、连接池第一次set_keepalive时连接池大小就确定下了,不会再变更;

注意:我们如何知道,redis连接对象是从连接池中获取的,还是新创建的连接呢??

使用 red:get_reused_times --->得到此连接被使用的次数

如果当前连接不是从内建连接池中获取的,该方法总是返回 0 ,也就是说,该连接还没有被使用过。

如果连接来自连接池,那么返回值永远都是非零。所以这个方法可以用来确认当前连接是否来自池子。

连接优化

采用连接池,连接带认证的redis

---定义 redis关闭连接的方法
local function close_redis(red)  
    if not red then  
        return  
    end  
    --释放连接(连接池实现)  
    local pool_max_idle_time = 10000 --毫秒  
    local pool_size = 100 --连接池大小  
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)  
    if not ok then  
        ngx.say("set keepalive error : ", err)  
    end  
end

local redis = require "resty.redis"  --引入redis模块
local red = redis:new()  --创建一个对象,注意是用冒号调用的
--设置超时(毫秒)  
red:set_timeout(1000)
--建立连接  
local ip = "10.11.0.215"  
local port = 6379
local ok, err = red:connect(ip, port)
if not ok then  
    ngx.say("connect to redis error : ", err)  
    return close_redis(red)  
end

local count, err = red:get_reused_times()
if 0 == count then ----新建连接,需要认证密码
    ok, err = red:auth("redis123")
    if not ok then
        ngx.say("failed to auth: ", err)
        return
    end
elseif err then  ----从连接池中获取连接,无需再次认证密码
    ngx.say("failed to get reused times: ", err)
    return
end

--调用API设置key  
ok, err = red:set("msg", "hello world333333333")  
if not ok then  
    ngx.say("set msg error : ", err)  
    return close_redis(red)  
end  
--调用API获取key值  
local resp, err = red:get("msg")  
if not resp then  
    ngx.say("get msg error : ", err)  
    return close_redis(red)  
end

ngx.say("msg : ", resp)
close_redis(red)

=======================================

注意:连接池使用过程中,业务代码有select方法,会导致数据错乱

ok, err = red:select(1)  --->选择db
if not ok then
    ngx.say("failed to select db: ", err)
    return
end

如:
A业务使用了db1,所以使用了 select(1);

B业务使用默认的db0,select(0)遗漏

但A,B业务共用了连接池,很有可能 B业务拿到的 A业务使用的连接,而此连接操作的数据库db1;
而B业务中代码没有指定select数据库,所以B业务操作数据到了db1中;导致数据错乱

openresty开发系列26--openresty中使用redis模块的更多相关文章

  1. openresty开发系列36--openresty执行流程之6日志模块处理阶段

    openresty开发系列36--openresty执行流程之6日志模块处理阶段 一)header_filter_by_lua 语法:header_filter_by_lua <lua-scri ...

  2. openresty开发系列27--openresty中封装redis操作

    openresty开发系列27--openresty中封装redis操作 在关于web+lua+openresty开发中,项目中会大量操作redis, 重复创建连接-->数据操作-->关闭 ...

  3. openresty开发系列38--通过Lua+Redis 实现动态封禁IP

    openresty开发系列38--通过Lua+Redis 实现动态封禁IP 一)需求背景为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单.对于黑名单之内的 IP ,拒绝 ...

  4. openresty开发系列28--openresty中操作mysql

    openresty开发系列28--openresty中操作mysql Mysql客户端   应用中最常使用的就是数据库了,尤其mysql数据库,那openresty lua如何操作mysql呢?   ...

  5. openresty开发系列30--openresty中使用全局缓存

    openresty开发系列30--openresty中使用全局缓存 Nginx全局内存---本地缓存 使用过如Java的朋友可能知道如Ehcache等这种进程内本地缓存.Nginx是一个Master进 ...

  6. openresty开发系列29--openresty中发起http请求

    openresty开发系列29--openresty中发起http请求 有些场景是需要nginx在进行请求转发 用户浏览器请求url访问到nginx服务器,但此请求业务需要再次请求其他业务:如用户请求 ...

  7. openresty开发系列25--openresty中使用json模块

    openresty开发系列25--openresty中使用json模块 web开发过程中,经常用的数据结构为json,openresty中封装了json模块,我们看如何使用 一)如何引入cjson模块 ...

  8. openresty开发系列24--openresty中lua的引入及使用

    openresty开发系列24--openresty中lua的引入及使用 openresty 引入 lua 一)openresty中nginx引入lua方式 1)xxx_by_lua   ---> ...

  9. openresty开发系列16--lua中的控制结构if-else/repeat/for/while

    openresty开发系列16--lua中的控制结构if-else/repeat/for/while 一)条件 - 控制结构 if-else if-else 是我们熟知的一种控制结构.Lua 跟其他语 ...

随机推荐

  1. 思想家:潘石屹学python

    1.python在一些算法,图像处理,机器视觉方面越来越重要 2.计算机语言像英语一样,渐渐成为一种非专业技术,不能成为专业,而只能成为一种工具 3.想发挥工具价值,需要与别的专业结合,例如潘总的房地 ...

  2. P1341 无序字母对[欧拉路]

    题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 解析 毒瘤字符串读入 我就是不喜欢邻接 ...

  3. LG3768 简单的数学题

    P3768 简单的数学题 题目描述 输入一个整数n和一个整数p,你需要求出$(\sum_{i=1}^n\sum_{j=1}^n ijgcd(i,j))~mod~p$,其中gcd(a,b)表示a与b的最 ...

  4. 《Flask Web开发实战:入门、进阶与原理解析》 学习笔记

    一个视图函数可以绑定多个 URL 为了让互联网上的人都可以访问,需要安装程序的服务器有公网ip 如果过度使用扩展,在不需要 的地方引人,那么相应也会导致代码不容易维护 ,应该尽量从实际需求出发,只在需 ...

  5. IntelliJ IDEA:给 web 应用提供 JSTL 支持

    最近在看<Head First Servlet JSP>学习JSP,看到JSTL一章,为了添加JSTL支持折腾了好久. 网上的教程五花八门,而且多数比较旧. 我尝试了各种方法都没有成功,很 ...

  6. ES 基础理论 配置调优

    一.简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为 ...

  7. codevs 4014EZ系列

    4014 EZ系列之丁畅大大打小怪兽   题目描述 Description 丁畅大大除了喜欢吃鸡腿和番茄炒鸡蛋,还喜欢变成奥特曼去打小怪兽. 有一天,他遇到了迪迦!!!!!!!!!!!!!!!!!!! ...

  8. Tyvj P2044 ["扫地"杯III day2]旅游景点

    二次联通门 : Tyvj P2044 ["扫地"杯III day2]旅游景点 /* Tyvj P2044 ["扫地"杯III day2]旅游景点 并查集 先把大 ...

  9. Python 全栈开发【第0篇】:目录

    Python 全栈开发[第0篇]:目录   第一阶段:Python 开发入门 Python 全栈开发[第一篇]:计算机原理&Linux系统入门 Python 全栈开发[第二篇]:Python基 ...

  10. SpringData like关键字不起作用

    使用springdata简单查询时,like关键字不起作用 Hibernate: select article0_.oId as oId1_2_, article0_.articleAbstract ...