Redis PSYNC2 bug post mortem(antirez.com)
antirez.com
Redis PSYNC2 bug post mortem
http://antirez.com/news/115
31 コメント
Thanks for all you do antirez!
> the tests never try to mix PSYNC2 with replication of Lua scripts
This sort of testing gap is so hard to avoid. Any complex system has an inexhaustible number of potential feature interactions. It's very difficult at best to guess which combinations need to be tested, and often difficult to even write a test which exercises a particular combination.
What techniques do people use to ensure test coverage of complex cross-feature interactions like this? Two things I emphasize:
* Emphasize integration tests, and try to use multiple features in each test. This can help drive out interaction problems; the downside is that these tests are harder to write and (especially) maintain. It can also be difficult to exercise specific code paths.
* Write randomized tests, that exercise as many features as possible. The challenge here is identifying failures. "The program didn't assert or crash" is often a good start. A gold standard is to run a simple reference implementation alongside your real implementation, and compare the output... but that's not always possible.
This sort of testing gap is so hard to avoid. Any complex system has an inexhaustible number of potential feature interactions. It's very difficult at best to guess which combinations need to be tested, and often difficult to even write a test which exercises a particular combination.
What techniques do people use to ensure test coverage of complex cross-feature interactions like this? Two things I emphasize:
* Emphasize integration tests, and try to use multiple features in each test. This can help drive out interaction problems; the downside is that these tests are harder to write and (especially) maintain. It can also be difficult to exercise specific code paths.
* Write randomized tests, that exercise as many features as possible. The challenge here is identifying failures. "The program didn't assert or crash" is often a good start. A gold standard is to run a simple reference implementation alongside your real implementation, and compare the output... but that's not always possible.
If you mean randomized tests as in adding random choices to your tests, I think that is a very bad idea (that I have been bitten by before).
You NEED tests to behave consistently. If you run the tests twice against the same code, it needs to return the same result. Otherwise, how will you know you have fixed the issue the tests caught?
Speaking from experience, soon after you introduce randomness to tests, you will start to get intermittent test failures. When that happens, people will start to ignore failing tests because, 'hey, this is probably just a random failure'
You NEED tests to behave consistently. If you run the tests twice against the same code, it needs to return the same result. Otherwise, how will you know you have fixed the issue the tests caught?
Speaking from experience, soon after you introduce randomness to tests, you will start to get intermittent test failures. When that happens, people will start to ignore failing tests because, 'hey, this is probably just a random failure'
It's possible to have both randomness and reproduciblility - generate a random seed, log it, then explicitly seed the RNG. If you encounter a failure you suspect is caused by a particular random seed, temporarily hard-code that seed while you debug it.
The "that's an intermittent failure, just re-run it and it usually passes" attitude is in my experience more likely due to just plain old poorly-written tests, usually with a time.sleep() or something similar that makes them unreliable.
The "that's an intermittent failure, just re-run it and it usually passes" attitude is in my experience more likely due to just plain old poorly-written tests, usually with a time.sleep() or something similar that makes them unreliable.
Seeded RNG.
Exactly, you use a fixed RNG seed so that the behavior is reproducible.
For complex multithreaded code, it can become difficult to achieve consistent execution, but a fixed seed is at least a good start.
For complex multithreaded code, it can become difficult to achieve consistent execution, but a fixed seed is at least a good start.
So not really random, then? What is the point of adding an RNG if it is going to output the same values every time?
Because then the testing stimulus is not hard coded anymore, but generated. It's then trivial to run longer sequences, or tweak the test.
In hardware design, where reliability is key (making a chip costs multiple millions and 6 months time), there is only random testing (with seed for reproducibility), not "that bunch of case that the person testing thought of that day"
In hardware design, where reliability is key (making a chip costs multiple millions and 6 months time), there is only random testing (with seed for reproducibility), not "that bunch of case that the person testing thought of that day"
If you generate 10k test cases that find edge cases you wouldn't have normally found, that's value. If the framework is deterministic and always runs the same 10k test cases, that's generally valuable as well.
I'm not aware of anyone currently looking to ensure their test cases our generated using cryptographically random data.
I'm not aware of anyone currently looking to ensure their test cases our generated using cryptographically random data.
What techniques do people use to ensure test coverage of complex cross-feature interactions like this?
The Feynman Algorithm: http://wiki.c2.com/?FeynmanAlgorithm
It's the uncomfortable truth we like to dance around. Just accept you can't plan for everything. Think carefully before making design decisions. Build in contingency plans in case things go wrong.
The Feynman Algorithm: http://wiki.c2.com/?FeynmanAlgorithm
It's the uncomfortable truth we like to dance around. Just accept you can't plan for everything. Think carefully before making design decisions. Build in contingency plans in case things go wrong.
This. Fuzzing and integration tests is what usually is able to signal a regression.
We're all human – appreciate the write-up.
Is Redis a one-man show? (plus contributors)
I am still using memcached, but consider Redis in future.
I am looking for a Redis-based high-performance message-queue that can be filled from Nodejs and consumed with PHP. Basically a high-performance message-queue that doesn't need dozens of servers to start with.
I am still using memcached, but consider Redis in future.
I am looking for a Redis-based high-performance message-queue that can be filled from Nodejs and consumed with PHP. Basically a high-performance message-queue that doesn't need dozens of servers to start with.
Hello frik, Redis at this point is still handled by me directly for most parts, but we got recently (a few days ago) a new OSS payed contributor, https://github.com/artix75. Fabio works part time but 100% at Redis OSS. Additionally I receive help from Redis Labs core developers, and by an impressive Chinese community, see for instance the work made recently by http://github.com/soloestoy in pull requests about bug fixing and improvements. Plus other spontaneous contribs from other companies or individuals. I continue to be the person that writes most of the new code, basically, but without the contributions to bring stability, testing and investigations to Redis, it would not be practically possible to continue the development alone. Not now that we have so many subsystems: data structures, scripting, modules, replication, cluster, sentinel, persistence, and so forth.
About message queues, I developed recently one called "Disque", but this is going to be totally ported to Redis, as a module, during the first two quarters of 2018. Otherwise there are many other solutions, many of them are based on Redis itself.
About message queues, I developed recently one called "Disque", but this is going to be totally ported to Redis, as a module, during the first two quarters of 2018. Otherwise there are many other solutions, many of them are based on Redis itself.
For your use case, RabbitMQ will probably suffice. It can work very well with a single server, and, if you set it up in memory-only mode, is at least competitive with (if not superior to) Redis in terms of performance. If you use Rabbit's push-based subscriptions fully, it will far exceed Redis (edit: is Redis doing push-based pubsub these days? I'm told by a coworker that it is). I only mention this since you said "high-performance message-queue" in your comment; the out of the box performance of Redis and RMQ with zero tuning is more than enough for most people.
While Redis's protocol is simpler, it is a full memory database (with enableable persistence) plus optional queue/pubsub extensions. RabbitMQ is trying to be a full queue/pubsub system only, with memory and persistent options.
Its replication and durability features, if you want to add more servers, are also much longer-standing/more battle-tested (though far from perfect; I'm looking at you, "pause-minority" failures). Redis's persistence is quite good these days, though, so that's less of a competitive point.
RabbitMQ's setup is on par with Redis for simplicity. Client libs exist for PHP and Nodejs, and, while the protocol is more complex than Redis's, that usually just means "copy lines from $how_to_guide for startup/shutdown and then just publish/consume like you'd expect".
If I wanted a cache server that I occasionally needed to subscribe to, I'd use Redis no question. For a performance-oriented queue that needed either durability or throughput scalability, I'd start with Rabbit.
While Redis's protocol is simpler, it is a full memory database (with enableable persistence) plus optional queue/pubsub extensions. RabbitMQ is trying to be a full queue/pubsub system only, with memory and persistent options.
Its replication and durability features, if you want to add more servers, are also much longer-standing/more battle-tested (though far from perfect; I'm looking at you, "pause-minority" failures). Redis's persistence is quite good these days, though, so that's less of a competitive point.
RabbitMQ's setup is on par with Redis for simplicity. Client libs exist for PHP and Nodejs, and, while the protocol is more complex than Redis's, that usually just means "copy lines from $how_to_guide for startup/shutdown and then just publish/consume like you'd expect".
If I wanted a cache server that I occasionally needed to subscribe to, I'd use Redis no question. For a performance-oriented queue that needed either durability or throughput scalability, I'd start with Rabbit.
I would recommend checking out Faktory (https://github.com/contribsys/faktory), by the author of Sidekiq. It's fairly new but looks interesting.
For something production-tested already, I've found RabbitMQ to be very easy to operate as a single server. You obviously don't get HA with a single server, but it's been a breeze to manage.
For something production-tested already, I've found RabbitMQ to be very easy to operate as a single server. You obviously don't get HA with a single server, but it's been a breeze to manage.
Try https://github.com/antirez/disque. Written by the same guy behind Redis.
> Is Redis a one-man show? (plus contributors)
Well, yes, started by one man, and he continues to lead it, with many contributions from the community.
Update: I fixed the wrong URL.
> Is Redis a one-man show? (plus contributors)
Well, yes, started by one man, and he continues to lead it, with many contributions from the community.
Update: I fixed the wrong URL.
> Try https://github.com/resque/resque. Written by the same people behind Redis.
Huh? I don't think it is, Redis is by antirez .. https://github.com/resque/resque/graphs/contributors
Huh? I don't think it is, Redis is by antirez .. https://github.com/resque/resque/graphs/contributors
Right, not the same devs. Resque originally was from GitHub folks. Now probably maintained by other people.
Oh damn, I meant https://github.com/antirez/disque, not resque. Apologies.
FWIW, it appears the current plan is to not continue it as a standalone app but turn it into a redis module: https://gist.github.com/antirez/a3787d538eec3db381a41654e214...
Yeah, kind of. High quality software though, recommended for many things :)
MartinMond(5)