A high performant Erlang pool for eredis based on erlpool
Beside the fact that the most popular project in this area eredis_pool has a low activity in the last time, it has also the following problems:
- it's using another
gen_server
proxy from where get's the pid of the redis connection inside thepoolboy
checkout. This is most probably because in the pasteredis
was crashing thegen_server
when connection was lost and if too many crashes takes place in a short period of time the supervisor could stop. This is no longer the case as time newer versions of eredis can reconnect without crashing thegen_server
. poolboy
seems overkill for managing a pool of redis connections. Insteaderlpool
overhead is resumed only to one ETScounter_update
operation and onelookup
Getting all deps and compile:
rebar get-deps
rebar compile
You can define your pools inside app.config
:
[
{redis_pool, [
{pools, [
{mypool,[
{size, 10},
{host, "127.0.0.1"},
{port, 6379},
{database, 0},
{reconnect_sleep, 100}
]}
]}
]}
].
Or you can dynamically add/remove pools at runtime using start_pool/2
and stop_pool/1
:
redis_pool:start(),
Args = [
{size, 20},
{host, "127.0.0.1"},
{port, 6379}
],
redis_pool:start_pool(mypool, Args),
{ok, <<"OK">>} = redis_pool:q(mypool, [<<"SET">>, <<"foo">>, <<"bar">>]).
The supported options for a pool are:
size
: the pool size (how many connections are created)host
: redis server address (string, default:"127.0.0.1"
)port
: redis server port (integer, default:6379
)database
: database number (integer, default to0
)password
: database password (string, default empty password)reconnect_sleep
: in case connection to server is lost after how many milliseconds should try to reconnect (integer, default to100
)connect_timeout
: how many milliseconds will stay in connect until timeout (integer, default5000
)
The API is identical with the one from eredis exceptions making the transaction support:
Transactions are implemented using pipeline, this means that you need to send the list of the commands that you want to execute in the same transaction:
redis_pool:transaction(mypool, [["SET", var1, "1"], ["LPUSH", var2, "3"], ["LPUSH", var2, "2"]]).
{ok,[<<"OK">>,<<"1">>,<<"2">>]}
The code is in benchmark
folder. In the following test I send 300000 requests from 300 concurrent processes on a pool of 10 connections.
make bench
### 1355 ms 250000 req/sec
You can run it yourself using make bench
after you copy the load_test.erl
from benchmark folder in src and compile.