@Override
 protected void storeSession(final RedisSession session) {
   if (!session.redisMap.isEmpty()) {
     final Map<String, String> toStore =
         session.redisMap.containsKey("attributes")
             ? session.redisMap
             : new TreeMap<String, String>(session.redisMap);
     if (toStore.containsKey("attributes"))
       toStore.put("attributes", serializer.serialize(session.getSessionAttributes()));
     LOG.debug(
         "[RedisSessionManager] storeSession - Storing session id={}", session.getClusterId());
     jedisExecutor.execute(
         new JedisCallback<Object>() {
           @Override
           public Object execute(Jedis jedis) {
             session.lastSaved = System.currentTimeMillis();
             toStore.put("lastSaved", "" + session.lastSaved);
             return jedis.multi(
                 new TransactionBlock() {
                   @Override
                   public void execute() throws JedisException {
                     final String key =
                         RedisSessionIdManager.REDIS_SESSION_KEY + session.getClusterId();
                     super.hmset(key, toStore);
                     int ttl = session.getMaxInactiveInterval();
                     if (ttl > 0) {
                       super.expire(key, ttl);
                     }
                   }
                 });
           }
         });
     session.redisMap.clear();
   }
 }
 private RedisSession loadFromStore(final String clusterId, final RedisSession current) {
   List<String> redisData =
       jedisExecutor.execute(
           new JedisCallback<List<String>>() {
             @Override
             public List<String> execute(Jedis jedis) {
               final String key = RedisSessionIdManager.REDIS_SESSION_KEY + clusterId;
               if (current == null) {
                 return jedis.exists(key) ? jedis.hmget(key, FIELDS) : null;
               } else {
                 String val = jedis.hget(key, "lastSaved");
                 if (val == null) {
                   // no session in store
                   return Collections.emptyList();
                 }
                 if (current.lastSaved != Long.parseLong(val)) {
                   // session has changed - reload
                   return jedis.hmget(key, FIELDS);
                 } else {
                   // session dit not changed in cache since last save
                   return null;
                 }
               }
             }
           });
   if (redisData == null) {
     // case where session has not been modified
     return current;
   }
   if (redisData.isEmpty() || redisData.get(0) == null) {
     // no session found in redis (no data)
     return null;
   }
   Map<String, String> data = new HashMap<String, String>();
   for (int i = 0; i < FIELDS.length; i++) data.put(FIELDS[i], redisData.get(i));
   String attrs = data.get("attributes");
   //noinspection unchecked
   return new RedisSession(
       data,
       attrs == null ? new HashMap<String, Object>() : serializer.deserialize(attrs, Map.class));
 }
 @Override
 public void doStop() throws Exception {
   super.doStop();
   serializer.stop();
 }
 @Override
 public void doStart() throws Exception {
   serializer.start();
   super.doStart();
 }