Skip to content

Commit 2b56ca8

Browse files
Merge pull request #88 from Netflix/feature/duet_write_only_and_primary
Feature/duet write only and primary
2 parents 8f56c78 + 18a5271 commit 2b56ca8

File tree

4 files changed

+147
-64
lines changed

4 files changed

+147
-64
lines changed

evcache-core/src/main/java/com/netflix/evcache/pool/EVCacheClientPool.java

+135-64
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ public class EVCacheClientPool implements Runnable, EVCacheClientPoolMBean {
7070

7171
// name of the duet EVCache application, if applicable.
7272
private final Property<String> duet;
73+
// indicates if duet needs to be primary
74+
private final Property<Boolean> duetPrimary;
7375
// evCacheClientPool of the duet EVCache application, if applicable. Supports daisy chaining.
7476
private EVCacheClientPool duetClientPool;
7577

@@ -174,6 +176,8 @@ public Property<Boolean> get(Object _serverGroup) {
174176
setupDuet();
175177
});
176178

179+
this.duetPrimary = config.getPropertyRepository().get(appName + ".duet.primary", Boolean.class).orElseGet("evcache.duet.primary").orElse(false);
180+
177181
tagList = new ArrayList<Tag>(2);
178182
EVCacheMetricsFactory.getInstance().addAppNameTags(tagList, _appName);
179183

@@ -251,11 +255,20 @@ private EVCacheClient getEVCacheClientForReadInternal() {
251255
public EVCacheClient getEVCacheClientForRead() {
252256
EVCacheClient evCacheClient = getEVCacheClientForReadInternal();
253257

254-
if (evCacheClient != null) {
258+
// most common production scenario
259+
if (null == duetClientPool) {
255260
return evCacheClient;
256261
}
257262

258-
return duetClientPool != null ? duetClientPool.getEVCacheClientForRead() : null;
263+
// return duet if current client is not available or if duet is primary
264+
if (null == evCacheClient || duetPrimary.get()) {
265+
EVCacheClient duetClient = duetClientPool.getEVCacheClientForRead();
266+
267+
// if duetClient is not present, fallback to evCacheClient
268+
return null == duetClient ? evCacheClient : duetClient;
269+
}
270+
271+
return evCacheClient;
259272
}
260273

261274
private List<EVCacheClient> getAllEVCacheClientForReadInternal() {
@@ -288,17 +301,26 @@ private List<EVCacheClient> getAllEVCacheClientForReadInternal() {
288301

289302
public List<EVCacheClient> getAllEVCacheClientForRead() {
290303
List<EVCacheClient> evCacheClients = getAllEVCacheClientForReadInternal();
291-
if (duetClientPool != null) {
292-
List<EVCacheClient> duetEVCacheClients = duetClientPool.getAllEVCacheClientForRead();
293-
if (null == evCacheClients)
294-
return duetEVCacheClients;
295304

296-
if (null == duetEVCacheClients)
297-
return evCacheClients;
305+
// most common production scenario
306+
if (null == duetClientPool) {
307+
return evCacheClients;
308+
}
298309

299-
evCacheClients.addAll(duetClientPool.getAllEVCacheClientForRead());
310+
List<EVCacheClient> duetEVCacheClients = duetClientPool.getAllEVCacheClientForRead();
311+
if (null == evCacheClients)
312+
return duetEVCacheClients;
313+
314+
if (null == duetEVCacheClients)
315+
return evCacheClients;
316+
317+
if (duetPrimary.get()) {
318+
duetEVCacheClients.addAll(evCacheClients);
319+
return duetEVCacheClients;
320+
} else {
321+
evCacheClients.addAll(duetEVCacheClients);
322+
return evCacheClients;
300323
}
301-
return evCacheClients;
302324
}
303325

304326
private EVCacheClient selectClient(List<EVCacheClient> clients) {
@@ -340,11 +362,20 @@ private EVCacheClient getEVCacheClientForReadExcludeInternal(ServerGroup rsetUse
340362
public EVCacheClient getEVCacheClientForReadExclude(ServerGroup rsetUsed) {
341363
EVCacheClient evCacheClient = getEVCacheClientForReadExcludeInternal(rsetUsed);
342364

343-
if (evCacheClient != null) {
365+
// most common production scenario
366+
if (null == duetClientPool) {
344367
return evCacheClient;
345368
}
346369

347-
return duetClientPool != null ? duetClientPool.getEVCacheClientForReadExclude(rsetUsed) : null;
370+
// return duet if current client is not available or if duet is primary
371+
if (null == evCacheClient || duetPrimary.get()) {
372+
EVCacheClient duetClient = duetClientPool.getEVCacheClientForReadExclude(rsetUsed);
373+
374+
// if duetClient is not present, fallback to evCacheClient
375+
return null == duetClient ? evCacheClient : duetClient;
376+
}
377+
378+
return evCacheClient;
348379
}
349380

350381
private EVCacheClient getEVCacheClientInternal(ServerGroup serverGroup) {
@@ -374,11 +405,20 @@ private EVCacheClient getEVCacheClientInternal(ServerGroup serverGroup) {
374405
public EVCacheClient getEVCacheClient(ServerGroup serverGroup) {
375406
EVCacheClient evCacheClient = getEVCacheClientInternal(serverGroup);
376407

377-
if (evCacheClient != null) {
408+
// most common production scenario
409+
if (null == duetClientPool) {
378410
return evCacheClient;
379411
}
380412

381-
return duetClientPool != null ? duetClientPool.getEVCacheClient(serverGroup) : null;
413+
// return duet if current client is not available or if duet is primary
414+
if (null == evCacheClient || duetPrimary.get()) {
415+
EVCacheClient duetClient = duetClientPool.getEVCacheClient(serverGroup);
416+
417+
// if duetClient is not present, fallback to evCacheClient
418+
return null == duetClient ? evCacheClient : duetClient;
419+
}
420+
421+
return evCacheClient;
382422
}
383423

384424
private List<EVCacheClient> getEVCacheClientsForReadExcludingInternal(ServerGroup serverGroupToExclude) {
@@ -431,17 +471,26 @@ private List<EVCacheClient> getEVCacheClientsForReadExcludingInternal(ServerGrou
431471

432472
public List<EVCacheClient> getEVCacheClientsForReadExcluding(ServerGroup serverGroupToExclude) {
433473
List<EVCacheClient> evCacheClients = getEVCacheClientsForReadExcludingInternal(serverGroupToExclude);
434-
if (duetClientPool != null) {
435-
List<EVCacheClient> duetEVCacheClients = duetClientPool.getEVCacheClientsForReadExcluding(serverGroupToExclude);
436-
if (null == evCacheClients)
437-
return duetEVCacheClients;
438474

439-
if (null == duetEVCacheClients)
440-
return evCacheClients;
475+
// most common production scenario
476+
if (null == duetClientPool) {
477+
return evCacheClients;
478+
}
479+
480+
List<EVCacheClient> duetEVCacheClients = duetClientPool.getEVCacheClientsForReadExcluding(serverGroupToExclude);
481+
if (null == evCacheClients)
482+
return duetEVCacheClients;
483+
484+
if (null == duetEVCacheClients)
485+
return evCacheClients;
441486

487+
if (duetPrimary.get()) {
488+
duetEVCacheClients.addAll(evCacheClients);
489+
return duetEVCacheClients;
490+
} else {
442491
evCacheClients.addAll(duetEVCacheClients);
492+
return evCacheClients;
443493
}
444-
return evCacheClients;
445494
}
446495

447496
public boolean isInWriteOnly(ServerGroup serverGroup) {
@@ -503,27 +552,39 @@ private EVCacheClient[] getWriteOnlyEVCacheClientsInternal() {
503552
}
504553

505554
public EVCacheClient[] getWriteOnlyEVCacheClients() {
506-
EVCacheClient[] evCacheClients = null;
507-
try {
508-
evCacheClients = getWriteOnlyEVCacheClientsInternal();
509-
if (duetClientPool != null) {
510-
EVCacheClient[] duetEVCacheClients = duetClientPool.getWriteOnlyEVCacheClients();
511-
512-
// common scenario for duet usage
513-
if (null == evCacheClients || evCacheClients.length == 0) {
514-
return duetEVCacheClients;
515-
}
516-
517-
if (null != duetEVCacheClients && duetEVCacheClients.length > 0) {
518-
EVCacheClient[] allEVCacheClients = Arrays.copyOf(evCacheClients, evCacheClients.length + duetEVCacheClients.length);
519-
System.arraycopy(duetEVCacheClients, 0, allEVCacheClients, evCacheClients.length, duetEVCacheClients.length);
520-
return allEVCacheClients;
521-
}
522-
}
523-
return evCacheClients;
524-
} finally {
525-
if(evCacheClients == null) return new EVCacheClient[0];
526-
}
555+
EVCacheClient[] evCacheClients = getWriteOnlyEVCacheClientsInternal();
556+
557+
// most common production scenario
558+
if (null == duetClientPool) {
559+
return evCacheClients;
560+
}
561+
562+
EVCacheClient[] duetEVCacheClients = duetClientPool.getWriteOnlyEVCacheClients();
563+
if (null == evCacheClients || evCacheClients.length == 0) {
564+
return duetEVCacheClients;
565+
}
566+
567+
if (null == duetEVCacheClients || duetEVCacheClients.length == 0) {
568+
return evCacheClients;
569+
}
570+
571+
if (duetPrimary.get()) {
572+
// return write-only of duet app and all writers of original app to which duet is attached
573+
// get all writers of original app
574+
evCacheClients = getEVCacheClientForWriteInternal();
575+
576+
EVCacheClient[] allEVCacheClients = Arrays.copyOf(duetEVCacheClients, duetEVCacheClients.length + evCacheClients.length);
577+
System.arraycopy(evCacheClients, 0, allEVCacheClients, duetEVCacheClients.length, evCacheClients.length);
578+
return allEVCacheClients;
579+
} else {
580+
// return write-only of original app and all writers of duet app
581+
// get all writers of duet app
582+
duetEVCacheClients = duetClientPool.getEVCacheClientForWrite();
583+
584+
EVCacheClient[] allEVCacheClients = Arrays.copyOf(evCacheClients, evCacheClients.length + duetEVCacheClients.length);
585+
System.arraycopy(duetEVCacheClients, 0, allEVCacheClients, evCacheClients.length, duetEVCacheClients.length);
586+
return allEVCacheClients;
587+
}
527588
}
528589

529590
EVCacheClient[] getAllWriteClients() {
@@ -594,27 +655,31 @@ private EVCacheClient[] getEVCacheClientForWriteInternal() {
594655
}
595656

596657
public EVCacheClient[] getEVCacheClientForWrite() {
597-
EVCacheClient[] evCacheClients = null;
598-
try {
599-
evCacheClients = getEVCacheClientForWriteInternal();
600-
if (duetClientPool != null) {
601-
EVCacheClient[] duetEVCacheClients = duetClientPool.getEVCacheClientForWrite();
602-
603-
// common scenario for duet usage
604-
if (null == evCacheClients || evCacheClients.length == 0) {
605-
return duetEVCacheClients;
606-
}
607-
608-
if (null != duetEVCacheClients && duetEVCacheClients.length > 0) {
609-
EVCacheClient[] allEVCacheClients = Arrays.copyOf(evCacheClients, evCacheClients.length + duetEVCacheClients.length);
610-
System.arraycopy(duetEVCacheClients, 0, allEVCacheClients, evCacheClients.length, duetEVCacheClients.length);
611-
return allEVCacheClients;
612-
}
613-
}
614-
return evCacheClients;
615-
} finally {
616-
if(evCacheClients == null) return new EVCacheClient[0];
617-
}
658+
EVCacheClient[] evCacheClients = getEVCacheClientForWriteInternal();
659+
660+
// most common production scenario
661+
if (null == duetClientPool) {
662+
return evCacheClients;
663+
}
664+
665+
EVCacheClient[] duetEVCacheClients = duetClientPool.getEVCacheClientForWrite();
666+
if (null == evCacheClients || evCacheClients.length == 0) {
667+
return duetEVCacheClients;
668+
}
669+
670+
if (null == duetEVCacheClients || duetEVCacheClients.length == 0) {
671+
return evCacheClients;
672+
}
673+
674+
if (duetPrimary.get()) {
675+
EVCacheClient[] allEVCacheClients = Arrays.copyOf(duetEVCacheClients, duetEVCacheClients.length + evCacheClients.length);
676+
System.arraycopy(evCacheClients, 0, allEVCacheClients, duetEVCacheClients.length, evCacheClients.length);
677+
return allEVCacheClients;
678+
} else {
679+
EVCacheClient[] allEVCacheClients = Arrays.copyOf(evCacheClients, evCacheClients.length + duetEVCacheClients.length);
680+
System.arraycopy(duetEVCacheClients, 0, allEVCacheClients, evCacheClients.length, duetEVCacheClients.length);
681+
return allEVCacheClients;
682+
}
618683
}
619684

620685
private void refresh() throws IOException {
@@ -1432,7 +1497,7 @@ public String getFallbackServerGroup() {
14321497
}
14331498

14341499
public boolean supportsFallback() {
1435-
return memcachedFallbackReadInstances.getSize() > 1 || (duetClientPool != null && duetClientPool.supportsFallback());
1500+
return memcachedFallbackReadInstances.getSize() > 1 || (duetClientPool != null && duetPrimary.get() && duetClientPool.supportsFallback());
14361501
}
14371502

14381503
public boolean isLogEventEnabled() {
@@ -1486,6 +1551,9 @@ public Property<Integer> getOpQueueMaxBlockTime() {
14861551
}
14871552

14881553
public Property<Integer> getOperationTimeout() {
1554+
if (duetClientPool !=null && duetPrimary.get()) {
1555+
return duetClientPool.getOperationTimeout();
1556+
}
14891557
return _operationTimeout;
14901558
}
14911559

@@ -1528,6 +1596,9 @@ public Map<ServerGroup, Property<Boolean>> getWriteOnlyFastPropertyMap() {
15281596
}
15291597

15301598
public Property<Integer> getReadTimeout() {
1599+
if (duetClientPool != null && duetPrimary.get()) {
1600+
return duetClientPool.getReadTimeout();
1601+
}
15311602
return _readTimeout;
15321603
}
15331604

evcache-core/src/main/java/net/spy/memcached/EVCacheNode.java

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.List;
44

55
import com.netflix.evcache.EVCache;
6+
import com.netflix.evcache.pool.EVCacheClient;
67
import com.netflix.evcache.pool.ServerGroup;
78
import com.netflix.spectator.api.Tag;
89

@@ -58,5 +59,7 @@ public interface EVCacheNode extends MemcachedNode {
5859
int getReconnectCount();
5960

6061
boolean isActive();
62+
63+
EVCacheClient getEVCacheClient();
6164

6265
}

evcache-core/src/main/java/net/spy/memcached/protocol/ascii/EVCacheAsciiNodeImpl.java

+4
Original file line numberDiff line numberDiff line change
@@ -230,4 +230,8 @@ public String getConnectTime() {
230230
}
231231

232232

233+
@Override
234+
public EVCacheClient getEVCacheClient() {
235+
return client;
236+
}
233237
}

evcache-core/src/main/java/net/spy/memcached/protocol/binary/EVCacheNodeImpl.java

+5
Original file line numberDiff line numberDiff line change
@@ -325,4 +325,9 @@ public String getSocketChannelRemoteAddress() {
325325
public String getConnectTime() {
326326
return ISODateTimeFormat.dateTime().print(stTime);
327327
}
328+
329+
@Override
330+
public EVCacheClient getEVCacheClient() {
331+
return client;
332+
}
328333
}

0 commit comments

Comments
 (0)