Özel sürüm önizlemesiGerçek ödeme alınmazSürüm ayrıntıları ↗

EN · ÖZGÜN DEPO BELGESİ

Güncel adaya geçiş

Özgün İngilizce metin. Komutlar ve kanıtlar, belgede belirtilen revizyona ve ortama aittir.

MIGRATION-v2.md

Bu sayfada

v2 migration and rollback

Version 1.26.0-rc.1 is a source review candidate, not a production-approved release. After the owner’s later PHP-test authorization, the local PHP 8.3.0 suite passed 37 regression cases and 148 assertions. A subsequent authorized Docker run passed six real WordPress/WooCommerce/standalone Redis integration scripts and the lifecycle suite, including the previously skipped WordPress contract. Topology/TLS/Relay, checkout isolation, scale and performance gates remain pending. Historical reports describe earlier code only. Track remaining gates in IMPLEMENTATION-STATUS.md.

Requirements and behavior

The separate optional ocp_remember() API requires coordinated configuration of stampede_groups on all workers. The default empty list keeps protection disabled. Drain old workers and in-flight callbacks before enabling/changing/disabling it; mixed source/configuration and direct Redis writes bypass the mutation protocol. Protected scopes incur extra transactions and lease scans. Read the complete remember contract, including the optional Redis 6.0.9+ capability requirement, no-replay/partial-EXEC limits and final test gates. The existing remember/sear helpers do not acquire leases or wait; cached false is now a hit.

Use PHP 8.2+ and PhpRedis 6.0+. Relay remains supported in source with runtime capability checks; licensed real-Relay verification remains open. Install the matching plugin and bundled object-cache.php drop-in from the same candidate. The public wp_cache_* entry points and WP_REDIS_CONFIG name remain unchanged.

Before enabling or upgrading, inspect the existing wp-content/object-cache.php. Automatic and admin file replacement/removal require its nonempty Plugin Name and Plugin URI headers to match this project’s bundled drop-in. Legacy upstream headers remain recognizable for compatibility but do not grant file ownership. Unidentified or unreadable files are preserved, and CLI disable also refuses to remove them. Keep a backup and disable the provider that manages that drop-in before installing this project’s stub. The existing wp redis enable --force command remains an explicit overwrite option; it warns on unowned files and does not create a backup automatically. The new migration wizard adds explicit preview, signed backup download and guarded install/restore actions; its runtime validation is deferred. Header matching is an accidental-conflict safeguard, not file integrity verification or atomic exclusion of another writer.

Identifiers use v2:<encoded prefix>:<encoded scope>:<encoded group>:{tag}:<encoded key>. Prefix, scope, group and string form of the key retain case, separators, whitespace and Unicode bytes. Integers and their equivalent string keys retain WordPress’s existing identity semantics. Site keys use site:N; global groups remain shared. Global/all-sites scope covers the sites using this cache prefix, including other networks sharing the same Redis database and prefix. Use separate prefixes for independent installations; a prefix is an application isolation boundary.

No old namespace is read on the first v2 request. Old data is not automatically deleted. Expect a cold-cache database load increase; the existence of old Redis data does not warm v2. Automatic integrity/lifecycle cleanup is limited to v2. Explicit full-database flush commands retain their existing broad behavior.

Split alloptions changes use WATCH/MULTI/EXEC on one captured primary connection. Only fields previously observed by the caller are eligible for removal. A watch conflict returns false, is not retried, and invalidates the local value. Redis does not roll back already executed commands after an individual EXEC error. Cluster resolves CLUSTER SLOTS before every WATCH and uses a direct, nonpersistent connection to the owning primary. Relay conditional reads use a connection with its local value cache disabled. Each owning connection can retain at most eight such sockets for subsequent transactions. Settings and native connection state must still match; failed or uncertain sockets are retired. When native state inspection is unavailable, the socket is closed after that operation as before. Native redirection or retry is not used to replay the transaction. Network access to the reported primary and permission for these commands are prerequisites. Connection reuse and its performance effect await the final test phase. Initial serializer/compression option failures now close the client and reject setup.

Persistent incr/decr now use the same watched-primary contract. Arithmetic, PHP serialization and nonpersistent-group behavior are retained. A missing key, conflict, write failure or unconfirmed EXEC returns false and invalidates the request-local value. Only a confirmed SET publishes the new integer. A false result after a lost reply does not prove that Redis stayed unchanged; do not blindly retry a non-idempotent mutation.

Counters read and memoize INFO on the captured physical connection to select expiry handling. Redis 6+ uses one SET XX KEEPTTL. Older servers use watched PTTL and one SET XX PX with the remaining lifetime, reduced by local elapsed time; persistent keys stay persistent. This relative-TTL fallback can drift by queue/transport delay and does not promise the exact original deadline. Missing, expired or invalid TTLs abort. INFO (and PTTL on older servers) must be permitted; unavailable capability information fails the mutation without a write. No failed SET is followed by an unconditional SET. See the Redis SET command contract.

Sentinel retries only commands on the existing read-only allowlist. Ordinary writes and unknown/raw commands disable native retries for their first send, restore the previous retry policy afterwards, and never replay after an error. Primary rediscovery prepares a later caller-initiated command; discovery failure does not replace the original write error. If restoring retry settings fails, the socket is closed. Buffered transactions retain their existing pinned behavior. Network failures can therefore surface as false/errors instead of silent recovery. The additional round trips and conflict rate still require measurement.

Raw metadata/analytics callbacks keep serialization and compression disabled when Sentinel discovers replacement primary/replica connections. Newly discovered nodes join every active raw scope before use; nested callbacks restore the immediately previous mode, and the outer callback restores each client’s original options. Pinned Cluster/Relay transactions also inherit the active raw scope and restore their normal options before pool reuse. Setup/cleanup failures retain the first error and an unsuccessful restoration attempts to close the affected client. These changes have source review only; real failover and native-client validation remain part of the final test phase.

Bounded defaults and management

Option Default Meaning
group_flush incremental Non-atomic PHP SCAN followed by deletion batches of at most 500 keys
prefetch_ttl 3600 Per-record metadata lifetime in seconds
prefetch_max_keys 256 Maximum recorded/prefetched keys in one request, across sites and runtime flushes
prefetch_max_requests 1024 Metadata request records per site, enforced through Redis transactions
log_limit 500 In-memory logger/command record cap; omitted records are counted
ttl_jitter 0 Optional 0-100% random reduction of each effective finite write TTL; disabled by default

TTL jitter runs after maxttl/queryttl limits, separately for each valid key in single/bulk writes and for split alloptions hashes. It never extends the capped TTL or changes a finite TTL to zero. Effective TTLs of zero (persistent) and one second stay unchanged. A 10% setting maps 600 seconds to 540-600 seconds inclusive. It adds no Redis commands, but random sampling and earlier expiry have an unmeasured cost. Counter increments/decrements still preserve expiry; internal metadata and prefetch retention keep their dedicated policies. Disabling jitter changes future writes only. No concurrent recomputation lock is provided by jitter. The separate stampede/remember API work remains outstanding.

The same configured limit also caps the request’s diagnostic error list, which retains its earliest records. Later errors still increment error metrics and reach the configured logger. info()->errors_omitted and the performance snapshot’s error_records_omitted report discarded error-list records; log_records_omitted continues to describe the separate logger buffer. Do not add these counters: the same error may be omitted from both buffers. Diagnostics, the overview widget and Site Health report truncation, and the latter two include discarded records in their error totals. A fresh cache initialization resets the error-list counter; runtime flushes and repeated initialization of the existing cache do not.

SCAN COUNT is a hint; deletion batches impose their own limit. Concurrent writes can occur between scan batches. Existing scan and keys Lua options remain atomic per Redis node and can block that node. They do not create a transaction across a cluster. group_flush=full retains database-wide behavior for the public group-flush operation and all-sites management actions; the UI labels this scope. Explicit site, prefetch and maintenance cleanup stays scoped and uses incremental SCAN even when the public group-flush setting is full.

Prefetch metadata uses a record hash and an expiry index in the same site scope. Equal container counts do not prove equal membership. Before crediting enough evictions to stay within the request limit, writes verify the relevant records and the current request’s index membership. Detected inconsistencies reset only that site’s two disposable metadata containers; cached application values remain intact. This adds a ZSCORE read to normal writes and HEXISTS reads for required evictions. The performance cost has not been measured. WATCH conflicts and failed EXEC replies are not replayed. Redis does not roll back partially applied EXEC commands: a failed write can leave damaged metadata, including a temporary cap overrun, for a subsequent successful write to repair or bound.

wp redis doctor --format=json and --format=table expose allowlisted health facts. Errors return nonzero; warnings remain visible with exit zero. TLS checks describe configuration and the connection probe, not a successful probe of every node. Method availability does not establish server ACL permission for every operation. Reports do not include passwords, tokens or cached values.

The performance widget labels current-request measurements. Historical charts require analytics to be enabled. Instrumented command attempts include failed attempts; their wait is included. They are not identical to the server’s command counter (connection handshakes and client-internal work are separate). Legacy cache read/write counters remain available. No external telemetry is added.

REST operations require objectcache_manage and validate site scope on the server. Site managers cannot select another site or global groups. Network managers may select their network’s sites or the existing all-sites prefix scope. A preview deletes nothing and reports bounded observations, never a definitive key count. Raw keys and values are replaced by fingerprints. Long-running workers must reset runtime cache between jobs.

Rollout gates

  1. Preserve an immutable copy of the previous plugin/drop-in, its configuration, and the candidate archive and SHA-256 manifest. Record the current namespace.
  2. Verify identical plugin/drop-in versions and runtime requirements on staging. Refresh PHP workers/OPcache when changing code. Do not mix code generations.
  3. Complete the real WordPress/WooCommerce, multisite, concurrency, topology/TLS and Relay contracts listed in IMPLEMENTATION-STATUS.md before acceptance.
  4. Capture at least five cold/warm repetitions with the same fixture/configuration. Bind each report to the installed runtime, drop-in and measurement harness. A warm p95 or PHP peak-memory increase above 5% blocks rollout.
  5. Start on staging, then one low-traffic site, then the multisite network. Monitor database query load, errors/timeouts and latency during each cold transition. Stop expansion when the agreed performance thresholds are exceeded.

No target staging/production installation or deployment is performed by this development work. Local PHP regressions or a review archive cannot satisfy these gates.

Explicit legacy cleanup

Retain old records until rollback planning and observation are complete. The command requires the exact, nonempty, previously normalized prefix (1-32 lowercase letters, digits, underscores or hyphens). Do not guess it. Installations that used an empty or otherwise unsupported legacy prefix need a separately reviewed, explicit inventory; the command does not widen the match to compensate.

wp redis cleanup-legacy --prefix=old-prefix --site-id=2 --group=posts
wp redis cleanup-legacy --prefix=old-prefix --site-id=2 --group=posts --execute --yes

The first command only samples fingerprints. The second removes matching old keys in bounded batches and can partially complete before a failure. Site scope excludes shared/global records. Omitting site/group widens only within the exact legacy prefix. It never interprets v2 identifiers as legacy records.

Rollback without stale cache reuse

  1. Stop writes/traffic or isolate the target so old and new workers cannot overlap.
  2. Before starting previous code, configure a fresh, unused prefix within the previous version’s length/character constraints, for example rollback-20261004a. Verify that it has no keys. Do not restore the old pre-v2 prefix.
  3. Restore both the previous plugin and its matching drop-in; restart/refresh PHP workers and OPcache. Keep the database and persistent business data intact.
  4. Warm and observe the empty rollback namespace, then reopen traffic gradually. Keep v2 records for diagnosis or remove only their explicitly selected scope.

Reinstalling v2 later should likewise use an unused prefix if its previous cache could have become stale while old code was serving requests.