]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: Expire entries in bucket info cache 18954/head
authorAdam C. Emerson <aemerson@redhat.com>
Fri, 17 Nov 2017 22:15:26 +0000 (17:15 -0500)
committerAdam C. Emerson <aemerson@redhat.com>
Mon, 27 Nov 2017 20:57:15 +0000 (15:57 -0500)
To bound the degree to which an RGW instance can go out to lunch if
the watch/notify breaks down, force refresh of any cache entry over a
certain age.

Fifteen minutes by default, and expiration can be turned off entirely.

This is separate from the LRU. The LRU removes entries based on the
last time of access. This expiration patch forces refresh based on the
last time they were updated.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
src/common/options.cc
src/rgw/rgw_rados.h

index 0064af6652312f65d52f74251d0f6854940729e2..78365c699e00730b57009bd72cef0cb7a16164a1 100644 (file)
@@ -4300,7 +4300,7 @@ std::vector<Option> get_global_options() {
     Option("debug_deliberately_leak_memory", Option::TYPE_BOOL, Option::LEVEL_DEV)
     .set_default(false)
     .set_description(""),
-      
+
     Option("debug_asserts_on_shutdown", Option::TYPE_BOOL,Option::LEVEL_DEV)
     .set_default(false)
     .set_description("Enable certain asserts to check for refcounting bugs on shutdown; see http://tracker.ceph.com/issues/21738"),
@@ -5540,6 +5540,26 @@ std::vector<Option> get_rgw_options() {
     Option("rgw_reshard_thread_interval", Option::TYPE_UINT, Option::LEVEL_ADVANCED)
     .set_default(10_min)
     .set_description(""),
+
+    Option("rgw_bucket_info_cache_expiry_interval", Option::TYPE_UINT,
+          Option::LEVEL_ADVANCED)
+    .set_default(15_min)
+    .set_description("Number of seconds before entries in the bucket info "
+                    "cache are assumed stale and re-fetched. Zero is never.")
+    .add_tag("performance")
+    .add_service("rgw")
+    .set_long_description("The Rados Gateway stores metadata about buckets in "
+                         "an internal cache. This should be kept consistent "
+                         "by the OSD's relaying notify events between "
+                         "multiple watching RGW processes. In the event "
+                         "that this notification protocol fails, bounding "
+                         "the length of time that any data in the cache will "
+                         "be assumed valid will ensure that any RGW instance "
+                         "that falls out of sync will eventually recover. "
+                         "This seems to be an issue mostly for large numbers "
+                         "of RGW instances under heavy use. If you would like "
+                         "to turn off cache expiry, set this value to zero."),
+
   });
 }
 
index 57f8bf09c99e31d4b0d9ac1ad0d8c5c5259cfced..279180ac4524c215715d599f1d50cdd7b27987c6 100644 (file)
@@ -3747,25 +3747,32 @@ public:
 
 template <class T>
 class RGWChainedCacheImpl : public RGWChainedCache {
+  ceph::timespan expiry;
   RWLock lock;
 
-  map<string, T> entries;
+  map<string, std::pair<T, ceph::coarse_mono_time>> entries;
 
 public:
   RGWChainedCacheImpl() : lock("RGWChainedCacheImpl::lock") {}
 
   void init(RGWRados *store) {
     store->register_chained_cache(this);
+    expiry = std::chrono::seconds(store->ctx()->_conf->get_val<uint64_t>(
+                                   "rgw_bucket_info_cache_expiry_interval"));
   }
 
   bool find(const string& key, T *entry) {
     RWLock::RLocker rl(lock);
-    typename map<string, T>::iterator iter = entries.find(key);
+    auto iter = entries.find(key);
     if (iter == entries.end()) {
       return false;
     }
+    if (expiry.count() &&
+       (ceph::coarse_mono_clock::now() - iter->second.second) > expiry) {
+      return false;
+    }
 
-    *entry = iter->second;
+    *entry = iter->second.first;
     return true;
   }
 
@@ -3779,7 +3786,10 @@ public:
   void chain_cb(const string& key, void *data) override {
     T *entry = static_cast<T *>(data);
     RWLock::WLocker wl(lock);
-    entries[key] = *entry;
+    entries[key].first = *entry;
+    if (expiry.count() > 0) {
+      entries[key].second = ceph::coarse_mono_clock::now();
+    }
   }
 
   void invalidate(const string& key) override {