-
Notifications
You must be signed in to change notification settings - Fork 21
Private vs. Shared connections
When using the VMOD and calling redis.db() you choose between using 'private connections' or 'shared connections'.
When using private connections Redis connections are local to each Varnish worker thread. This is great because each worker has its own local connections (i.e. there is not extra thread contention when executing Redis queries); however, depending on the workload of your Varnish servers, and the number of different Redis instances you need to access to from your VCL, that number of connections could be too much.
Using shared connections is the alternative: Redis connections are shared between all Varnish workers threads using one or more pools. Obviously this adds extra thread contention, which may seriously harm the performance of your caching layer if the pools are not correctly dimensioned. On the other hand, this way you can limit the number of Redis connections created by the VMOD.
@davidfb and me crunched some numbers that may help you understand the performance differences between private and shared connections. Please, beware this is not a serious benchmark, but it's definitely something you may want to consider.
- Ubuntu Trusty, Intel Core i3-3220 CPU @ 3.30GHz × 4 (64 bits), 7.5GB RAM.
- Varnish Cache 4.1.2 revision 0d7404e (default configuration).
- Redis 3.0.7 (single server & persistence disabled).
- Redis VMOD 829778b.
siege -q -b -c 400 -t 60S http://192.168.4.104:6081/
- First row shows performance metrics when no Redis queries are executed.
| Shared conns | Max conns | # Varnish workers | # Redis conns | HTTP reqs / sec | Blocked workers |
|---|---|---|---|---|---|
| - | - | 737 | - | 10570 | - |
| NO | 1 | 811 | 807 | 8438 | - |
| YES | 1000 | 808 | 400 | 8417 | 0 |
| YES | 500 | 825 | 400 | 8605 | 0 |
| YES | 400 | 839 | 400 | 8285 | 0 |
| YES | 300 | 836 | 300 | 8664 | 990K |
| YES | 200 | 808 | 200 | 7873 | 1011K |
| YES | 100 | 808 | 100 | 7953 | 1211K |
| YES | 50 | 791 | 50 | 9122 | 1556K |
| YES | 25 | 790 | 25 | 9392 | 1604K |
| YES | 10 | 790 | 10 | 9431 | 1633K |
| YES | 5 | 753 | 5 | 9151 | 1614K |
| YES | 4 | 698 | 4 | 9088 | 1608K |
| YES | 3 | 624 | 3 | 8849 | 1561K |
| YES | 2 | 618 | 2 | 7906 | 1437K |
| YES | 1 | 535 | 1 | 5143 | 924K |
vcl 4.0;
import std;
import redis;
backend default {
.host = "127.0.0.1";
.port = "80";
}
sub vcl_init {
#new db = redis.db(
# location="127.0.0.1:6379",
# type=master,
# connection_timeout=500,
# connection_ttl=0,
# command_timeout=0,
# max_command_retries=0,
# shared_connections=false,
# max_connections=1,
# password="",
# sickness_ttl=0,
# max_cluster_hops=0);
#new db = redis.db(
# location="127.0.0.1:6379",
# type=master,
# connection_timeout=500,
# connection_ttl=0,
# command_timeout=0,
# max_command_retries=0,
# shared_connections=true,
# max_connections=1000,
# password="",
# sickness_ttl=0,
# max_cluster_hops=0);
#new db = redis.db(
# location="127.0.0.1:6379",
# type=master,
# connection_timeout=500,
# connection_ttl=0,
# command_timeout=0,
# max_command_retries=0,
# shared_connections=true,
# max_connections=500,
# password="",
# sickness_ttl=0,
# max_cluster_hops=0);
# ...
}
sub vcl_recv {
return (synth(200, "OK"));
}
sub vcl_synth {
if (req.url == "/stats") {
synthetic(db.stats());
} else {
db.command("SET");
db.push("foo");
db.push("Hello world!");
db.execute(true);
if (!db.reply_is_status()) {
std.syslog(6, "500");
set resp.status = 500;
}
db.free();
db.command("GET");
db.push("foo");
db.execute(true);
if (!db.reply_is_string()) {
std.syslog(6, "501");
set resp.status = 501;
}
db.free();
db.command("EVAL");
db.push({"
redis.call('SET', KEYS[1], ARGV[1]);
redis.call('EXPIRE', KEYS[1], ARGV[2]);
"});
db.push("1");
db.push("bar");
db.push(req.xid);
db.push("1");
db.execute(true);
if (!db.reply_is_nil()) {
std.syslog(6, "502");
set resp.status = 502;
}
db.free();
synthetic("");
}
return (deliver);
}