Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLEANUP: Refactored MemcachedConnection.switchoverMemcachedReplGroup() method. #852

Merged
merged 1 commit into from
Dec 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 34 additions & 27 deletions src/main/java/net/spy/memcached/MemcachedConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ private void updateReplConnections(List<InetSocketAddress> addrs) throws IOExcep

if (oldGroup.isDelayedSwitchover()) {
delayedSwitchoverGroups.remove(oldGroup);
switchoverMemcachedReplGroup(oldGroup.getMasterNode(), true);
switchoverMemcachedReplGroup(oldGroup, true);
}

MemcachedNode oldMasterNode = oldGroup.getMasterNode();
Expand Down Expand Up @@ -587,26 +587,29 @@ private Set<ArcusReplNodeAddress> getSlaveAddrsFromGroupAddrs(
/* ENABLE_REPLICATION end */

/* ENABLE_REPLICATION if */
private void switchoverMemcachedReplGroup(MemcachedNode node, boolean cancelNonIdempotent) {
MemcachedReplicaGroup group = node.getReplicaGroup();
private void switchoverMemcachedReplGroup(MemcachedReplicaGroup group,
boolean cancelNonIdempotent) {

if (group.getMasterCandidate() == null) {
getLogger().warn("Delay switchover because invalid group state : " + group);
return;
}

MemcachedNode oldMaster = group.getMasterNode();

/* must keep the following execution order when switchover
* - first moveOperations
* - second, queueReconnect
*
* because moves all operations
*/
if (group.getMasterNode() != null && group.getMasterCandidate() != null) {
if (((ArcusReplNodeAddress) node.getSocketAddress()).isMaster()) {
((ArcusReplKetamaNodeLocator) locator).switchoverReplGroup(group);
}
node.moveOperations(group.getMasterNode(), cancelNonIdempotent);
addedQueue.offer(group.getMasterNode());
queueReconnect(node, ReconnDelay.IMMEDIATE,
"Discarded all pending reading state operation to move operations.");
} else {
getLogger().warn("Delay switchover because invalid group state : " + group);
}
((ArcusReplKetamaNodeLocator) locator).switchoverReplGroup(group);
Copy link
Collaborator

@oliviarla oliviarla Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기존처럼 group.getMasterNode() != null && group.getMasterCandidate() != null 조건이 만족할 때에만 switchover + move operation + old master reconnect 해야 하지 않나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/jam2in/arcus-works/issues/637#issuecomment-2521925920

해당 조건에 맞지 않는데도 이 메소드를 호출하는 경우가 로직적으로는 없어서 조건문을 제거했습니다.
그래도 조건문을 유지하도록 할까요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private 메서드라서 반드시 유지할 필요는 없어보이지만, 단순 검증 용도로 둔다면 나중에 리팩토링 시에 이 부분을 인지하여 버그 발생 가능성이 줄어들 것 같습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아래와 같이 조건을 넣어 두시죠.

  • oldMaster는 분명히 존재하는 상황에서 switchover 대상이 될 수 있음.
  • masterCandidate가 null인 경우는 없을 것으로 보이지만,
    masterCandidate가 null인 경우에 locator.switchoverReplGroup(group) 수행은
    오동작(invalid group으로 변환)하게 되므로,
    masterCandidate != null 조건을 넣어두는 것이 괜찮을 것 같습니다.
if (group.getMasterCandidate() != null) {
  ((ArcusReplKetamaNodeLocator) locator).switchoverReplGroup(group);
   . . .
   queueReconnect(oldMaster, ReconnDelay.IMMEDIATE,
        "Discarded all pending reading state operation to move operations.");
} else {
  getLogger().warn("Delay switchover because invalid group state : " + group);
}

MemcachedNode newMaster = group.getMasterNode();

oldMaster.moveOperations(newMaster, cancelNonIdempotent);
addedQueue.offer(newMaster);
queueReconnect(oldMaster, ReconnDelay.IMMEDIATE,
"Discarded all pending reading state operation to move operations.");
}
/* ENABLE_REPLICATION end */

Expand Down Expand Up @@ -1015,8 +1018,9 @@ private void handleReads(MemcachedNode qa)
/* ENABLE_REPLICATION if */
if (currentOp != null && currentOp.getState() == OperationState.MOVING) {
((Buffer) rbuf).clear();
delayedSwitchoverGroups.remove(qa.getReplicaGroup());
switchoverMemcachedReplGroup(qa, false);
MemcachedReplicaGroup group = qa.getReplicaGroup();
delayedSwitchoverGroups.remove(group);
switchoverMemcachedReplGroup(group, false);
break;
}
/* ENABLE_REPLICATION end */
Expand All @@ -1031,10 +1035,10 @@ private void handleReads(MemcachedNode qa)
/* ENABLE_REPLICATION if */
if (arcusReplEnabled) {
if (currentOp == null) { // readQ is empty
if (qa.getReplicaGroup().isDelayedSwitchover() &&
qa.getReplicaGroup().masterNode == qa) {
delayedSwitchoverGroups.remove(qa.getReplicaGroup());
switchoverMemcachedReplGroup(qa, false);
MemcachedReplicaGroup group = qa.getReplicaGroup();
if (group.isDelayedSwitchover() && group.getMasterNode() == qa) {
delayedSwitchoverGroups.remove(group);
switchoverMemcachedReplGroup(group, false);
}
}
}
Expand Down Expand Up @@ -1179,10 +1183,10 @@ private void queueReconnect(MemcachedNode qa, ReconnDelay type, String cause) {

/* ENABLE_REPLICATION if */
if (arcusReplEnabled) {
if (qa.getReplicaGroup().isDelayedSwitchover() &&
qa.getReplicaGroup().getMasterNode() == qa) {
delayedSwitchoverGroups.remove(qa.getReplicaGroup());
switchoverMemcachedReplGroup(qa, true);
MemcachedReplicaGroup group = qa.getReplicaGroup();
if (group.isDelayedSwitchover() && group.getMasterNode() == qa) {
delayedSwitchoverGroups.remove(group);
switchoverMemcachedReplGroup(group, true);
return;
}
}
Expand Down Expand Up @@ -1800,12 +1804,15 @@ public void switchover() {
Iterator<Entry<Long, MemcachedReplicaGroup>> iterator = groups.entrySet().iterator();
while (iterator.hasNext()) {
Entry<Long, MemcachedReplicaGroup> entry = iterator.next();
if (now < entry.getKey()) {
long switchoverTime = entry.getKey();
MemcachedReplicaGroup group = entry.getValue();

if (now < switchoverTime) {
return;
} else {
iterator.remove();
entry.getValue().setDelayedSwitchover(false);
switchoverMemcachedReplGroup(entry.getValue().getMasterNode(), true);
group.setDelayedSwitchover(false);
switchoverMemcachedReplGroup(group, true);
}
}
}
Expand Down