Hi Alex,
Sorry I'm pretty late to this thread. The original question is pretty interesting and not something I'd really thought about before.
If you have an odd-sized cluster and know with high confidence that a server is dead, you can remove it with no real change in behavior. For example, say I have {S1, S2, S3, S4, S5} but I know S5 is dead. Then any decision requires 3 of {S1, S2, S3, S4}. But that's the exact same property I get if I evict S5 from the cluster.
The same doesn't hold when you're starting with an even-sized cluster. For example, say I have {S1, S2, S3, S4} but I know S4 is dead. Then any decision requires all of {S1, S2, S3}. If I evict S4 from the cluster, now any decision requires only two of {S1, S2, S3}. That may be preferable, but it also may be fewer copies than the administrator had in mind. Taken to the extreme, would you be ok with a 1-server cluster? Probably not.
So maybe you want the administrator to set not only a target cluster size but also a minimum cluster size, such as target 5 and minimum of 3 or 4. Would this policy for an automated replacement task do the right thing?
while true {
while curr > min && exists dead server {
remove dead server;
}
while curr < target && exists spare healthy server {
add spare healthy server;
}
}
For manual replacement, where the server being replaced is healthy, I think you'd still want to add then remove.
Of course, determining whether a server is in fact dead is difficult to do exactly, but you might be happy with a heuristic in practice.
Another option is to implement the joint consensus approach to membership changes. It takes a moderate amount of additional work to implement, but it lets you replace any number of members atomically. If you're worried about this kind of thing, that may be worth it to you.
-Diego