<div dir="ltr"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="color:rgb(0,0,0);font-size:12.8px">That's the correct behaviour: it should return true iff a value was actually deleted.</span></blockquote><div><br></div><div>Ok, if that's the case you should do another FetchValue after the deletion (to update the <span style="color:rgb(0,0,0);font-family:monospace,monospace;font-size:12.8px">response.hasValues()</span><span style="color:rgb(0,0,0);font-size:12.8px"><font face="arial, helvetica, sans-serif">) field, or use the async version of the delete function. I also noticed that we weren't passing the vclock to the Delete function, so I added that here as well:</font></span></div><div><span style="color:rgb(0,0,0);font-size:12.8px"><font face="arial, helvetica, sans-serif"><br></font></span></div><div><pre style="color:rgb(0,0,0);font-family:Menlo;font-size:10.5pt"><pre style="font-family:Menlo;font-size:10.5pt"><span style="color:rgb(0,0,128);font-weight:bold">public boolean </span>delete(String key) <span style="color:rgb(0,0,128);font-weight:bold">throws </span>ExecutionException, InterruptedException {<br><br>    <span style="color:rgb(128,128,128);font-style:italic">// fetch in order to get the causal context<br></span><span style="color:rgb(128,128,128);font-style:italic">    </span>FetchValue.Response response = fetchValue(key);<br><br>    <span style="color:rgb(0,0,128);font-weight:bold">if</span>(response.isNotFound())<br>    {<br>        <span style="color:rgb(0,0,128);font-weight:bold">return </span>???; <span style="color:rgb(128,128,128);font-style:italic">// what do we return if it doesn't exist?<br></span><span style="color:rgb(128,128,128);font-style:italic">    </span>}<br><br>    DeleteValue deleteValue = <span style="color:rgb(0,0,128);font-weight:bold">new </span>DeleteValue.Builder(<span style="color:rgb(0,0,128);font-weight:bold">new </span>Location(<span style="color:rgb(102,14,122);font-weight:bold">namespace</span>, key))<br>                                             .withVClock(response.getVectorClock())<br>                                             .build();<br><br>    <span style="color:rgb(0,0,128);font-weight:bold">final </span>RiakFuture<Void, Location> deleteFuture = <span style="color:rgb(102,14,122);font-weight:bold">client</span>.executeAsync(deleteValue);<br><br>    deleteFuture.await();</pre><pre style="font-family:Menlo;font-size:10.5pt">    <span style="color:rgb(0,0,128);font-weight:bold">if</span>(deleteFuture.isSuccess()) <br>    {<br>        <span style="color:rgb(0,0,128);font-weight:bold">return true</span>;<br>    }<br>    <span style="color:rgb(0,0,128);font-weight:bold">else<br></span><span style="color:rgb(0,0,128);font-weight:bold">    </span>{<br>        deleteFuture.cause(); <span style="color:rgb(128,128,128);font-style:italic">// Cause of failure<br></span><span style="color:rgb(128,128,128);font-style:italic">        </span><span style="color:rgb(0,0,128);font-weight:bold">return false</span>;<br>    }<br>}</pre><pre style="font-family:Menlo;font-size:10.5pt"><br></pre></pre></div><div><span style="color:rgb(0,0,0);font-size:12.8px"><font face="arial, helvetica, sans-serif">Thanks,</font></span></div><div><span style="color:rgb(0,0,0);font-size:12.8px"><font face="arial, helvetica, sans-serif">Alex</font></span></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Feb 22, 2016 at 10:48 AM, Vanessa Williams <span dir="ltr"><<a href="mailto:vanessa.williams@thoughtwire.ca" target="_blank">vanessa.williams@thoughtwire.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">See inline:<br><div class="gmail_extra"><br><div class="gmail_quote"><span class="">On Mon, Feb 22, 2016 at 10:31 AM, Alex Moore <span dir="ltr"><<a href="mailto:amoore@basho.com" target="_blank">amoore@basho.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Vanessa,<div><br></div><div>You might have a problem with your delete function (depending on it's return value). </div><div>What does the return value of the delete() function indicate?  Right now if an object existed, and was deleted, the function will return true, and will only return false if the object didn't exist or only consisted of tombstones. </div></div></blockquote><div><br></div><div><br></div></span><div>That's the correct behaviour: it should return true iff a value was actually deleted.</div><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><pre style="color:rgb(0,0,0);font-family:Menlo;font-size:10.5pt"><span style="font-family:arial,sans-serif;font-size:small;color:rgb(34,34,34)">If you never look at the object value returned by your </span><span style="font-size:small;color:rgb(34,34,34);font-family:monospace,monospace">fetchValue(key)</span><span style="font-family:arial,sans-serif;font-size:small;color:rgb(34,34,34)"> function, another potential optimization you could make is to only return the HEAD / metadata:</span><br></pre></div><div><span style="color:rgb(0,0,0);font-family:Menlo;font-size:10.5pt">FetchValue fv = </span><span style="font-family:Menlo;font-size:10.5pt;color:rgb(0,0,128);font-weight:bold">new </span><span style="color:rgb(0,0,0);font-family:Menlo;font-size:10.5pt">FetchValue.Builder(</span><span style="font-family:Menlo;font-size:10.5pt;color:rgb(0,0,128);font-weight:bold">new </span><span style="color:rgb(0,0,0);font-family:Menlo;font-size:10.5pt">Location(</span><span style="font-family:Menlo;font-size:10.5pt;color:rgb(0,0,128);font-weight:bold">new </span><span style="color:rgb(0,0,0);font-family:Menlo;font-size:10.5pt">Namespace(</span><span style="font-family:Menlo;font-size:10.5pt;color:rgb(0,128,0);font-weight:bold">"some_bucket"</span><span style="color:rgb(0,0,0);font-family:Menlo;font-size:10.5pt">), key))</span><br></div><div><pre style="color:rgb(0,0,0);font-family:Menlo;font-size:10.5pt">                              .withOption(FetchValue.Option.<span style="color:rgb(102,14,122);font-weight:bold;font-style:italic">HEAD</span>, <span style="color:rgb(0,0,128);font-weight:bold">true</span>)<br>                              .build();</pre></div><div class="gmail_extra">This would be more efficient because Riak won't have to send you the values over the wire, if you only need the metadata.</div><div class="gmail_extra"><br></div></div></blockquote><div><br></div></span><div>Thanks, I'll clean that up.</div><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"></div><div class="gmail_extra">If you do write this up somewhere, share the link! :) </div></div></blockquote><div><br></div></span><div>Will do!</div><div><br></div><div>Regards,</div><div>Vanessa</div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><br></div><div class="gmail_extra">Thanks,</div><div class="gmail_extra">Alex</div><div><div><div class="gmail_extra"><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Feb 22, 2016 at 6:23 AM, Vanessa Williams <span dir="ltr"><<a href="mailto:vanessa.williams@thoughtwire.ca" target="_blank">vanessa.williams@thoughtwire.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Dmitri, this thread is old, but I read this part of your answer carefully:<div><br></div><div><span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">You can use the following strategies to prevent stale values, in increasing order of security/preference:<br>1) Use timestamps (and not pass in vector clocks/causal context). This is ok if you're not editing objects, or you're ok with a bit of risk of stale values.<br>2) Use causal context correctly (which means, read-before-you-write -- in fact, the Update operation in the java client does this for you, I think). And if Riak can't determine which version is correct, it will fall back on timestamps.<br>3) Turn on siblings, for that bucket or bucket type.  That way, Riak will still try to use causal context to decide the right value. But if it can't decide, it will store BOTH values, and give them back to you on the next read, so that your application can decide which is the correct one.</blockquote><div><br></div></span><div>I decided on strategy #2. What I am hoping for is some validation that the code we use to "get", "put", and "delete" is correct in that context, or if it could be simplified in some cases. Not we are using delete-mode "immediate" and no duplicates. </div></div><div><br></div><div>In their shortest possible forms, here are the three methods I'd like some feedback on (note, they're being used in production and haven't caused any problems yet, however we have very few writes in production so the lack of problems doesn't support the conclusion that the implementation is correct.) Note all argument-checking, exception-handling, and logging removed for clarity. <b>I'm mostly concerned about correct use of causal context and response.isNotFound and response.hasValues. </b>Is there anything I could/should have left out?</div><div><br></div><div><div><font face="arial, helvetica, sans-serif"> </font><font face="monospace, monospace">   public RiakClient(String name, com.basho.riak.client.api.RiakClient client)</font></div><div><font face="monospace, monospace">    {</font></div><div><font face="monospace, monospace">        <a href="http://this.name" target="_blank">this.name</a> = name;</font></div><div><font face="monospace, monospace">        this.namespace = new Namespace(name);</font></div><div><font face="monospace, monospace">        this.client = client;</font></div><div><font face="monospace, monospace">    }</font></div><div><br></div><div><font face="monospace, monospace">    public byte[] get(String key) throws ExecutionException, InterruptedException {</font></div><div><br></div><div><font face="monospace, monospace">        FetchValue.Response response = fetchValue(key);</font></div><div><font face="monospace, monospace">        if (!response.isNotFound())</font></div><div><font face="monospace, monospace">        {</font></div><div><font face="monospace, monospace">            RiakObject riakObject = response.getValue(RiakObject.class);</font></div><div><font face="monospace, monospace">            return riakObject.getValue().getValue();</font></div><div><font face="monospace, monospace">        }</font></div><div><span style="font-family:monospace,monospace">        return null;</span><br></div><div><font face="monospace, monospace">    }</font></div><div><br></div><div><font face="monospace, monospace">    public void put(String key, byte[] value) throws ExecutionException, InterruptedException {</font></div><div><br></div><div><span style="font-family:monospace,monospace">        // fetch in order to get the causal context</span><br></div><div><font face="monospace, monospace">        FetchValue.Response response = fetchValue(key);</font></div><div><font face="monospace, monospace">        RiakObject storeObject = new  </font></div><div><font face="monospace, monospace">            RiakObject().setValue(BinaryValue.create(value)).setContentType("binary/octet-stream");</font></div><div><font face="monospace, monospace">        StoreValue.Builder builder = </font></div><div><font face="monospace, monospace">            new StoreValue.Builder(storeObject).withLocation(new Location(namespace, key));</font></div><div><font face="monospace, monospace">        if (response.getVectorClock() != null) {</font></div><div><font face="monospace, monospace">            builder = builder.withVectorClock(response.getVectorClock());</font></div><div><font face="monospace, monospace">        }</font></div><div><font face="monospace, monospace">        StoreValue storeValue = builder.build();</font></div><div><font face="monospace, monospace">        client.execute(storeValue);</font></div><div><span style="font-family:monospace,monospace">    }</span><br></div><div><br></div><div><font face="monospace, monospace">    public boolean delete(String key) throws ExecutionException, InterruptedException {</font></div><div><br></div><div><span style="font-family:monospace,monospace">        // fetch in order to get the causal context</span><br></div><div><font face="monospace, monospace">        FetchValue.Response response = fetchValue(key);</font></div><div><font face="monospace, monospace">        if (!response.isNotFound())</font></div><div><font face="monospace, monospace">        {</font></div><div><font face="monospace, monospace">            DeleteValue deleteValue = new DeleteValue.Builder(new Location(namespace, key)).build();</font></div><div><font face="monospace, monospace">            client.execute(deleteValue);</font></div><div><font face="monospace, monospace">        }</font></div><div><font face="monospace, monospace">        return !response.isNotFound() || !response.hasValues();</font></div><div><font face="monospace, monospace">    }</font></div></div><div><br></div><div><br></div><div>Any comments much appreciated. I want to provide a minimally correct example of simple client code somewhere (GitHub, blog post, something...) so I don't want to post this without review.</div><div><br></div><div>Thanks,</div><div>Vanessa</div><div><br></div><div>ThoughtWire Corporation</div><div><a href="http://www.thoughtwire.com" target="_blank">http://www.thoughtwire.com</a></div><div><br></div><div><br></div><div><br></div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 8, 2015 at 8:45 AM, Dmitri Zagidulin <span dir="ltr"><<a href="mailto:dzagidulin@basho.com" target="_blank">dzagidulin@basho.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div>Hi Vanessa,<br><br></div>The thing to keep in mind about read repair is -- it happens asynchronously on every GET, but /after/ the results are returned to the client.<br><br></div>So, when you issue a GET with r=1, the coordinating node only waits for 1 of the replicas before responding to the client with a success, and only afterwards triggers read-repair.  <br><br>It's true that with notfound_ok=false, it'll wait for the first non-missing replica before responding. But if you edit or update your objects at all, an R=1 still gives you a risk of stale values being returned. <br><br></div>For example, say you write an object with value A.  And let's say your 3 replicas now look like this:<br><br></div><div>replica 1: A,  replica 2: A, replica 3: notfound/missing<br><br></div><div>A read with an R=1 and notfound_ok=false is just fine, here. (Chances are, the notfound replica will arrive first, but the notfound_ok setting will force the coordinator to wait for the first non-empty value, A, and return it to the client. And then trigger read-repair).<br><br></div><div>But what happens if you edit that same object, and give it a new value, B?  So, now, there's a chance that your replicas will look like this:<br><br></div><div>replica 1: A, replica 2: B, replica 3: B.<br><br></div><div>So now if you do a read with an R=1, there's a chance that replica 1, with the old value of A, will arrive first, and that's the response that will be returned to the client.<br><br></div><div>Whereas, using R=2 eliminates that risk -- well, at least decreases it. You still have the issue of -- how does Riak decide whether A or B is the correct value? Are you using causal context/vclocks correctly? (That is, reading the object before you update, to get the correct causal context?) Or are you relying on timestamps? (This is an ok strategy, provided that the edits are sufficiently far apart in time, and you don't have many concurrent edits, AND you're ok with the small risk of occasionally the timestamp being wrong). You can use the following strategies to prevent stale values, in increasing order of security/preference:<br><br></div><div>1) Use timestamps (and not pass in vector clocks/causal context). This is ok if you're not editing objects, or you're ok with a bit of risk of stale values.<br><br></div><div>2) Use causal context correctly (which means, read-before-you-write -- in fact, the Update operation in the java client does this for you, I think). And if Riak can't determine which version is correct, it will fall back on timestamps.<br><br></div><div>3) Turn on siblings, for that bucket or bucket type.  That way, Riak will still try to use causal context to decide the right value. But if it can't decide, it will store BOTH values, and give them back to you on the next read, so that your application can decide which is the correct one.<br></div><div><br><br></div><div><div><br><br><br><br></div></div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 8, 2015 at 1:56 AM, Vanessa Williams <span dir="ltr"><<a href="mailto:vanessa.williams@thoughtwire.ca" target="_blank">vanessa.williams@thoughtwire.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Dmitri, what would be the benefit of r=2, exactly? It isn't necessary to trigger read-repair, is it? If it's important I'd rather try it sooner than later...<div><br></div><div>Regards,</div><div>Vanessa</div><div><br></div><div><br></div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 7, 2015 at 4:02 PM, Dmitri Zagidulin <span dir="ltr"><<a href="mailto:dzagidulin@basho.com" target="_blank">dzagidulin@basho.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Glad you sorted it out!<br><br></div>(I do want to encourage you to bump your R setting to at least 2, though. Run some tests -- I think you'll find that the difference in speed will not be noticeable, but you do get a lot more data resilience with 2.)<br></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 7, 2015 at 6:24 PM, Vanessa Williams <span dir="ltr"><<a href="mailto:vanessa.williams@thoughtwire.ca" target="_blank">vanessa.williams@thoughtwire.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Dmitri, well...we solved our problem to our satisfaction but it turned out to be something unexpected.<div><br></div><div>The keys were two properties mentioned in a blog post on "configuring Riak’s oft-subtle behavioral characteristics": <a href="http://basho.com/posts/technical/riaks-config-behaviors-part-4/" target="_blank">http://basho.com/posts/technical/riaks-config-behaviors-part-4/</a></div><div><br></div><div>notfound_ok= false</div><div>basic_quorum=true</div><div><br></div><div>The 2nd one just makes things a little faster, but the first one is the one whose default value of true was killing us. </div><div><br></div><div>With r=1 and notfound_ok=true (default) the first node to respond, if it didn't find the requested key, the authoritative answer was "this key is not found". Not what we were expecting at all. </div><div><br></div><div>With the changed settings, it will wait for a quorum of responses and only if *no one* finds the key will "not found" be returned. Perfect. (Without this setting it would wait for all responses, not ideal.)</div><div><br></div><div>Now there is only one snag, which is that if the Riak node the client connects to goes down, there will be no communication and we have a problem. This is easily solvable with a load-balancer, though for complicated reasons we actually don't need to do that right now. It's just acceptable for us temporarily. Later, we'll get the load-balancer working and even that won't be a problem.</div><div><br></div><div>I *think* we're ok now. Thanks for your help!</div><div><br></div><div>Regards,</div><div>Vanessa</div><div><br></div><div><br></div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 7, 2015 at 9:33 AM, Dmitri Zagidulin <span dir="ltr"><<a href="mailto:dzagidulin@basho.com" target="_blank">dzagidulin@basho.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Yeah, definitely find out what the sysadmin's experience was, with the load balancer. It could have just been a wrong configuration or something.<br></div><div class="gmail_extra"><br></div><div class="gmail_extra">And yes, that's the documentation page I recommend - <a href="http://docs.basho.com/riak/latest/ops/advanced/configs/load-balancing-proxy/" target="_blank">http://docs.basho.com/riak/latest/ops/advanced/configs/load-balancing-proxy/</a><br></div><div class="gmail_extra">Just set up HAProxy, and point your Java clients to its IP.<br><br></div><div class="gmail_extra">The drawbacks to load-balancing on the java client side (yes, the cluster object) instead of a standalone load balancer like HAProxy, are the following:<br><br></div><div class="gmail_extra">1) Adding node means code changes (or at very least, config file changes) rolled out to all your clients. Which turns out to be a pretty serious hassle. Instead, HAProxy allows you to add or remove nodes without changing any java code or config files.<br><br></div><div class="gmail_extra">2) Performance. We've ran many tests to compare performance, and client-side load balancing results in significantly lower throughput than you'd have using haproxy (or nginx). (Specifically, you actually want to use the 'leastconn' load balancing algorithm with HAProxy, instead of round robin).<br><br></div><div class="gmail_extra">3) The health check on the client side (so that the java load balancer can tell when a remote node is down) is much less intelligent than a dedicated load balancer would provide. With something like HAProxy, you should be able to take down nodes with no ill effects for the client code.<br><br></div><div class="gmail_extra">Now, if you load balance on the client side and you take a node down, it's not supposed to stop working completely. (I'm not sure why it's failing for you, we can investigate, but it'll be easier to just use a load balancer). It should throw an error or two, but then start working again (on the retry).<span><font color="#888888"><br><br></font></span></div><span><font color="#888888"><div class="gmail_extra">Dmitri<br></div></font></span><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 7, 2015 at 2:45 PM, Vanessa Williams <span dir="ltr"><<a href="mailto:vanessa.williams@thoughtwire.ca" target="_blank">vanessa.williams@thoughtwire.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi Dmitri, thanks for the quick reply.<div><br></div><div>It was actually our sysadmin who tried the load balancer approach and had no success, late last evening. However I haven't discussed the gory details with him yet. The failure he saw was at the application level (i.e. failure to read a key), but I don't know a) how he set up the LB or b) what the Java exception was, if any. I'll find that out in an hour or two and report back.</div><div><br></div><div>I did find this article just now:</div><div><br></div><div><a href="http://docs.basho.com/riak/latest/ops/advanced/configs/load-balancing-proxy/" target="_blank">http://docs.basho.com/riak/latest/ops/advanced/configs/load-balancing-proxy/</a><br></div><div><br></div><div>So I suppose we'll give those suggestions a try this morning. </div><div><br></div><div>What is the drawback to having the client connect to all 4 nodes (the cluster client, I assume you mean?) My understanding from reading articles I've found is that one of the nodes going away causes that client to fail as well. Is that what you mean, or are there other drawbacks as well?</div><div><br></div><div>If there's anything else you can recommend, or links other than the one above you can point me to, it would be much appreciated. We expect both node failure and deliberate node removal for upgrade, repair, replacement, etc. </div><div><br></div><div>Regards,</div><div>Vanessa</div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 7, 2015 at 8:29 AM, Dmitri Zagidulin <span dir="ltr"><<a href="mailto:dzagidulin@basho.com" target="_blank">dzagidulin@basho.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div>Hi Vanessa,<br><br></div>Riak is definitely meant to run behind a load balancer. (Or, at the worst case, to be load-balanced on the client side. That is, all clients connect to all 4 nodes).<br><br></div>When you say "<span style="font-size:13px">we did try putting all 4 Riak nodes behind a load-balancer and pointing the clients at it, but it didn't help." -- what do you mean exactly, by "it didn't help"? What happened when you tried using the load balancer?<br><br><br></span></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div>On Wed, Oct 7, 2015 at 1:57 PM, Vanessa Williams <span dir="ltr"><<a href="mailto:vanessa.williams@thoughtwire.ca" target="_blank">vanessa.williams@thoughtwire.ca</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div><div dir="ltr">Hi all, we are still (for a while longer) using Riak 1.4 and the matching Java client. The client(s) connect to one node in the cluster (since that's all it can do in this client version). The cluster itself has 4 nodes (sorry, we can't use 5 in this scenario). There are 2 separate clients.<div><br></div><div>We've tried both n_val = 3 and n_val=4. We achieve consistency-by-writes by setting w=all. Therefore, we only require one successful read (r=1).<br><div><br></div><div>When all nodes are up, everything is fine. If one node fails, the clients can no longer read any keys at all. There's an exception like this:</div></div><div><br></div><div><span style="font-size:13px">com.basho.riak.client.</span><span style="font-size:13px">RiakRetryFailedException: java.net.ConnectException: Connection refused</span><br></div><div><span style="font-size:13px"><br></span></div><div><span style="font-size:13px">Now, it isn't possible that Riak can't operate when one node fails, so we're clearly missing something here.</span></div><div><span style="font-size:13px"><br></span></div><div><span style="font-size:13px">Note: we did try putting all 4 Riak nodes behind a load-balancer and pointing the clients at it, but it didn't help.</span></div><div><span style="font-size:13px"><br></span></div><div>Riak is a high-availability key-value store, so... why are we failing to achieve high-availability? Any suggestions greatly appreciated, and if more info is required I'll do my best to provide it. </div><div><br></div><div>Thanks in advance,</div><div>Vanessa</div><div><br></div><div>--</div><div>Vanessa Williams</div><div>ThoughtWire Corporation</div><div><a href="http://www.thoughtwire.com" target="_blank">http://www.thoughtwire.com</a></div><div><br></div></div>
<br></div></div>_______________________________________________<br>
riak-users mailing list<br>
<a href="mailto:riak-users@lists.basho.com" target="_blank">riak-users@lists.basho.com</a><br>
<a href="http://lists.basho.com/mailman/listinfo/riak-users_lists.basho.com" rel="noreferrer" target="_blank">http://lists.basho.com/mailman/listinfo/riak-users_lists.basho.com</a><br>
<br></blockquote></div><br></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div></div></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
riak-users mailing list<br>
<a href="mailto:riak-users@lists.basho.com" target="_blank">riak-users@lists.basho.com</a><br>
<a href="http://lists.basho.com/mailman/listinfo/riak-users_lists.basho.com" rel="noreferrer" target="_blank">http://lists.basho.com/mailman/listinfo/riak-users_lists.basho.com</a><br>
<br></blockquote></div><br></div></div></div></div>
</blockquote></div></div></div><br></div></div>
</blockquote></div><br></div>