@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();
   }
 }
 public RedisSession createSession() {
   RedisSession redisSession = new RedisSession();
   if (defaultMaxInactiveInterval != null) {
     redisSession.setMaxInactiveIntervalInSeconds(defaultMaxInactiveInterval);
   }
   return redisSession;
 }
 /**
  * @param id the session id
  * @param allowExpired if true, will also include expired sessions that have not been deleted. If
  *     false, will ensure expired sessions are not returned.
  * @return
  */
 private RedisSession getSession(String id, boolean allowExpired) {
   Map<Object, Object> entries = getSessionBoundHashOperations(id).entries();
   if (entries.isEmpty()) {
     return null;
   }
   MapSession loaded = new MapSession();
   loaded.setId(id);
   for (Map.Entry<Object, Object> entry : entries.entrySet()) {
     String key = (String) entry.getKey();
     if (CREATION_TIME_ATTR.equals(key)) {
       loaded.setCreationTime((Long) entry.getValue());
     } else if (MAX_INACTIVE_ATTR.equals(key)) {
       loaded.setMaxInactiveIntervalInSeconds((Integer) entry.getValue());
     } else if (LAST_ACCESSED_ATTR.equals(key)) {
       loaded.setLastAccessedTime((Long) entry.getValue());
     } else if (key.startsWith(SESSION_ATTR_PREFIX)) {
       loaded.setAttribute(key.substring(SESSION_ATTR_PREFIX.length()), entry.getValue());
     }
   }
   if (!allowExpired && loaded.isExpired()) {
     return null;
   }
   RedisSession result = new RedisSession(loaded);
   result.originalLastAccessTime =
       loaded.getLastAccessedTime()
           + TimeUnit.SECONDS.toMillis(loaded.getMaxInactiveIntervalInSeconds());
   result.setLastAccessedTime(System.currentTimeMillis());
   return result;
 }
 @Override
 protected void deleteSession(final RedisSession session) {
   LOG.debug(
       "[RedisSessionManager] deleteSession - Deleting from Redis session id={}",
       session.getClusterId());
   jedisExecutor.execute(
       new JedisCallback<Object>() {
         @Override
         public Object execute(Jedis jedis) {
           return jedis.del(RedisSessionIdManager.REDIS_SESSION_KEY + session.getClusterId());
         }
       });
 }
 @Override
 protected RedisSession loadSession(final String clusterId, final RedisSession current) {
   long now = System.currentTimeMillis();
   RedisSession loaded;
   if (current == null) {
     LOG.debug(
         "[RedisSessionManager] loadSession - No session found in cache, loading id={}",
         clusterId);
     loaded = loadFromStore(clusterId, current);
   } else if (current.requestStarted()) {
     LOG.debug(
         "[RedisSessionManager] loadSession - Existing session found in cache, loading id={}",
         clusterId);
     loaded = loadFromStore(clusterId, current);
   } else {
     loaded = current;
   }
   if (loaded == null) {
     LOG.debug(
         "[RedisSessionManager] loadSession - No session found in Redis for id={}", clusterId);
     if (current != null) current.invalidate();
   } else if (loaded == current) {
     LOG.debug(
         "[RedisSessionManager] loadSession - No change found in Redis for session id={}",
         clusterId);
     return loaded;
   } else if (!loaded.lastNode.equals(getSessionIdManager().getWorkerName()) || current == null) {
     // if the session in the database has not already expired
     if (loaded.expiryTime * 1000 > now) {
       // session last used on a different node, or we don't have it in memory
       loaded.changeLastNode(getSessionIdManager().getWorkerName());
     } else {
       LOG.debug(
           "[RedisSessionManager] loadSession - Loaded session has expired, id={}", clusterId);
       loaded = null;
     }
   }
   return loaded;
 }
 public void save(RedisSession session) {
   session.saveDelta();
 }