You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by GitBox <gi...@apache.org> on 2019/01/15 01:37:16 UTC

[zookeeper] Diff for: [GitHub] enixon closed pull request #770: ZOOKEEPER-3244: Add option to snapshot based on log size

diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/SyncRequestProcessor.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/SyncRequestProcessor.java
index 57cca9c3c4..02d0dd61db 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/SyncRequestProcessor.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/SyncRequestProcessor.java
@@ -67,6 +67,17 @@
      */
     private static int snapCount = ZooKeeperServer.getSnapCount();
 
+    /**
+     * The total size of log entries before starting a snapshot
+     */
+    private static long snapSize = ZooKeeperServer.getSnapSize();
+
+    /**
+     * Random numbers used to vary snapshot timing
+     */
+    private int randRoll;
+    private long randSize;
+
     private final Request requestOfDeath = Request.requestOfDeath;
 
     public SyncRequestProcessor(ZooKeeperServer zks,
@@ -95,6 +106,18 @@ public static int getSnapCount() {
         return snapCount;
     }
 
+    private boolean shouldSnapshot() {
+        int logCount = zks.getZKDatabase().getTxnCount();
+        long logSize = zks.getZKDatabase().getTxnSize();
+        return (logCount > (snapCount / 2 + randRoll)) ||
+                (logSize > (snapSize / 2 + randSize));
+    }
+
+    private void resetSnapshotStats() {
+        randRoll = r.nextInt(snapCount/2);
+        randSize = Math.abs(r.nextLong() % (snapSize/2));
+    }
+
     @Override
     public void run() {
         try {
@@ -102,7 +125,7 @@ public void run() {
 
             // we do this in an attempt to ensure that not all of the servers
             // in the ensemble take a snapshot at the same time
-            int randRoll = r.nextInt(snapCount/2);
+            resetSnapshotStats();
             while (true) {
                 Request si = null;
                 if (toFlush.isEmpty()) {
@@ -120,9 +143,8 @@ public void run() {
                 if (si != null) {
                     // track the number of records written to the log
                     if (zks.getZKDatabase().append(si)) {
-                        logCount++;
-                        if (logCount > (snapCount / 2 + randRoll)) {
-                            randRoll = r.nextInt(snapCount/2);
+                        if (shouldSnapshot()) {
+                            resetSnapshotStats();
                             // roll the log
                             zks.getZKDatabase().rollLog();
                             // take a snapshot
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZKDatabase.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZKDatabase.java
index 753461a5e6..251859e170 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZKDatabase.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZKDatabase.java
@@ -28,6 +28,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
@@ -88,6 +89,11 @@
     protected ReentrantReadWriteLock logLock = new ReentrantReadWriteLock();
     volatile private boolean initialized = false;
 
+    /**
+     * Number of txn since last snapshot;
+     */
+    private AtomicInteger txnCount = new AtomicInteger(0);
+
     /**
      * the filetxnsnaplog that this zk database
      * maps to. There is a one to one relationship
@@ -581,6 +587,7 @@ public void serializeSnapshot(OutputArchive oa) throws IOException,
      * @return true if the append was succesfull and false if not
      */
     public boolean append(Request si) throws IOException {
+        txnCount.incrementAndGet();
         return this.snapLog.append(si);
     }
 
@@ -589,6 +596,7 @@ public boolean append(Request si) throws IOException {
      */
     public void rollLog() throws IOException {
         this.snapLog.rollLog();
+        resetTxnCount();
     }
 
     /**
@@ -661,4 +669,26 @@ public boolean removeWatch(String path, WatcherType type, Watcher watcher) {
     public DataTree createDataTree() {
         return new DataTree();
     }
+
+    /**
+     * Reset the number of txn since last rollLog
+     */
+    public void resetTxnCount() {
+        txnCount.set(0);
+        snapLog.setTotalLogSize(0);
+    }
+
+    /**
+     * Get the number of txn since last snapshot
+     */
+    public int getTxnCount() {
+        return txnCount.get();
+    }
+
+    /**
+     * Get the size of txn since last snapshot
+     */
+    public long getTxnSize() {
+        return snapLog.getTotalLogSize();
+    }
 }
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
index 20ab023ec5..1355e0f6b0 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperServer.java
@@ -873,6 +873,10 @@ public int getGlobalOutstandingLimit() {
         return limit;
     }
 
+    public static long getSnapSize() {
+        return Long.getLong("zookeeper.snapSize", 4294967296L); // 4GB by default
+    }
+
     public void setServerCnxnFactory(ServerCnxnFactory factory) {
         serverCnxnFactory = factory;
     }
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileTxnLog.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileTxnLog.java
index c739152799..195ec56fed 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileTxnLog.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileTxnLog.java
@@ -157,6 +157,12 @@
 
     private volatile long syncElapsedMS = -1L;
 
+    /**
+     * A running total of all complete log files
+     * This does not include the current file being written to
+     */
+    private long prevLogsRunningTotal;
+
     /**
      * constructor for FileTxnLog. Take the directory
      * where the txnlogs are stored
@@ -202,6 +208,14 @@ public synchronized long getCurrentLogSize() {
         return 0;
     }
 
+    public synchronized void setTotalLogSize(long size) {
+        prevLogsRunningTotal = size;
+    }
+
+    public long getTotalLogSize() {
+        return prevLogsRunningTotal + getCurrentLogSize();
+    }
+
     /**
      * creates a checksum algorithm to be used
      * @return the checksum used for this txnlog
@@ -217,8 +231,11 @@ protected Checksum makeChecksumAlgorithm(){
     public synchronized void rollLog() throws IOException {
         if (logStream != null) {
             this.logStream.flush();
+            prevLogsRunningTotal += getCurrentLogSize();
             this.logStream = null;
             oa = null;
+
+            // Roll over the current log file into the running total
         }
     }
 
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
index e6d299831c..7409af8503 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
@@ -491,7 +491,7 @@ public File findMostRecentSnapshot() throws IOException {
     /**
      * append the request to the transaction logs
      * @param si the request to be appended
-     * returns true iff something appended, otw false
+     * @return true iff something appended, otw false
      * @throws IOException
      */
     public boolean append(Request si) throws IOException {
@@ -554,4 +554,12 @@ public SnapDirContentCheckException(String msg) {
             super(msg);
         }
     }
+
+    public void setTotalLogSize(long size) {
+        txnLog.setTotalLogSize(size);
+    }
+
+    public long getTotalLogSize() {
+        return txnLog.getTotalLogSize();
+    }
 }
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLog.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLog.java
index 9781f45307..184b59df1f 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLog.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLog.java
@@ -46,7 +46,7 @@
      * Append a request to the transaction log
      * @param hdr the transaction header
      * @param r the transaction itself
-     * returns true iff something appended, otw false 
+     * @return true iff something appended, otw false
      * @throws IOException
      */
     boolean append(TxnHeader hdr, Record r) throws IOException;
@@ -100,6 +100,17 @@
      * close the transactions logs
      */
     void close() throws IOException;
+
+    /**
+     * Sets the total size of all log files
+     */
+    void setTotalLogSize(long size);
+
+    /**
+     * Gets the total size of all log files
+     */
+    long getTotalLogSize();
+
     /**
      * an iterating interface for reading 
      * transaction logs. 


With regards,
Apache Git Services