From d3c8ff6c0cc8241b8ee4b89ec2f123174881a615 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 21 Dec 2020 15:54:56 -0500 Subject: [PATCH] TT#63000 improve Redis SCAN increase and falloff Instead of making the COUNT increase and falloff dependent on the number of results produced, we make it dependent on the query run time. This is to prevent Redis being blocked by extended consecutive SCAN queries. Each individual query should not run longer than 100 ms, and we also add a short pause before going to the next SCAN to give competing queries a chance to run. Change-Id: I6b88cacf795513cf3e0aeefc67fbedef8e1bb8c1 (cherry picked from commit 2a23b940270fb066fdd90aab5e402fd6425f0ab3) --- debian/patches/series | 1 + .../sipwise/db_redis_graceful_scan.patch | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 debian/patches/sipwise/db_redis_graceful_scan.patch diff --git a/debian/patches/series b/debian/patches/series index b8b26b907..3c39b6fa7 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -58,3 +58,4 @@ upstream/tm-execute-TMCB_REQUEST_FWDED-cb-as-BRANCH_ROUTE-whe.patch ## backport from kamailio upstream (5.4) upstream/ndb_redis-set-message-level-to-debug-on-exec.patch sipwise/db_redis_skip_empty_keys.patch +sipwise/db_redis_graceful_scan.patch diff --git a/debian/patches/sipwise/db_redis_graceful_scan.patch b/debian/patches/sipwise/db_redis_graceful_scan.patch new file mode 100644 index 000000000..9f1dd354d --- /dev/null +++ b/debian/patches/sipwise/db_redis_graceful_scan.patch @@ -0,0 +1,52 @@ +--- a/src/modules/db_redis/redis_dbase.c ++++ b/src/modules/db_redis/redis_dbase.c +@@ -754,7 +754,7 @@ + int l; + + +-#undef USE_SCAN ++#define USE_SCAN + + #ifdef USE_SCAN + +@@ -762,6 +762,8 @@ + unsigned long cursor = 0; + unsigned int match_count = match_count_start_val; + char match_count_str[16]; ++ struct timeval start_tv, end_tv; ++ long tv_diff; + + do { + snprintf(cursor_str, sizeof(cursor_str), "%lu", cursor); +@@ -796,7 +798,12 @@ + goto err; + } + ++ gettimeofday(&start_tv, NULL); + reply = db_redis_command_argv(con, query_v); ++ gettimeofday(&end_tv, NULL); ++ tv_diff = ((long long) end_tv.tv_sec * 1000LL + end_tv.tv_usec / 1000L) ++ - ((long long) start_tv.tv_sec * 1000LL + start_tv.tv_usec / 1000L); ++ + db_redis_key_free(&query_v); + db_redis_check_reply(con, reply, err); + if (reply->type != REDIS_REPLY_ARRAY) { +@@ -870,11 +877,15 @@ + } + + #ifdef USE_SCAN +- // exponential increase and falloff, hovering around 1000 results +- if (keys_list->elements > 1300 && match_count > 500) ++ // exponential increase and falloff, not to exceed ~100 ms query run time ++ if (tv_diff > 50 && match_count > 10) + match_count /= 2; +- else if (keys_list->elements < 700 && match_count < 500000) ++ else if (tv_diff < 25 && match_count < 1000000) + match_count *= 2; ++ if (cursor > 0) { ++ // give other queries some time to run ++ usleep(100000); ++ } + #endif + + db_redis_free_reply(&reply);