You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ja...@apache.org on 2019/11/19 00:27:14 UTC
[couchdb] 02/06: Improve efficiency and observability of expiration
This is an automated email from the ASF dual-hosted git repository.
jaydoane pushed a commit to branch expiring-cache
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit c8f5c3f9199c64482f7b314c15b907faa1391841
Author: Jay Doane <ja...@apache.org>
AuthorDate: Tue Oct 29 00:03:19 2019 -0700
Improve efficiency and observability of expiration
---
.../src/couch_expiring_cache_fdb.erl | 55 ++++++++++++++------
.../src/couch_expiring_cache_server.erl | 58 ++++++++++++----------
2 files changed, 72 insertions(+), 41 deletions(-)
diff --git a/src/couch_expiring_cache/src/couch_expiring_cache_fdb.erl b/src/couch_expiring_cache/src/couch_expiring_cache_fdb.erl
index f432813..283a92b 100644
--- a/src/couch_expiring_cache/src/couch_expiring_cache_fdb.erl
+++ b/src/couch_expiring_cache/src/couch_expiring_cache_fdb.erl
@@ -13,6 +13,7 @@
-module(couch_expiring_cache_fdb).
-export([
+ clear_expired_range/2,
get_range/2,
cache_prefix/1,
layer_prefix/1,
@@ -22,11 +23,11 @@
%% delete_all/1,
insert/5,
lookup/2,
- remove/2
+ remove_primary/2
]).
--define(DEFAULT_LIMIT, 100000).
+-define(DEFAULT_LIMIT, 100000). % How to enforce?
-define(XC, 53). % coordinate with fabric2.hrl
-define(PK, 1).
@@ -78,12 +79,32 @@ get_range(EndTS, Limit) when Limit > 0 ->
remove_exp(ExpiresTS, Name, Key) ->
fabric2_fdb:transactional(fun(Tx) ->
- Prefix = layer_prefix(Tx),
+ clear_expired(Tx, ExpiresTS, Name, Key, layer_prefix(Tx))
+ end).
+
- PK = erlfdb_tuple:pack({?XC, ?PK, Name, Key}, Prefix),
- XK = erlfdb_tuple:pack({?XC, ?EXP, ExpiresTS, Name, Key}, Prefix),
- ok = erlfdb:clear(Tx, PK),
- ok = erlfdb:clear(Tx, XK)
+clear_expired(Tx, ExpiresTS, Name, Key, Prefix) ->
+ PK = primary_key(Name, Key, Prefix),
+ XK = expiry_key(ExpiresTS, Name, Key, Prefix),
+ ok = erlfdb:clear(Tx, PK),
+ ok = erlfdb:clear(Tx, XK).
+
+
+clear_expired_range(EndTS, Limit) when Limit > 0 ->
+ Callback = fun
+ (TS, 0) when TS > 0 -> TS;
+ (TS, Acc) -> min(TS, Acc)
+ end,
+ fabric2_fdb:transactional(fun(Tx) ->
+ LayerPrefix = layer_prefix(Tx),
+ ExpiresPrefix = erlfdb_tuple:pack({?XC, ?EXP}, LayerPrefix),
+ fabric2_fdb:fold_range({tx, Tx}, ExpiresPrefix, fun({K, _V}, Acc) ->
+ Unpacked = erlfdb_tuple:unpack(K, ExpiresPrefix),
+ couch_log:info("~p clearing ~p", [?MODULE, Unpacked]),
+ {ExpiresTS, Name, Key} = Unpacked,
+ clear_expired(Tx, ExpiresTS, Name, Key, LayerPrefix),
+ Callback(ExpiresTS, Acc)
+ end, 0, [{end_key, EndTS}, {limit, Limit}])
end).
@@ -91,11 +112,11 @@ insert(Name, Key, Val, StaleTS, ExpiresTS) ->
fabric2_fdb:transactional(fun(Tx) ->
Prefix = layer_prefix(Tx),
- PK = erlfdb_tuple:pack({?XC, ?PK, Name, Key}, Prefix),
+ PK = primary_key(Name, Key, Prefix),
PV = erlfdb_tuple:pack({Val, StaleTS, ExpiresTS}),
ok = erlfdb:set(Tx, PK, PV),
- XK = erlfdb_tuple:pack({?XC, ?EXP, ExpiresTS, Name, Key}, Prefix),
+ XK = expiry_key(ExpiresTS, Name, Key, Prefix),
XV = erlfdb_tuple:pack({}),
ok = erlfdb:set(Tx, XK, XV)
end).
@@ -105,7 +126,7 @@ lookup(Name, Key) ->
fabric2_fdb:transactional(fun(Tx) ->
Prefix = layer_prefix(Tx),
- PK = erlfdb_tuple:pack({?XC, ?PK, Name, Key}, Prefix),
+ PK = primary_key(Name, Key, Prefix),
case erlfdb:wait(erlfdb:get(Tx, PK)) of
not_found ->
not_found;
@@ -121,15 +142,21 @@ lookup(Name, Key) ->
end).
-remove(Name, Key) ->
+remove_primary(Name, Key) ->
fabric2_fdb:transactional(fun(Tx) ->
- Prefix = layer_prefix(Tx),
-
- PK = erlfdb_tuple:pack({?XC, ?PK, Name, Key}, Prefix),
+ PK = primary_key(Name, Key, layer_prefix(Tx)),
erlfdb:clear(Tx, PK)
end).
+primary_key(Name, Key, Prefix) ->
+ erlfdb_tuple:pack({?XC, ?PK, Name, Key}, Prefix).
+
+
+expiry_key(ExpiresTS, Name, Key, Prefix) ->
+ erlfdb_tuple:pack({?XC, ?EXP, ExpiresTS, Name, Key}, Prefix).
+
+
layer_prefix(Tx) ->
fabric2_fdb:get_dir(Tx).
diff --git a/src/couch_expiring_cache/src/couch_expiring_cache_server.erl b/src/couch_expiring_cache/src/couch_expiring_cache_server.erl
index 0072c38..f67e7be 100644
--- a/src/couch_expiring_cache/src/couch_expiring_cache_server.erl
+++ b/src/couch_expiring_cache/src/couch_expiring_cache_server.erl
@@ -28,8 +28,9 @@
]).
--define(PERIOD_DEFAULT, 10).
--define(MAX_JITTER_DEFAULT, 1).
+-define(DEFAULT_BATCH, 1000).
+-define(DEFAULT_PERIOD_MS, 5000).
+-define(DEFAULT_MAX_JITTER_MS, 1000).
start_link() ->
@@ -38,7 +39,11 @@ start_link() ->
init(_) ->
Ref = schedule_remove_expired(),
- {ok, #{timer_ref => Ref}}.
+ {ok, #{
+ timer_ref => Ref,
+ lag => 0,
+ last_expiration => 0,
+ min_ts => 0}}.
terminate(_, _) ->
@@ -54,9 +59,14 @@ handle_cast(Msg, St) ->
handle_info(remove_expired, St) ->
- ok = remove_expired(),
+ Now = erlang:system_time(second),
+ MinTS = remove_expired(Now),
Ref = schedule_remove_expired(),
- {noreply, St#{timer_ref => Ref}};
+ {noreply, St#{
+ timer_ref => Ref,
+ lag => Now - MinTS,
+ last_expiration => Now,
+ min_ts => MinTS}};
handle_info(Msg, St) ->
{stop, {bad_info, Msg}, St}.
@@ -66,33 +76,27 @@ code_change(_OldVsn, St, _Extra) ->
{ok, St}.
-remove_expired() ->
- Now = erlang:system_time(second),
- Limit = 10,
- Expired = couch_expiring_cache_fdb:get_range(Now, Limit),
- case Expired of
- [] ->
- ok;
- _ ->
- lists:foreach(fun({TS, Name, Key} = Exp) ->
- couch_log:info("~p remove_expired ~p", [?MODULE, Exp]),
- couch_expiring_cache_fdb:remove_exp(TS, Name, Key)
- end, Expired)
- end.
+remove_expired(EndTS) ->
+ couch_expiring_cache_fdb:clear_expired_range(EndTS, batch_size()).
schedule_remove_expired() ->
- Timeout = get_period_sec(),
- MaxJitter = max(Timeout div 2, get_max_jitter_sec()),
+ Timeout = period_ms(),
+ MaxJitter = max(Timeout div 2, max_jitter_ms()),
Wait = Timeout + rand:uniform(max(1, MaxJitter)),
- erlang:send_after(Wait * 1000, self(), remove_expired).
+ erlang:send_after(Wait, self(), remove_expired).
+
+
+period_ms() ->
+ config:get_integer("couch_expiring_cache", "period_ms",
+ ?DEFAULT_PERIOD_MS).
-get_period_sec() ->
- config:get_integer("couch_expiring_cache", "period_sec",
- ?PERIOD_DEFAULT).
+max_jitter_ms() ->
+ config:get_integer("couch_expiring_cache", "max_jitter_ms",
+ ?DEFAULT_MAX_JITTER_MS).
-get_max_jitter_sec() ->
- config:get_integer("couch_expiring_cache", "max_jitter_sec",
- ?MAX_JITTER_DEFAULT).
+batch_size() ->
+ config:get_integer("couch_expiring_cache", "batch_size",
+ ?DEFAULT_BATCH).