From 8c6ccb5fd41864155a043856ff9240e84999e4bf Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Thu, 18 Jun 2020 11:48:14 -0700 Subject: proxy: Add a chance to skip memcache when looking for shard ranges By having some small portion of calls skip cache and go straight to disk, we can ensure the cache is always kept fresh and never expires (at least, for active containers). Previously, when shard ranges fell out of cache there would frequently be a thundering herd that could overwhelm the container server, leading to 503s served to clients or an increase in async pendings. Include metrics for hit/miss/skip rates. Change-Id: I6d74719fb41665f787375a08184c1969c86ce2cf Related-Bug: #1883324 --- swift/proxy/controllers/base.py | 12 +++++++++--- swift/proxy/controllers/container.py | 11 ++++++++++- swift/proxy/server.py | 8 +++++++- 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'swift/proxy') diff --git a/swift/proxy/controllers/base.py b/swift/proxy/controllers/base.py index 278a8b832..d08392601 100644 --- a/swift/proxy/controllers/base.py +++ b/swift/proxy/controllers/base.py @@ -33,6 +33,7 @@ import functools import inspect import itertools import operator +import random from copy import deepcopy from sys import exc_info @@ -2384,9 +2385,14 @@ class Controller(object): cached_ranges = infocache.get(cache_key) if cached_ranges is None and memcache: - cached_ranges = memcache.get(cache_key) - self.app.logger.increment('shard_updating.cache.%s' - % ('hit' if cached_ranges else 'miss')) + skip_chance = \ + self.app.container_updating_shard_ranges_skip_cache + if skip_chance and random.random() < skip_chance: + self.app.logger.increment('shard_updating.cache.skip') + else: + cached_ranges = memcache.get(cache_key) + self.app.logger.increment('shard_updating.cache.%s' % ( + 'hit' if cached_ranges else 'miss')) if cached_ranges: shard_ranges = [ diff --git a/swift/proxy/controllers/container.py b/swift/proxy/controllers/container.py index 6a54454a3..36cc53b3a 100644 --- a/swift/proxy/controllers/container.py +++ b/swift/proxy/controllers/container.py @@ -15,6 +15,7 @@ import json import math +import random import six from six.moves.urllib.parse import unquote @@ -150,7 +151,15 @@ class ContainerController(Controller): shard='listing') cached_ranges = infocache.get(cache_key) if cached_ranges is None and memcache: - cached_ranges = memcache.get(cache_key) + skip_chance = \ + self.app.container_listing_shard_ranges_skip_cache + if skip_chance and random.random() < skip_chance: + self.app.logger.increment('shard_listing.cache.skip') + else: + cached_ranges = memcache.get(cache_key) + self.app.logger.increment('shard_listing.cache.%s' % ( + 'hit' if cached_ranges else 'miss')) + if cached_ranges is not None: infocache[cache_key] = tuple(cached_ranges) # shard ranges can be returned from cache diff --git a/swift/proxy/server.py b/swift/proxy/server.py index e63d20d56..1e1388c41 100644 --- a/swift/proxy/server.py +++ b/swift/proxy/server.py @@ -35,7 +35,7 @@ from swift.common.utils import Watchdog, get_logger, \ get_remote_client, split_path, config_true_value, generate_trans_id, \ affinity_key_function, affinity_locality_predicate, list_from_csv, \ register_swift_info, parse_prefixed_conf, config_auto_int_value, \ - config_request_node_count_value + config_request_node_count_value, config_percent_value from swift.common.constraints import check_utf8, valid_api_version from swift.proxy.controllers import AccountController, ContainerController, \ ObjectControllerRouter, InfoController @@ -227,6 +227,12 @@ class Application(object): self.recheck_account_existence = \ int(conf.get('recheck_account_existence', DEFAULT_RECHECK_ACCOUNT_EXISTENCE)) + self.container_updating_shard_ranges_skip_cache = \ + config_percent_value(conf.get( + 'container_updating_shard_ranges_skip_cache_pct', 0)) + self.container_listing_shard_ranges_skip_cache = \ + config_percent_value(conf.get( + 'container_listing_shard_ranges_skip_cache_pct', 0)) self.allow_account_management = \ config_true_value(conf.get('allow_account_management', 'no')) self.container_ring = container_ring or Ring(swift_dir, -- cgit v1.2.1