MediaWiki master
|
Semaphore semantics to restrict how many workers may concurrently perform a task. More...
Inherits LoggerAwareInterface.
Inherited by MediaWiki\PoolCounter\PoolCounterClient, MediaWiki\PoolCounter\PoolCounterNull, and MediaWiki\PoolCounter\PoolCounterRedis.
Public Member Functions | |
__construct (array $conf, string $type, string $key) | |
acquireForAnyone ( $timeout=null) | |
I want to do this task, but if anyone else does it instead, it's also fine for me. | |
acquireForMe ( $timeout=null) | |
I want to do this task and I need to do it myself. | |
getKey () | |
getLogger () | |
isFastStaleEnabled () | |
Is fast stale mode (T250248) enabled? This may be overridden by the PoolCounterWork subclass. | |
release () | |
I have successfully finished my task. | |
setLogger (LoggerInterface $logger) | |
Public Attributes | |
const | DONE = 3 |
const | ERROR = -1 |
const | LOCK_HELD = -5 |
const | LOCKED = 1 |
const | NOT_LOCKED = -2 |
const | QUEUE_FULL = -3 |
const | RELEASED = 2 |
const | TIMEOUT = -4 |
Protected Member Functions | |
hashKeyIntoSlots ( $type, $key, $slots) | |
Given a key (any string) and the number of lots, returns a slot key (a prefix with a suffix integer from the [0..($slots-1)] range). | |
onAcquire () | |
Update any lock tracking information when the lock is acquired. | |
onRelease () | |
Update any lock tracking information when the lock is released. | |
precheckAcquire () | |
Checks that the lock request is sensible. | |
Protected Attributes | |
string | $key |
All workers with the same key share the lock. | |
LoggerInterface | $logger |
int | $maxqueue |
If this number of workers are already working/waiting, fail instead of wait. | |
int | $slots = 0 |
Maximum number of workers working on this task type, regardless of key. | |
int | $timeout |
Maximum time in seconds to wait for the lock. | |
int | $workers |
Maximum number of workers working on tasks with the same key simultaneously. | |
Semaphore semantics to restrict how many workers may concurrently perform a task.
When you have many workers (threads/servers) in service, and a cached item expensive to produce expires, you may get several workers computing the same expensive item at the same time.
Given enough incoming requests and the item expiring quickly (non-cacheable, or lots of edits or other invalidation events) that single task can end up unfairly using most (or all) of the CPUs of the server cluster. This is also known as "Michael Jackson effect", as this scenario happened on the English Wikipedia in 2009 on the day Michael Jackson died. See also https://wikitech.wikimedia.org/wiki/Michael_Jackson_effect.
PoolCounter was created to provide semaphore semantics to restrict the number of workers that may be concurrently performing a given task. Only one key can be locked by any PoolCounter instance of a process, except for keys that start with "nowait:". However, only non-blocking requests (timeout=0) may be used with a "nowait:" key.
By default PoolCounterNull is used, which provides no locking. Install the poolcounterd service from https://gerrit.wikimedia.org/g/mediawiki/services/poolcounter to enable this feature.
Definition at line 56 of file PoolCounter.php.
MediaWiki\PoolCounter\PoolCounter::__construct | ( | array | $conf, |
string | $type, | ||
string | $key ) |
array | $conf | |
string | $type | The class of actions to limit concurrency for (task type) |
string | $key |
Definition at line 104 of file PoolCounter.php.
References MediaWiki\PoolCounter\PoolCounter\$key, and MediaWiki\PoolCounter\PoolCounter\hashKeyIntoSlots().
|
abstract |
I want to do this task, but if anyone else does it instead, it's also fine for me.
I will read its cached data.
int | null | $timeout | Wait timeout, or null to use value passed to the constructor |
Reimplemented in MediaWiki\PoolCounter\PoolCounterClient, MediaWiki\PoolCounter\PoolCounterNull, and MediaWiki\PoolCounter\PoolCounterRedis.
|
abstract |
I want to do this task and I need to do it myself.
int | null | $timeout | Wait timeout, or null to use value passed to the constructor |
Reimplemented in MediaWiki\PoolCounter\PoolCounterClient, MediaWiki\PoolCounter\PoolCounterNull, and MediaWiki\PoolCounter\PoolCounterRedis.
MediaWiki\PoolCounter\PoolCounter::getKey | ( | ) |
Definition at line 125 of file PoolCounter.php.
References MediaWiki\PoolCounter\PoolCounter\$key.
MediaWiki\PoolCounter\PoolCounter::getLogger | ( | ) |
Definition at line 242 of file PoolCounter.php.
|
protected |
Given a key (any string) and the number of lots, returns a slot key (a prefix with a suffix integer from the [0..($slots-1)] range).
This is used for a global limit on the number of instances of a given type that can acquire a lock. The hashing is deterministic so that PoolCounter::$workers is always an upper limit of how many instances with the same key can acquire a lock.
string | $type | The class of actions to limit concurrency for (task type) |
string | $key | PoolCounter instance key (any string) |
int | $slots | The number of slots (max allowed value is 65536) |
Definition at line 215 of file PoolCounter.php.
References MediaWiki\PoolCounter\PoolCounter\$key, and MediaWiki\PoolCounter\PoolCounter\$slots.
Referenced by MediaWiki\PoolCounter\PoolCounter\__construct().
MediaWiki\PoolCounter\PoolCounter::isFastStaleEnabled | ( | ) |
Is fast stale mode (T250248) enabled? This may be overridden by the PoolCounterWork subclass.
Definition at line 225 of file PoolCounter.php.
|
finalprotected |
Update any lock tracking information when the lock is acquired.
Definition at line 191 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterRedis\waitForSlotOrNotif().
|
finalprotected |
Update any lock tracking information when the lock is released.
Definition at line 199 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterRedis\release(), and MediaWiki\PoolCounter\PoolCounterRedis\waitForSlotOrNotif().
|
finalprotected |
Checks that the lock request is sensible.
Definition at line 162 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterRedis\acquireForAnyone(), and MediaWiki\PoolCounter\PoolCounterRedis\acquireForMe().
|
abstract |
I have successfully finished my task.
Lets another one grab the lock, and returns the workers waiting on acquireForAnyone()
Reimplemented in MediaWiki\PoolCounter\PoolCounterClient, MediaWiki\PoolCounter\PoolCounterNull, and MediaWiki\PoolCounter\PoolCounterRedis.
MediaWiki\PoolCounter\PoolCounter::setLogger | ( | LoggerInterface | $logger | ) |
LoggerInterface | $logger |
Definition at line 234 of file PoolCounter.php.
References MediaWiki\PoolCounter\PoolCounter\$logger.
|
protected |
All workers with the same key share the lock.
Definition at line 69 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterRedis\__construct(), MediaWiki\PoolCounter\PoolCounter\__construct(), MediaWiki\PoolCounter\PoolCounter\getKey(), and MediaWiki\PoolCounter\PoolCounter\hashKeyIntoSlots().
|
protected |
Definition at line 83 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounter\setLogger().
|
protected |
If this number of workers are already working/waiting, fail instead of wait.
Definition at line 80 of file PoolCounter.php.
|
protected |
Maximum number of workers working on this task type, regardless of key.
0 means unlimited. Max allowed value is 65536. The way the slot limit is enforced is overzealous - this option should be used with caution.
Definition at line 78 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounter\hashKeyIntoSlots().
|
protected |
Maximum time in seconds to wait for the lock.
Definition at line 82 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterRedis\acquireForAnyone(), MediaWiki\PoolCounter\PoolCounterRedis\acquireForMe(), and MediaWiki\PoolCounter\PoolCounterRedis\waitForSlotOrNotif().
|
protected |
Maximum number of workers working on tasks with the same key simultaneously.
Definition at line 71 of file PoolCounter.php.
const MediaWiki\PoolCounter\PoolCounter::DONE = 3 |
Definition at line 60 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterWork\execute(), and MediaWiki\PoolCounter\PoolCounterRedis\waitForSlotOrNotif().
const MediaWiki\PoolCounter\PoolCounter::ERROR = -1 |
Definition at line 62 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterWork\execute().
const MediaWiki\PoolCounter\PoolCounter::LOCK_HELD = -5 |
Definition at line 66 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterWork\execute(), and MediaWiki\PoolCounter\PoolCounterRedis\waitForSlotOrNotif().
const MediaWiki\PoolCounter\PoolCounter::LOCKED = 1 |
const MediaWiki\PoolCounter\PoolCounter::NOT_LOCKED = -2 |
Definition at line 63 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterRedis\release().
const MediaWiki\PoolCounter\PoolCounter::QUEUE_FULL = -3 |
Definition at line 64 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterWork\execute(), and MediaWiki\PoolCounter\PoolCounterRedis\waitForSlotOrNotif().
const MediaWiki\PoolCounter\PoolCounter::RELEASED = 2 |
Definition at line 59 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterNull\release(), and MediaWiki\PoolCounter\PoolCounterRedis\release().
const MediaWiki\PoolCounter\PoolCounter::TIMEOUT = -4 |
Definition at line 65 of file PoolCounter.php.
Referenced by MediaWiki\PoolCounter\PoolCounterWork\execute(), and MediaWiki\PoolCounter\PoolCounterRedis\waitForSlotOrNotif().