nrk / redis-lua

A Lua client library for the redis key value storage system.
MIT License
733 stars 239 forks source link

support nonblocking behavior. #31

Closed littleboss closed 10 years ago

littleboss commented 10 years ago

i check the lua redis client in https://github.com/agentzh/lua-resty-redis, it support 100% nonblocking behavior. because it uses cosocket api,

dose this client api support non blocking

thanks

nrk commented 10 years ago

Hi @littleboss,

This is a blocking client implementation and currently there are no plans to add a non-blocking interface to it (to be honest I've never experimented with cosocket) as it's not a priority. Things may change in this respect with help coming from other developers though.

AMD-NICK commented 10 months ago

You can make a non-blocking (asynchronous) implementation using copas. It will look like this ( example with benchmark):

local redis  = require("redis")
local copas  = require("copas")
local socket = require("socket")

local get_connection = function(host, port, pass)
    local sock = socket.tcp()
    sock = copas.wrap(sock)
    sock:connect(host, port or 6379)

    local client = redis.connect({
        socket = sock,
    })
    client:auth(pass)
    return client
end

local now = socket.gettime
local start = now()
local reps = 1000
for i = 1, reps do

    copas.addthread(function()
        local host, port, pass = "redis", 6379, "redis-pass"
        local client = get_connection(host, port, pass)

        print(i, client:incr("bench") )
        reps = reps - 1
        if reps == 0 then
            print("finished in " .. (now() - start) .. " seconds") -- 0.18 seconds for 1000 requests
        end
    end)
end

copas.loop()

⚠️ Yes, we making a new connection for every request, but you always can implement connection pool with copas.queue and copas.semaphore like I done it here: click, so you will not have to create new connections for every request

Here is the benchmark for the default implementation:

local redis = require("redis")

local host, port, pass = "redis", 6379, "redis_pass"

local client = redis.connect(host, port or 6379)
client:auth(pass)

local now = require("socket").gettime
local start = now()
for _ = 1, 1000 do
    print( client:incr("bench1") )
end
print("finished in " .. (now() - start) .. " seconds") -- 11.95 seconds

As you can see, 1000 queries in the synchronous implementation are executed in 11 seconds, while "async" queries are executed in 0.18 seconds