Comments (17)
Agree something better than fatal error has to be done, but just returning that the key does not exist isn't a great solution either - WordPress will make thousands of SQL queries for each page load if the Object Cache is broken.
The best solution would be to look at the connection management in phpredis and if that connection fails, default to using the default Object Cache implementation, which is a simple non-persistent array structure.
from wp-redis.
Hey @jtsternberg - thanks for filing this. Picking up this issue to get it some love in September.
I can replicate this locally by taking down the redis container, and I agree that we should fall-back to the database as well as logging this to the error log.
from wp-redis.
We should also make the plugin "Pantheon savvy" and let the user know they need to enable it in the dashboard for it to work (if it isn't).
from wp-redis.
@joshkoenig curious, what is the status here? (for having it fallback to DB)
from wp-redis.
from wp-redis.
Other option that might be preferable: fall back to APC? Could this be a setting?
from wp-redis.
The best solution would be to look at the connection management in phpredis and if that connection fails, default to using the default Object Cache implementation, which is a simple non-persistent array structure.
Looking at this in a bit more depth. Because wp-redis.php/object-cache.php
defines the same functions and class name as wp-includes/cache.php
, we can't simply load and instantiate the latter.
In #10, I've subclassed Redis
so we can fall back to a run-time object cache when PHPRedis is unavailable. However, there's a conceptual problem we need to address:
- Redis is available, so WordPress uses it as a persistent object cache.
- Redis becomes unavailable, so WordPress falls back to its run-time object cache, adding, updating, and deleting keys.
- Redis becomes available again, so WordPress begins to pull now stale and incorrect values from the persistent storage backend.
from wp-redis.
Related tollmanz/wordpress-pecl-memcached-object-cache#55
from wp-redis.
@danielbachhuber your concerns are indeed valid. What if we store the modifed keys in an option (update the option at shutdown) and when persistent cache comes back, update (or delete) those keys? Not super-elegant, but better than getting stuck in a stale-cache feedback loop.
from wp-redis.
Redis is available, so WordPress uses it as a persistent object cache.
Redis becomes unavailable, so WordPress falls back to its run-time object cache, adding, updating, and deleting keys.
Redis becomes available again, so WordPress begins to pull now stale and incorrect values from the persistent storage backend.
How about this - if an error is detected and we fall back to the run-time object cache, we won't return to Redis during that request.
Side effects aren't that bad (you get newer data once the fallback kicks in) and everything is nice and tidy once the request is over. (The next request might use Redis if it's back.)
from wp-redis.
The side effects come with cache writes, which will do a DB update. The DB has a new value, but Redis doesn't know that. So the next time Redis kicks back on, it will pull back the value from the cache, NOT the updated value in the DB.
from wp-redis.
@joshkoenig and I talked about this a bit and came up with an idea:
- If WP Redis fails to connect to Redis, then WP Redis will write an option to the database documenting such and then fall back to the internal object cache.
- On every page load, WP Redis checks for the presence of this option. If the option exists, and WP Redis is able to reconnect to Redis, the WP Redis emits a
flushAll
call to Redis and removes the option. TheflushAll
would effectively ensure Redis won't serve stale results. - If the option doesn't exist and WP Redis can connect to Redis, then WP Redis would just serve the cache from Redis.
#18 is everything but the database write and check. I'm hesitant about a write stampede, and adding another SQL SELECT to every page load. However, I think we can mitigate both by making sure we're checking the primed alloptions
cache on reads, and doing a read check before we do a write. Plus, we can add a kill switch for this behavior (falling back to potentially serving stale cache) if someone runs into a situation where it's causing a performance problem.
from wp-redis.
That plan is similar to #4 (comment) except instead of flushing individual keys, you're flushing the entire cache, which is better than doing an option write every load where a key is updated/deleted. Seems like a pretty great solution to me. Thanks for the updates!
from wp-redis.
Thanks for the input @jtsternberg!
While it's a bummer to have to dump the cache on a the fail-back event, I think this is the only "bulletproof" way to insure cache coherence. Even if it does mean a slower request to repopulate caches, it is highly preferable to downtime or crazy difficult bugs due to cache incoherence.
@danielbachhuber +1 for having a killswitch option. I do not think one more sql select should be a problem. wp_options
is well keyed, and the data transferred is minimal, so it should add very little load (mysql actually makes a pretty good key-value store too...).
from wp-redis.
Clearing all cache on connection error is the safest route for sure.
From experience on a large multisite network, we get very high database load when object cache gets cleared, so that'd be a potential caveat for this solution.
from wp-redis.
@khromov I agree that there may be a case where big sites may want to handle things differently. The implementation will include a CONSTANT that will allow you to opt-out of the flushing problem. This opts you into a cache-coherency problem, but that's your choice! 😄
from wp-redis.
Hi
Just want to share (and hope not to confuse) as I see this issue mentions a similar issue in the memcached plugin @ tollmanz/wordpress-pecl-memcached-object-cache#55
First - I think it is important to keep in mind that once cache is introduced into a system - it is expected that cache might return stale data. This means that it might be nice to try and sync the external cache once it is available again after some downtime period, but the application should deal with it and not persist any objects/data which shouldn't be cached. I think WP is doing that correctly - so you shouldn't be concerned with that case.
Nevertheless, it seems like there is a core WP issue with external caching plugins, where there is a specific place where WP misbehave with external caching plugins which try to fallback to internal non persistant cache.
I have created a defect and a suggested fix to WP core and I suggest you to review it and understand that it might probably break your fallback strategy as well:
https://core.trac.wordpress.org/ticket/33276#ticket
(I should update my fix because it is incomplete but seems like there's no response anyway from the WP team for few months now)
from wp-redis.
Related Issues (20)
- many php warnings in my logs HOT 2
- CircleCI is not configured correctly HOT 4
- When `$wp_object_cache->is_redis_connected` is `false` there is a fatal error for `$missing_redis_message` HOT 4
- [BUGS-5944] Command "wp redis cli" fails HOT 1
- Fix some docblocks
- [BUGS-6118] PHP Deprecation notice on passing port = null @ Redis::connect() HOT 5
- As of WordPress 6.1 A Notice About Incorrect Support for `wp_cache_flush_runtime` HOT 8
- Re-add wordpress-upstream-tests to behat tests
- Fatal error in WP-CLI when accessing cache HOT 3
- esc_html is not safe to use (exception loop) HOT 3
- Implement PHPUnit and/or Behat tests for WP-CLI
- [BUGS-6318] file_exists(): open_basedir restriction in effect. HOT 9
- PHP 8.2 compatibility HOT 1
- [CMSP-467] Please don't strip all tags from the cache password. HOT 2
- [CMSP-470] Replace use of wp_strip_all_tags (possibly any wp filter function?) in object-cache.php
- Changes Merged from #360 Break Redis Connections on Pantheon Due to #400 and Incorrect array_replace_recursive call
- Large response size HOT 2
- [BUGS-6457] Warning when using tls protocol HOT 4
- PHP 8.1 deprecated warning
- Stale data returned after delete call when key was already deleted
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from wp-redis.