local function redis_get()
        local config = require 'core.config'
        local redis = require 'resty.redis'
        local  r = redis:new()
      
        r:add_commands('srandmembers') -- srem key member1 ...,spop key [conut], srandmember key [count]
        local csrv_rd_tmo = 1000
        r:set_timeout(csrv_rd_tmo)
        local ok, err = r:connect_cluster(config.kvhosts, config.kvhost_pwd)
        if not ok then
            ngx.log(ngx.ERR, 'redis_get:', err)
            r:close()
            return false
        end

        local csrv_db_idx = 5
        local rv, err = r:select(csrv_db_idx)
        if not rv then
            r:close()
            return false
        end
        local k = 'xxkey'
        local value, err = r:srandmember(k, 100)
	       if not value then
                  r:close()
               return false
	end
        if type(value) == 'table' and #value > 0 then
	    local ok, err = r:srem(k, unpack(value))
            if not ok then
                r:close()
                return false
            end
            return  value
        end
        return false
    end
ngx.timer.at(5, redis_get)

会发现redis.new 的占用空间在500字节左右,会每5s创建一次redis.new 对象,导致内存线性增长。

    kurapica 感谢,自己实际测试过增加r:set_keepalive()同样存在这个问题

      resty.new 只是创建一个管理用对象,一般请求结束也回收了。 https://github.com/openresty/lua-resty-redis#connect 中有一个pool需要指定,也就是连接池。你在这里用的connect_cluster我在官方这里没有找到,如果是自定义的,可以到它的定义中找下,试试加上pool。

      kurapica 已经找到了位置,如图这个API会导致redis.new无法释放这个对象。目前删除可以解决。但是这个函数在timer中使用是存在内存线性增长的问题,主要是在timer中循环周期性起timer存在这种情况。

        add_commands实际是静态函数,redis.add_commands("srandmembers"), 因为它本身实现没加类型验证,这个错误没被抛出。

        再看了下源码,每次调用都会重新注册一个匿名函数,虽然之前的可以被回收掉。但最好在初始化时注册,不要每次redis_get的调用一次。__

          10 days later

          谢谢反馈,你可以到lua-resty-redis中提issue吗?

            Write a Reply...