This is an automated email from the ASF dual-hosted git repository.

nickva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/main by this push:
     new 7d9d2d360 Limit couch_server sharding
7d9d2d360 is described below

commit 7d9d2d36093b43d13a870ab4e9109c3bce98f5fb
Author: Nick Vatamaniuc <[email protected]>
AuthorDate: Thu Jun 4 15:50:59 2026 -0400

    Limit couch_server sharding
    
    With a default setting `max_dbs_open = 500` on servers with 128 CPU cores,
    per-instance LRU cache limits would become tiny (500/128 = 4). In that 
case, if
    just 4 db names on any gen_server randomly pick any the same server the 
cluster
    will start emitting `all_dbs_active` errors, even though in aggregate across
    all instances there will still be plenty of available LRU slots left.
    
    As a simple solution, let's limit the sharding factor with a config setting.
    Use the scheduler count on small instances and those will more schedulers 
are
    limited by the limit.
---
 rel/overlay/etc/default.ini    |  8 ++++++++
 src/couch/src/couch_server.erl | 15 ++++++++++++++-
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index ff148b271..0662e6afd 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -16,6 +16,14 @@ view_index_dir = {{view_index_dir}}
 ; among them.
 ;max_dbs_open = 500
 
+; Limit the maximum number of couch_server shards. Normally couch_server
+; instances equal the number of Erlang schedulers, which by default equal the
+; number of CPUs available on a node. However, to avoid over-sharding and
+; getting too low of a per-couch-server max_dbs_open threshold it's beneficial
+; to limit the sharding factor. This setting cannot be dynamically changed at
+; runtime, the node must be restarted for it to take effect.
+;max_couch_server_shards = 16
+
 ; Method used to compress everything that is appended to database and view 
index files, except
 ; for attachments (see the attachments section). Available methods are:
 ;
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index 9a4d8bffb..7eca53f3a 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -40,6 +40,8 @@
 -include("couch_server_int.hrl").
 
 -define(MAX_DBS_OPEN, 500).
+-define(DEFAULT_SHARDS, 16).
+-define(SHARD_COUNT_PKEY, {?MODULE, max_couch_server_shards}).
 -define(RELISTEN_DELAY, 5000).
 -define(DEFAULT_ENGINE, "couch").
 -define(AVAILABLE_JS_ENGINES, ["spidermonkey", "quickjs"]).
@@ -998,7 +1000,18 @@ name(BaseName, N) when is_integer(N), N > 0 ->
     list_to_atom(BaseName ++ "_" ++ integer_to_list(N)).
 
 num_servers() ->
-    erlang:system_info(schedulers).
+    % This value is not allowed to change at runtime. When we call this the
+    % first time from the supervisor we'll fix the value at that point and
+    % always return that from then on.
+    case persistent_term:get(?SHARD_COUNT_PKEY, undefined) of
+        undefined ->
+            Max = config:get_integer("couchdb", "max_couch_server_shards", 
?DEFAULT_SHARDS),
+            N = max(1, min(Max, erlang:system_info(schedulers))),
+            ok = persistent_term:put(?SHARD_COUNT_PKEY, N),
+            N;
+        N when is_integer(N), N >= 1 ->
+            N
+    end.
 
 aggregate_queue_len() ->
     N = num_servers(),

Reply via email to