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_serverproxy from where get's the pid of the redis connection inside thepoolboycheckout. This is most probably because in the pasterediswas crashing thegen_serverwhen 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. poolboyseems overkill for managing a pool of redis connections. Insteaderlpooloverhead is resumed only to one ETScounter_updateoperation 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.