You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by nn...@apache.org on 2021/03/19 02:27:48 UTC

[geode] branch feature/redis-performance-testing updated: GEODE-9019: Serialization improvements in geode-redis (#6115)

This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/redis-performance-testing
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/feature/redis-performance-testing by this push:
     new b0c7dde  GEODE-9019: Serialization improvements in geode-redis (#6115)
b0c7dde is described below

commit b0c7ddef3ac06699feec143f5527b9a9af38eb01
Author: Nabarun Nag <na...@users.noreply.github.com>
AuthorDate: Thu Mar 18 19:26:34 2021 -0700

    GEODE-9019: Serialization improvements in geode-redis (#6115)
    
    
    GEODE-9019: Serialization improvements in geode-redis (#6115)
    
       * DataSerializable classes were converted in DataSerializableFixedID
       * serialVersionID were added to the unavoidable Serializable classes
    
    GEODE-9019: Fixed synchronization blocks missed in previous commit  (#6123)
    
    * Added tests to validate synchronized modifiers.
    * Enum serialization fixed, comments updated
    * Fixed the pom error - geode-membership in geode-redis
    
    (cherry picked from commit 7aae7b8158a0c8aecc15468a81a421bd6ffdc05e)
    (cherry picked from commit 0b9c6b125d093d1e007527cf0e4d6ac2e419f6d1)
---
 .../codeAnalysis/sanctionedDataSerializables.txt   | 20 ++++++----
 .../geode/redis/internal/GeodeRedisService.java    | 20 ++++++++++
 .../redis/internal/data/AbstractRedisData.java     | 11 ++++--
 .../redis/internal/data/ByteArrayWrapper.java      |  5 +--
 .../geode/redis/internal/data/NullRedisData.java   | 22 ++++++++---
 .../geode/redis/internal/data/RedisData.java       |  4 +-
 .../geode/redis/internal/data/RedisHash.java       | 38 ++++++++++++------
 .../apache/geode/redis/internal/data/RedisKey.java |  2 +-
 .../apache/geode/redis/internal/data/RedisSet.java | 35 ++++++++++++-----
 .../geode/redis/internal/data/RedisString.java     | 30 ++++++++++-----
 .../redis/internal/executor/CommandFunction.java   |  1 +
 .../executor/SingleResultRedisFunction.java        |  1 +
 .../internal/executor/key/RenameFunction.java      |  1 +
 .../redis/internal/executor/string/SetOptions.java | 45 +++++++++++++++++++---
 .../redis/internal/gfsh/RedisCommandFunction.java  |  2 +
 .../sanctioned-geode-redis-serializables.txt       |  9 ++---
 .../geode/redis/internal/data/RedisHashTest.java   | 13 +++++++
 .../geode/redis/internal/data/RedisSetTest.java    | 14 +++++++
 .../geode/redis/internal/data/RedisStringTest.java | 16 +++++++-
 geode-redis/src/test/resources/expected-pom.xml    | 22 +++++++++++
 .../serialization/DataSerializableFixedID.java     |  6 ++-
 21 files changed, 252 insertions(+), 65 deletions(-)

diff --git a/geode-redis/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-redis/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
index 68fb673..6e96a2c 100644
--- a/geode-redis/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
+++ b/geode-redis/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
@@ -1,6 +1,6 @@
 org/apache/geode/redis/internal/data/AbstractRedisData,2
-fromData,12
-toData,12
+fromData,11
+toData,11
 
 org/apache/geode/redis/internal/data/ByteArrayWrapper,2
 fromData,9
@@ -11,14 +11,18 @@ fromData,8
 toData,8
 
 org/apache/geode/redis/internal/data/RedisHash,2
-toData,14
-fromData,14
+toData,15
+fromData,15
 
 org/apache/geode/redis/internal/data/RedisSet,2
-toData,14
-fromData,14
+toData,15
+fromData,15
 
 org/apache/geode/redis/internal/data/RedisString,2
-fromData,29
-toData,25
+toData,26
+fromData,30
+
+org/apache/geode/redis/internal/executor/string/SetOptions,2
+fromData,34
+toData,29
 
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/GeodeRedisService.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/GeodeRedisService.java
index 4c91c26..928a00e 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/GeodeRedisService.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/GeodeRedisService.java
@@ -28,7 +28,12 @@ import org.apache.geode.internal.serialization.DataSerializableFixedID;
 import org.apache.geode.logging.internal.log4j.api.LogService;
 import org.apache.geode.management.internal.beans.CacheServiceMBeanBase;
 import org.apache.geode.redis.internal.data.ByteArrayWrapper;
+import org.apache.geode.redis.internal.data.NullRedisData;
+import org.apache.geode.redis.internal.data.RedisHash;
 import org.apache.geode.redis.internal.data.RedisKey;
+import org.apache.geode.redis.internal.data.RedisSet;
+import org.apache.geode.redis.internal.data.RedisString;
+import org.apache.geode.redis.internal.executor.string.SetOptions;
 
 public class GeodeRedisService implements CacheService, ResourceEventsListener {
   private static final Logger logger = LogService.getLogger();
@@ -55,6 +60,21 @@ public class GeodeRedisService implements CacheService, ResourceEventsListener {
     InternalDataSerializer.getDSFIDSerializer().registerDSFID(
         DataSerializableFixedID.REDIS_BYTE_ARRAY_WRAPPER_KEY,
         RedisKey.class);
+    InternalDataSerializer.getDSFIDSerializer().registerDSFID(
+        DataSerializableFixedID.REDIS_SET_ID,
+        RedisSet.class);
+    InternalDataSerializer.getDSFIDSerializer().registerDSFID(
+        DataSerializableFixedID.REDIS_STRING_ID,
+        RedisString.class);
+    InternalDataSerializer.getDSFIDSerializer().registerDSFID(
+        DataSerializableFixedID.REDIS_HASH_ID,
+        RedisHash.class);
+    InternalDataSerializer.getDSFIDSerializer().registerDSFID(
+        DataSerializableFixedID.REDIS_NULL_DATA_ID,
+        NullRedisData.class);
+    InternalDataSerializer.getDSFIDSerializer().registerDSFID(
+        DataSerializableFixedID.REDIS_SET_OPTIONS_ID,
+        SetOptions.class);
   }
 
   @Override
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/AbstractRedisData.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/AbstractRedisData.java
index 46b41cb..2350101 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/AbstractRedisData.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/AbstractRedisData.java
@@ -27,6 +27,8 @@ import org.apache.geode.InvalidDeltaException;
 import org.apache.geode.cache.EntryNotFoundException;
 import org.apache.geode.cache.Region;
 import org.apache.geode.internal.cache.BucketRegion;
+import org.apache.geode.internal.serialization.DeserializationContext;
+import org.apache.geode.internal.serialization.SerializationContext;
 import org.apache.geode.redis.internal.delta.AddsDeltaInfo;
 import org.apache.geode.redis.internal.delta.AppendDeltaInfo;
 import org.apache.geode.redis.internal.delta.DeltaInfo;
@@ -155,13 +157,14 @@ public abstract class AbstractRedisData implements RedisData {
   }
 
   @Override
-  public void toData(DataOutput out) throws IOException {
-    DataSerializer.writeLong(expirationTimestamp, out);
+  public void toData(DataOutput out, SerializationContext context) throws IOException {
+    out.writeLong(expirationTimestamp);
   }
 
   @Override
-  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
-    expirationTimestamp = (DataSerializer.readLong(in));
+  public void fromData(DataInput in, DeserializationContext context)
+      throws IOException, ClassNotFoundException {
+    expirationTimestamp = in.readLong();
   }
 
   private void setDelta(DeltaInfo deltaInfo) {
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/ByteArrayWrapper.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/ByteArrayWrapper.java
index 2b2cb58..9db10ff 100755
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/ByteArrayWrapper.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/ByteArrayWrapper.java
@@ -19,7 +19,6 @@ package org.apache.geode.redis.internal.data;
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
-import java.io.Serializable;
 import java.util.Arrays;
 
 import org.apache.geode.DataSerializer;
@@ -35,7 +34,7 @@ import org.apache.geode.redis.internal.netty.Coder;
  * able to be used in querying. Class is also marked as Serializable for test support.
  */
 public class ByteArrayWrapper
-    implements DataSerializableFixedID, Serializable, Comparable<ByteArrayWrapper> {
+    implements DataSerializableFixedID, Comparable<ByteArrayWrapper> {
   /**
    * The data portion of ValueWrapper
    */
@@ -174,7 +173,7 @@ public class ByteArrayWrapper
 
   @Override
   public void fromData(DataInput in, DeserializationContext context)
-      throws IOException, ClassNotFoundException {
+      throws IOException {
     value = DataSerializer.readByteArray(in);
   }
 
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisData.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisData.java
index a5d916e..b31e912 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisData.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisData.java
@@ -18,10 +18,12 @@ package org.apache.geode.redis.internal.data;
 
 import java.io.DataInput;
 import java.io.DataOutput;
-import java.io.IOException;
 
 import org.apache.geode.InvalidDeltaException;
 import org.apache.geode.cache.Region;
+import org.apache.geode.internal.serialization.DeserializationContext;
+import org.apache.geode.internal.serialization.KnownVersion;
+import org.apache.geode.internal.serialization.SerializationContext;
 
 /**
  * Implements behaviour for when no instance of RedisData exists.
@@ -87,27 +89,37 @@ public class NullRedisData implements RedisData {
   }
 
   @Override
-  public void toData(DataOutput out) throws IOException {
+  public int getDSFID() {
+    return REDIS_NULL_DATA_ID;
+  }
+
+  @Override
+  public void toData(DataOutput out, SerializationContext context) {
     throw new UnsupportedOperationException();
   }
 
   @Override
-  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+  public void fromData(DataInput in, DeserializationContext context) {
     throw new UnsupportedOperationException();
   }
 
   @Override
+  public KnownVersion[] getSerializationVersions() {
+    return null;
+  }
+
+  @Override
   public boolean hasDelta() {
     return false;
   }
 
   @Override
-  public void toDelta(DataOutput out) throws IOException {
+  public void toDelta(DataOutput out) {
     throw new UnsupportedOperationException();
   }
 
   @Override
-  public void fromDelta(DataInput in) throws IOException, InvalidDeltaException {
+  public void fromDelta(DataInput in) throws InvalidDeltaException {
     throw new UnsupportedOperationException();
   }
 }
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisData.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisData.java
index 765db2a..cb18c95 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisData.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisData.java
@@ -17,11 +17,11 @@
 package org.apache.geode.redis.internal.data;
 
 
-import org.apache.geode.DataSerializable;
 import org.apache.geode.Delta;
 import org.apache.geode.cache.Region;
+import org.apache.geode.internal.serialization.DataSerializableFixedID;
 
-public interface RedisData extends Delta, DataSerializable {
+public interface RedisData extends Delta, DataSerializableFixedID {
   NullRedisData NULL_REDIS_DATA = new NullRedisData();
 
   /**
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHash.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHash.java
index 095827c..6a3b078 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHash.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHash.java
@@ -40,6 +40,9 @@ import org.apache.commons.lang3.tuple.Pair;
 
 import org.apache.geode.DataSerializer;
 import org.apache.geode.cache.Region;
+import org.apache.geode.internal.serialization.DeserializationContext;
+import org.apache.geode.internal.serialization.KnownVersion;
+import org.apache.geode.internal.serialization.SerializationContext;
 import org.apache.geode.redis.internal.delta.AddsDeltaInfo;
 import org.apache.geode.redis.internal.delta.DeltaInfo;
 import org.apache.geode.redis.internal.delta.RemsDeltaInfo;
@@ -67,8 +70,8 @@ public class RedisHash extends AbstractRedisData {
    * to be thread safe with toData.
    */
   @Override
-  public synchronized void toData(DataOutput out) throws IOException {
-    super.toData(out);
+  public synchronized void toData(DataOutput out, SerializationContext context) throws IOException {
+    super.toData(out, context);
     DataSerializer.writePrimitiveInt(hash.size(), out);
     for (Map.Entry<byte[], byte[]> entry : hash.entrySet()) {
       byte[] key = entry.getKey();
@@ -78,6 +81,22 @@ public class RedisHash extends AbstractRedisData {
     }
   }
 
+  @Override
+  public void fromData(DataInput in, DeserializationContext context)
+      throws IOException, ClassNotFoundException {
+    super.fromData(in, context);
+    int size = DataSerializer.readInteger(in);
+    hash = new Object2ObjectOpenCustomHashMap<>(size, ByteArrays.HASH_STRATEGY);
+    for (int i = 0; i < size; i++) {
+      hash.put(DataSerializer.readByteArray(in), DataSerializer.readByteArray(in));
+    }
+  }
+
+  @Override
+  public int getDSFID() {
+    return REDIS_HASH_ID;
+  }
+
   private synchronized byte[] hashPut(byte[] field, byte[] value) {
     return hash.put(field, value);
   }
@@ -92,16 +111,6 @@ public class RedisHash extends AbstractRedisData {
   }
 
   @Override
-  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
-    super.fromData(in);
-    int size = DataSerializer.readInteger(in);
-    hash = new Object2ObjectOpenCustomHashMap<>(size, ByteArrays.HASH_STRATEGY);
-    for (int i = 0; i < size; i++) {
-      hash.put(DataSerializer.readByteArray(in), DataSerializer.readByteArray(in));
-    }
-  }
-
-  @Override
   protected void applyDelta(DeltaInfo deltaInfo) {
     if (deltaInfo instanceof AddsDeltaInfo) {
       AddsDeltaInfo addsDeltaInfo = (AddsDeltaInfo) deltaInfo;
@@ -370,4 +379,9 @@ public class RedisHash extends AbstractRedisData {
   public String toString() {
     return "RedisHash{" + super.toString() + ", " + "size=" + hash.size() + "}";
   }
+
+  @Override
+  public KnownVersion[] getSerializationVersions() {
+    return null;
+  }
 }
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisKey.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisKey.java
index 01eef22..19c0fa6 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisKey.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisKey.java
@@ -63,7 +63,7 @@ public class RedisKey extends ByteArrayWrapper
 
   @Override
   public void fromData(DataInput in, DeserializationContext context)
-      throws IOException, ClassNotFoundException {
+      throws IOException {
     routingId = DataSerializer.readInteger(in);
     super.fromData(in, context);
   }
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisSet.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisSet.java
index 1a97b16..c758e4a 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisSet.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisSet.java
@@ -36,9 +36,12 @@ import java.util.stream.Collectors;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 
-import org.apache.geode.DataSerializer;
 import org.apache.geode.annotations.VisibleForTesting;
 import org.apache.geode.cache.Region;
+import org.apache.geode.internal.InternalDataSerializer;
+import org.apache.geode.internal.serialization.DeserializationContext;
+import org.apache.geode.internal.serialization.KnownVersion;
+import org.apache.geode.internal.serialization.SerializationContext;
 import org.apache.geode.redis.internal.delta.AddsDeltaInfo;
 import org.apache.geode.redis.internal.delta.DeltaInfo;
 import org.apache.geode.redis.internal.delta.RemsDeltaInfo;
@@ -195,10 +198,23 @@ public class RedisSet extends AbstractRedisData {
    * are modifying this object, the striped executor will not protect toData.
    * So any methods that modify "members" needs to be thread safe with toData.
    */
+
+  @Override
+  public synchronized void toData(DataOutput out, SerializationContext context) throws IOException {
+    super.toData(out, context);
+    InternalDataSerializer.writeHashSet(members, out);
+  }
+
+  @Override
+  public void fromData(DataInput in, DeserializationContext context)
+      throws IOException, ClassNotFoundException {
+    super.fromData(in, context);
+    members = InternalDataSerializer.readHashSet(in);
+  }
+
   @Override
-  public synchronized void toData(DataOutput out) throws IOException {
-    super.toData(out);
-    DataSerializer.writeHashSet(members, out);
+  public int getDSFID() {
+    return REDIS_SET_ID;
   }
 
   private synchronized boolean membersAdd(ByteArrayWrapper memberToAdd) {
@@ -218,11 +234,7 @@ public class RedisSet extends AbstractRedisData {
     return members.removeAll(remsDeltaInfo.getRemoves());
   }
 
-  @Override
-  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
-    super.fromData(in);
-    members = DataSerializer.readHashSet(in);
-  }
+
 
   /**
    * @param membersToAdd members to add to this set; NOTE this list may by
@@ -309,4 +321,9 @@ public class RedisSet extends AbstractRedisData {
   public String toString() {
     return "RedisSet{" + super.toString() + ", " + "members=" + members + '}';
   }
+
+  @Override
+  public KnownVersion[] getSerializationVersions() {
+    return null;
+  }
 }
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisString.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisString.java
index a097de2..95e501e 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisString.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisString.java
@@ -25,6 +25,9 @@ import java.util.Objects;
 
 import org.apache.geode.DataSerializer;
 import org.apache.geode.cache.Region;
+import org.apache.geode.internal.serialization.DeserializationContext;
+import org.apache.geode.internal.serialization.KnownVersion;
+import org.apache.geode.internal.serialization.SerializationContext;
 import org.apache.geode.redis.internal.RedisConstants;
 import org.apache.geode.redis.internal.delta.AppendDeltaInfo;
 import org.apache.geode.redis.internal.delta.DeltaInfo;
@@ -600,24 +603,28 @@ public class RedisString extends AbstractRedisData {
   /**
    * Since GII (getInitialImage) can come in and call toData while other threads
    * are modifying this object, the striped executor will not protect toData.
-   * So any methods that modify "value" need to be thread safe with toData.
-   * But currently all of them are because we never modify the existing byte
-   * array owned by "value" in place. Instead we create a new byte array
-   * and call setBytes. So toData will see either the old or new value but
-   * not a mix of both.
+   * So any methods that modify "value", "appendSequence" need to be thread safe with toData.
    */
+
   @Override
-  public void toData(DataOutput out) throws IOException {
-    super.toData(out);
+  public synchronized void toData(DataOutput out, SerializationContext context) throws IOException {
+    super.toData(out, context);
     DataSerializer.writePrimitiveInt(appendSequence, out);
     DataSerializer.writeByteArray(value.toBytes(), out);
   }
 
   @Override
-  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
-    super.fromData(in);
+  public void fromData(DataInput in, DeserializationContext context)
+      throws IOException, ClassNotFoundException {
+    super.fromData(in, context);
     appendSequence = DataSerializer.readPrimitiveInt(in);
     value = new ByteArrayWrapper(DataSerializer.readByteArray(in));
+
+  }
+
+  @Override
+  public int getDSFID() {
+    return REDIS_STRING_ID;
   }
 
   @Override
@@ -717,4 +724,9 @@ public class RedisString extends AbstractRedisData {
   protected void valueSetBytes(byte[] bytes) {
     value.setBytes(bytes);
   }
+
+  @Override
+  public KnownVersion[] getSerializationVersions() {
+    return null;
+  }
 }
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
index 7bda1f9..d993153 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
@@ -40,6 +40,7 @@ import org.apache.geode.redis.internal.statistics.RedisStats;
 public class CommandFunction extends SingleResultRedisFunction {
 
   public static final String ID = "REDIS_COMMAND_FUNCTION";
+  private static final long serialVersionUID = -1302506316316454732L;
 
   private final transient RedisKeyCommandsFunctionExecutor keyCommands;
   private final transient RedisHashCommandsFunctionExecutor hashCommands;
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SingleResultRedisFunction.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SingleResultRedisFunction.java
index 713c442..64c1120 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SingleResultRedisFunction.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SingleResultRedisFunction.java
@@ -27,6 +27,7 @@ import org.apache.geode.redis.internal.data.RedisKey;
 
 public abstract class SingleResultRedisFunction implements InternalFunction<Object[]> {
 
+  private static final long serialVersionUID = 3239452234149879302L;
   private final transient PartitionedRegion partitionedRegion;
 
   public SingleResultRedisFunction(Region<RedisKey, RedisData> dataRegion) {
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/key/RenameFunction.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/key/RenameFunction.java
index 3440a1e..722920b 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/key/RenameFunction.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/key/RenameFunction.java
@@ -40,6 +40,7 @@ import org.apache.geode.redis.internal.statistics.RedisStats;
 public class RenameFunction implements InternalFunction {
 
   public static final String ID = "REDIS_RENAME_FUNCTION";
+  private static final long serialVersionUID = 7047473969356686453L;
 
   private final transient PartitionedRegion partitionedRegion;
   private final transient CommandHelper commandHelper;
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetOptions.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetOptions.java
index 14492e6..b9667ff 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetOptions.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetOptions.java
@@ -16,16 +16,24 @@
 
 package org.apache.geode.redis.internal.executor.string;
 
-import java.io.Serializable;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.geode.DataSerializer;
+import org.apache.geode.internal.serialization.DataSerializableFixedID;
+import org.apache.geode.internal.serialization.DeserializationContext;
+import org.apache.geode.internal.serialization.KnownVersion;
+import org.apache.geode.internal.serialization.SerializationContext;
 
 /**
  * Class representing different options that can be used with Redis string SET command.
  */
-public class SetOptions implements Serializable {
+public class SetOptions implements DataSerializableFixedID {
 
-  private final Exists exists;
-  private final long expirationMillis;
-  private final boolean keepTTL;
+  private Exists exists;
+  private long expirationMillis;
+  private boolean keepTTL;
 
   public SetOptions(Exists exists, long expiration, boolean keepTTL) {
     this.exists = exists;
@@ -33,6 +41,8 @@ public class SetOptions implements Serializable {
     this.keepTTL = keepTTL;
   }
 
+  public SetOptions() {}
+
   public boolean isNX() {
     return exists.equals(Exists.NX);
   }
@@ -53,6 +63,31 @@ public class SetOptions implements Serializable {
     return keepTTL;
   }
 
+  @Override
+  public int getDSFID() {
+    return REDIS_SET_OPTIONS_ID;
+  }
+
+  @Override
+  public void toData(DataOutput out, SerializationContext context) throws IOException {
+    DataSerializer.writeEnum(exists, out);
+    out.writeLong(expirationMillis);
+    out.writeBoolean(keepTTL);
+  }
+
+  @Override
+  public void fromData(DataInput in, DeserializationContext context)
+      throws IOException, ClassNotFoundException {
+    exists = DataSerializer.readEnum(SetOptions.Exists.class, in);
+    expirationMillis = in.readLong();
+    keepTTL = in.readBoolean();
+  }
+
+  @Override
+  public KnownVersion[] getSerializationVersions() {
+    return null;
+  }
+
   public enum Exists {
     NONE,
 
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/gfsh/RedisCommandFunction.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/gfsh/RedisCommandFunction.java
index 58ed73f..a1f5fa2 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/gfsh/RedisCommandFunction.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/gfsh/RedisCommandFunction.java
@@ -23,6 +23,8 @@ import org.apache.geode.redis.internal.GeodeRedisService;
 
 public class RedisCommandFunction extends CliFunction<Boolean> {
 
+  private static final long serialVersionUID = -6607122865046807926L;
+
   public static void register() {
     FunctionService.registerFunction(new RedisCommandFunction());
   }
diff --git a/geode-redis/src/main/resources/org/apache/geode/redis/internal/sanctioned-geode-redis-serializables.txt b/geode-redis/src/main/resources/org/apache/geode/redis/internal/sanctioned-geode-redis-serializables.txt
index 91c3141..e5d170c 100755
--- a/geode-redis/src/main/resources/org/apache/geode/redis/internal/sanctioned-geode-redis-serializables.txt
+++ b/geode-redis/src/main/resources/org/apache/geode/redis/internal/sanctioned-geode-redis-serializables.txt
@@ -8,12 +8,11 @@ org/apache/geode/redis/internal/data/NullRedisString$BitOp,false
 org/apache/geode/redis/internal/data/RedisDataType,false,toStringValue:java/lang/String
 org/apache/geode/redis/internal/data/RedisDataTypeMismatchException,true,-2451663685348513870
 org/apache/geode/redis/internal/delta/DeltaType,false
-org/apache/geode/redis/internal/executor/CommandFunction,false
-org/apache/geode/redis/internal/executor/SingleResultRedisFunction,false
-org/apache/geode/redis/internal/executor/key/RenameFunction,false
-org/apache/geode/redis/internal/executor/string/SetOptions,false,exists:org/apache/geode/redis/internal/executor/string/SetOptions$Exists,expirationMillis:long,keepTTL:boolean
+org/apache/geode/redis/internal/executor/CommandFunction,true,-1302506316316454732
+org/apache/geode/redis/internal/executor/SingleResultRedisFunction,true,3239452234149879302
+org/apache/geode/redis/internal/executor/key/RenameFunction,true,7047473969356686453
 org/apache/geode/redis/internal/executor/string/SetOptions$Exists,false
-org/apache/geode/redis/internal/gfsh/RedisCommandFunction,false
+org/apache/geode/redis/internal/gfsh/RedisCommandFunction,true,-6607122865046807926
 org/apache/geode/redis/internal/netty/CoderException,true,4707944288714910949
 org/apache/geode/redis/internal/netty/RedisCommandParserException,true,4707944288714910949
 org/apache/geode/redis/internal/pubsub/PubSubImpl$1,false,this$0:org/apache/geode/redis/internal/pubsub/PubSubImpl
diff --git a/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisHashTest.java b/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisHashTest.java
index f4142d9..4b7365d 100644
--- a/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisHashTest.java
+++ b/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisHashTest.java
@@ -19,7 +19,9 @@ package org.apache.geode.redis.internal.data;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 
+import java.io.DataOutput;
 import java.io.IOException;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collections;
 
@@ -33,6 +35,7 @@ import org.apache.geode.internal.HeapDataOutputStream;
 import org.apache.geode.internal.InternalDataSerializer;
 import org.apache.geode.internal.serialization.ByteArrayDataInput;
 import org.apache.geode.internal.serialization.DataSerializableFixedID;
+import org.apache.geode.internal.serialization.SerializationContext;
 import org.apache.geode.redis.internal.netty.Coder;
 
 public class RedisHashTest {
@@ -42,6 +45,16 @@ public class RedisHashTest {
     InternalDataSerializer
         .getDSFIDSerializer()
         .registerDSFID(DataSerializableFixedID.REDIS_BYTE_ARRAY_WRAPPER, ByteArrayWrapper.class);
+    InternalDataSerializer.getDSFIDSerializer().registerDSFID(
+        DataSerializableFixedID.REDIS_HASH_ID,
+        RedisHash.class);
+  }
+
+  @Test
+  public void confirmToDataIsSynchronized() throws NoSuchMethodException {
+    assertThat(Modifier.isSynchronized(RedisHash.class
+        .getMethod("toData", DataOutput.class, SerializationContext.class).getModifiers()))
+            .isTrue();
   }
 
   @Test
diff --git a/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisSetTest.java b/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisSetTest.java
index fd1c39f..bfd44f4 100644
--- a/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisSetTest.java
+++ b/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisSetTest.java
@@ -19,7 +19,9 @@ package org.apache.geode.redis.internal.data;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 
+import java.io.DataOutput;
 import java.io.IOException;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -33,6 +35,7 @@ import org.apache.geode.internal.HeapDataOutputStream;
 import org.apache.geode.internal.InternalDataSerializer;
 import org.apache.geode.internal.serialization.ByteArrayDataInput;
 import org.apache.geode.internal.serialization.DataSerializableFixedID;
+import org.apache.geode.internal.serialization.SerializationContext;
 
 public class RedisSetTest {
 
@@ -41,6 +44,9 @@ public class RedisSetTest {
     InternalDataSerializer
         .getDSFIDSerializer()
         .registerDSFID(DataSerializableFixedID.REDIS_BYTE_ARRAY_WRAPPER, ByteArrayWrapper.class);
+    InternalDataSerializer.getDSFIDSerializer().registerDSFID(
+        DataSerializableFixedID.REDIS_SET_ID,
+        RedisSet.class);
   }
 
   @Test
@@ -54,6 +60,14 @@ public class RedisSetTest {
     assertThat(o2).isEqualTo(o1);
   }
 
+  @Test
+  public void confirmToDataIsSynchronized() throws NoSuchMethodException {
+    assertThat(Modifier
+        .isSynchronized(RedisSet.class
+            .getMethod("toData", DataOutput.class, SerializationContext.class).getModifiers()))
+                .isTrue();
+  }
+
   private RedisSet createRedisSet(int m1, int m2) {
     return new RedisSet(Arrays.asList(
         new ByteArrayWrapper(new byte[] {(byte) m1}),
diff --git a/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisStringTest.java b/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisStringTest.java
index f9540f0..9883ecd 100644
--- a/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisStringTest.java
+++ b/geode-redis/src/test/java/org/apache/geode/redis/internal/data/RedisStringTest.java
@@ -20,7 +20,9 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.Mockito.mock;
 
+import java.io.DataOutput;
 import java.io.IOException;
+import java.lang.reflect.Modifier;
 import java.math.BigDecimal;
 
 import org.junit.BeforeClass;
@@ -32,6 +34,7 @@ import org.apache.geode.internal.HeapDataOutputStream;
 import org.apache.geode.internal.InternalDataSerializer;
 import org.apache.geode.internal.serialization.ByteArrayDataInput;
 import org.apache.geode.internal.serialization.DataSerializableFixedID;
+import org.apache.geode.internal.serialization.SerializationContext;
 
 public class RedisStringTest {
 
@@ -40,6 +43,9 @@ public class RedisStringTest {
     InternalDataSerializer
         .getDSFIDSerializer()
         .registerDSFID(DataSerializableFixedID.REDIS_BYTE_ARRAY_WRAPPER, ByteArrayWrapper.class);
+    InternalDataSerializer.getDSFIDSerializer().registerDSFID(
+        DataSerializableFixedID.REDIS_STRING_ID,
+        RedisString.class);
   }
 
   @Test
@@ -105,7 +111,7 @@ public class RedisStringTest {
   }
 
   @Test
-  public void serializationIsStable() throws IOException, ClassNotFoundException {
+  public void confirmSerializationIsStable() throws IOException, ClassNotFoundException {
     RedisString o1 = new RedisString(new ByteArrayWrapper(new byte[] {0, 1, 2, 3}));
     o1.setExpirationTimestampNoDelta(1000);
     HeapDataOutputStream outputStream = new HeapDataOutputStream(100);
@@ -116,6 +122,14 @@ public class RedisStringTest {
   }
 
   @Test
+  public void confirmToDataIsSynchronized() throws NoSuchMethodException {
+    assertThat(Modifier
+        .isSynchronized(RedisString.class
+            .getMethod("toData", DataOutput.class, SerializationContext.class).getModifiers()))
+                .isTrue();
+  }
+
+  @Test
   public void incrThrowsArithmeticErrorWhenNotALong() {
     // allows unchecked cast of mock to Region<RedisKey, RedisData>
     @SuppressWarnings("unchecked")
diff --git a/geode-redis/src/test/resources/expected-pom.xml b/geode-redis/src/test/resources/expected-pom.xml
index c17b109..d4c17a5 100644
--- a/geode-redis/src/test/resources/expected-pom.xml
+++ b/geode-redis/src/test/resources/expected-pom.xml
@@ -59,6 +59,17 @@
     </dependency>
     <dependency>
       <groupId>org.apache.geode</groupId>
+      <artifactId>geode-membership</artifactId>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>spring-boot-starter-logging</artifactId>
+          <groupId>org.springframework.boot</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geode</groupId>
       <artifactId>geode-logging</artifactId>
       <scope>runtime</scope>
       <exclusions>
@@ -91,6 +102,17 @@
       </exclusions>
     </dependency>
     <dependency>
+      <groupId>it.unimi.dsi</groupId>
+      <artifactId>fastutil</artifactId>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>spring-boot-starter-logging</artifactId>
+          <groupId>org.springframework.boot</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
       <groupId>com.github.davidmoten</groupId>
       <artifactId>geo</artifactId>
       <scope>runtime</scope>
diff --git a/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java b/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java
index 7a30846..5168ae4 100644
--- a/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java
+++ b/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java
@@ -682,7 +682,11 @@ public interface DataSerializableFixedID extends SerializationVersions, BasicSer
   short ABORT_BACKUP_REQUEST = 2183;
   short MEMBER_IDENTIFIER = 2184;
   short HOST_AND_PORT = 2185;
-
+  short REDIS_SET_ID = 2186;
+  short REDIS_STRING_ID = 2187;
+  short REDIS_HASH_ID = 2188;
+  short REDIS_NULL_DATA_ID = 2189;
+  short REDIS_SET_OPTIONS_ID = 2190;
   // NOTE, codes > 65535 will take 4 bytes to serialize
 
   /**