Introduces the rate_limiter, a replica-side data structure meant for tracking the frequence with which each partition is being accessed (separately for reads and writes) and deciding whether the request should be accepted and processed further or rejected. The limiter is implemented as a statically allocated hashmap which keeps track of the frequency with which partitions are accessed. Its entries are incremented when an operation is admitted and are decayed exponentially over time. If a partition is detected to be accessed more than its limit allows, requests are rejected with a probability calculated in such a way that, on average, the number of accepted requests is kept at the limit. The structure currently weights a bit above 1MB and each shard is meant to keep a separate instance. All operations are O(1), including the periodic timer.
50 lines
1.4 KiB
C++
50 lines
1.4 KiB
C++
/*
|
|
* Copyright (C) 2022-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <variant>
|
|
#include <seastar/util/bool_class.hh>
|
|
|
|
namespace db {
|
|
|
|
using allow_per_partition_rate_limit = seastar::bool_class<class allow_per_partition_rate_limit_tag>;
|
|
|
|
namespace per_partition_rate_limit {
|
|
|
|
// Tells the replica to account the operation (increase the corresponding counter)
|
|
// and accept it regardless from the value of the counter.
|
|
//
|
|
// Used when the coordinator IS a replica (correct node and shard).
|
|
struct account_only {};
|
|
|
|
// Tells the replica to account the operation and decide whether to reject
|
|
// or not, based on the random variable sent by the coordinator.
|
|
//
|
|
// Used when the coordinator IS NOT a replica (wrong node or shard).
|
|
struct account_and_enforce {
|
|
// A random 32-bit number generated by the coordinator.
|
|
// Replicas are supposed to use it in order to decide whether
|
|
// to accept or reject.
|
|
uint32_t random_variable;
|
|
|
|
inline double get_random_variable_as_double() const {
|
|
return double(random_variable) / double(1LL << 32);
|
|
}
|
|
};
|
|
|
|
// std::monostate -> do not count to the rate limit and never reject
|
|
// account_and_enforce -> account to the rate limit and optionally reject
|
|
using info = std::variant<std::monostate, account_only, account_and_enforce>;
|
|
|
|
} // namespace per_partition_rate_limit
|
|
|
|
} // namespace db
|
|
|