Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis TTL #206

Merged
merged 6 commits into from
Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cachedb/cachedb.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ testframe_lookup(struct module_env* env, struct cachedb_env* cachedb_env,

static void
testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
char* key, uint8_t* data, size_t data_len)
char* key, uint8_t* data, size_t data_len, time_t ATTR_UNUSED(ttl))
{
struct testframe_moddata* d = (struct testframe_moddata*)
cachedb_env->backend_data;
Expand Down Expand Up @@ -606,7 +606,8 @@ cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
/* call backend */
(*ie->backend->store)(qstate->env, ie, key,
sldns_buffer_begin(qstate->env->scratch_buffer),
sldns_buffer_limit(qstate->env->scratch_buffer));
sldns_buffer_limit(qstate->env->scratch_buffer),
qstate->return_msg->rep->ttl);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion cachedb/cachedb.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ struct cachedb_backend {

/** Store (env, cachedb_env, key, data, data_len) */
void (*store)(struct module_env*, struct cachedb_env*, char*,
uint8_t*, size_t);
uint8_t*, size_t, time_t);
};

#define CACHEDB_HASHSIZE 256 /* bit hash */
Expand Down
45 changes: 40 additions & 5 deletions cachedb/redis.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ struct redis_moddata {
struct timeval timeout; /* timeout for connection setup and commands */
};

static redisReply* redis_command(struct module_env*, struct cachedb_env*,
const char*, const uint8_t*, size_t);

static redisContext*
redis_connect(const struct redis_moddata* moddata)
{
Expand Down Expand Up @@ -90,6 +93,8 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
{
int i;
struct redis_moddata* moddata = NULL;
redisReply* rep;
int redis_reply_type = 0;

verbose(VERB_ALGO, "redis_init");

Expand All @@ -114,6 +119,26 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
for(i = 0; i < moddata->numctxs; i++)
moddata->ctxs[i] = redis_connect(moddata);
cachedb_env->backend_data = moddata;
if (env->cfg->redis_expire_records) {
/** check if setex command is supported */
rep = redis_command(env, cachedb_env, "SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0);
Talkabout marked this conversation as resolved.
Show resolved Hide resolved
if(!rep) {
/** init failed, no response from redis server*/
log_err("redis_init: failed to init redis, the redis-expire-records option requires the SETEX command (redis >= 2.0.0)");
return 0;
}
redis_reply_type = rep->type;
freeReplyObject(rep);
switch (redis_reply_type) {
case REDIS_REPLY_STATUS:
break;
default:
/** init failed, setex command not supported */
log_err("redis_init: failed to init redis, the redis-expire-records option requires the SETEX command (redis >= 2.0.0)");
return 0;
}
}

return 1;
}

Expand Down Expand Up @@ -249,16 +274,26 @@ redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,

static void
redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
char* key, uint8_t* data, size_t data_len)
char* key, uint8_t* data, size_t data_len, time_t ttl)
{
redisReply* rep;
char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+3+1]; /* "SET " + key + " %b" */
int n;
int set_ttl = (int)(env->cfg->redis_expire_records && (!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0));
char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1]; /* "SETEX " + key + " " + ttl + " %b" or "SET " + key + " %b"*/

if (!set_ttl) {
verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
/* build command to set to a binary safe string */
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
} else {
/* add expired ttl time to redis ttl to avoid premature eviction of key */
ttl += env->cfg->serve_expired_ttl;
verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u", key, (int)data_len, (uint32_t)ttl);
/* build command to set to a binary safe string */
n = snprintf(cmdbuf, sizeof(cmdbuf), "SETEX %s %u %%b", key, (uint32_t)ttl);
}

verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);

/* build command to set to a binary safe string */
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
if(n < 0 || n >= (int)sizeof(cmdbuf)) {
log_err("redis_store: unexpected failure to build command");
return;
Expand Down
8 changes: 8 additions & 0 deletions doc/unbound.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -2127,6 +2127,14 @@ If this timeout expires Unbound closes the connection, treats it as
if the Redis server does not have the requested data, and will try to
re-establish a new connection later.
This option defaults to 100 milliseconds.
.TP
.B redis-expire-records: \fI<yes or no>
If redis record expiration is enabled. If yes, unbound sets ttl for redis
records so that redis can evict keys that have expired automatically. If
unbound is configured to serve expired entries and there is no expired ttl
set, this option is internally reverted to "no". Redis SETEX support required
(redis >= 2.0.0).
This option defaults to no.
.SS DNSTAP Logging Options
DNSTAP support, when compiled in, is enabled in the \fBdnstap:\fR section.
This starts an extra thread (when compiled with threading) that writes
Expand Down
2 changes: 2 additions & 0 deletions util/config_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ config_create(void)
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
cfg->redis_timeout = 100;
cfg->redis_server_port = 6379;
cfg->redis_expire_records = 0;
#endif /* USE_REDIS */
#endif /* USE_CACHEDB */
#ifdef USE_IPSET
Expand Down Expand Up @@ -1135,6 +1136,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_STR(opt, "redis-server-host", redis_server_host)
else O_DEC(opt, "redis-server-port", redis_server_port)
else O_DEC(opt, "redis-timeout", redis_timeout)
else O_YNO(opt, "redis-expire-records", redis_expire_records)
#endif /* USE_REDIS */
#endif /* USE_CACHEDB */
#ifdef USE_IPSET
Expand Down
2 changes: 2 additions & 0 deletions util/config_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,8 @@ struct config_file {
int redis_server_port;
/** timeout (in ms) for communication with the redis server */
int redis_timeout;
/** set redis ttl value based on dns response ttl */
int redis_expire_records;
#endif
#endif

Expand Down
Loading