diff --git a/src/box/lua/snapshot_daemon.lua b/src/box/lua/snapshot_daemon.lua index 81b7bc6c4f0eaa9148294e59ecfb937d56d8705a..1db09b81d382c5825be704046738ab26394c3bd3 100644 --- a/src/box/lua/snapshot_daemon.lua +++ b/src/box/lua/snapshot_daemon.lua @@ -6,11 +6,14 @@ do local fio = require 'fio' local yaml = require 'yaml' local errno = require 'errno' + local digest = require 'digest' + local pickle = require 'pickle' local PREFIX = 'snapshot_daemon' local daemon = { snapshot_period = 0; + snapshot_period_bias = 0; snapshot_count = 6; } @@ -145,7 +148,7 @@ do local function next_snap_interval(self) - + -- don't do anything in hot_standby mode if box.info.status ~= 'running' or self.snapshot_period == nil or @@ -153,34 +156,8 @@ do return nil end - local interval = self.snapshot_period / 10 - - local time = fiber.time() - local snaps = fio.glob(fio.pathjoin(box.cfg.snap_dir, '*.snap')) - if snaps == nil or #snaps == 0 then - return interval - end - - local last_snap = snaps[ #snaps ] - local stat = fio.stat(last_snap) - - if stat == nil then - return interval - end - - - -- there is no activity in xlogs - if self.snapshot_period * 2 + stat.mtime < time then - return interval - end - - local time_left = self.snapshot_period + stat.mtime - time - if time_left > 0 then - return time_left - end - - return interval - + return self.snapshot_period - + (fiber.time() + self.snapshot_period_bias) % self.snapshot_period end local function daemon_fiber(self) @@ -221,6 +198,12 @@ do __index = { set_snapshot_period = function() daemon.snapshot_period = box.cfg.snapshot_period + if daemon.snapshot_period > 0 then + local rnd = pickle.unpack('i', digest.urandom(4)) + daemon.snapshot_period_bias = rnd % daemon.snapshot_period + else + daemon.snapshot_period_bias = 0 + end reload(daemon) return end, @@ -232,7 +215,9 @@ do end daemon.snapshot_count = box.cfg.snapshot_count reload(daemon) - end + end, + + next_snap_interval = next_snap_interval } }) diff --git a/test/box/snapshot_daemon.result b/test/box/snapshot_daemon.result index 169e7c2fb021db03778eafbd22e08ece2bbf78f5..0cf8bedb7e2314b698f4458d08e7fc006067cbb8 100644 --- a/test/box/snapshot_daemon.result +++ b/test/box/snapshot_daemon.result @@ -132,3 +132,46 @@ daemon.snapshot_count = 20 box.cfg{ snapshot_count = 0 } --- ... +-- first start daemon +box.cfg{ snapshot_count = 2, snapshot_period = 3600} +--- +... +period_bias = daemon.snapshot_period_bias +--- +... +next_snap_interval = daemon.next_snap_interval(daemon) +--- +... +test_snap_interval = 3600 - (fiber.time() + period_bias) % 3600 +--- +... +(next_snap_interval - test_snap_interval + 3600) % 3600 < 2 +--- +- true +... +biases = {} +--- +... +max_equals = 0 +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +for i = 1, 20 do + box.cfg{ snapshot_period = 0} + box.cfg{ snapshot_period = 3600} + biases[daemon.snapshot_period_bias] = (biases[daemon.snapshot_period_bias] or 0) + 1 + if biases[daemon.snapshot_period_bias] > max_equals then + max_equals = biases[daemon.snapshot_period_bias] + end +end + +test_run:cmd("setopt delimiter ''"); +--- +... +max_equals < 4 +--- +- true +... diff --git a/test/box/snapshot_daemon.test.lua b/test/box/snapshot_daemon.test.lua index cf98a93d9ed44a98cda376bfe94eb828a55cea70..8acaed3877e1b7ec771fb35b3810736ab924490c 100644 --- a/test/box/snapshot_daemon.test.lua +++ b/test/box/snapshot_daemon.test.lua @@ -72,3 +72,26 @@ daemon.snapshot_count = 20 -- stop daemon box.cfg{ snapshot_count = 0 } + +-- first start daemon +box.cfg{ snapshot_count = 2, snapshot_period = 3600} +period_bias = daemon.snapshot_period_bias +next_snap_interval = daemon.next_snap_interval(daemon) +test_snap_interval = 3600 - (fiber.time() + period_bias) % 3600 +(next_snap_interval - test_snap_interval + 3600) % 3600 < 2 + +biases = {} +max_equals = 0 +test_run:cmd("setopt delimiter ';'") + +for i = 1, 20 do + box.cfg{ snapshot_period = 0} + box.cfg{ snapshot_period = 3600} + biases[daemon.snapshot_period_bias] = (biases[daemon.snapshot_period_bias] or 0) + 1 + if biases[daemon.snapshot_period_bias] > max_equals then + max_equals = biases[daemon.snapshot_period_bias] + end +end + +test_run:cmd("setopt delimiter ''"); +max_equals < 4