基于Redis的在线用户列表解决方案

系统 2015 0

前言:

由于项目需求,需要在集群环境下实现在线用户列表的功能,并依靠在线列表实现用户单一登陆(同一账户只能一处登陆)功能:

在单机环境下,在线列表的实现方案可以采用SessionListener来完成,当有Session创建和销毁的时候做相应的操作即可完成功能及将相应的Session的引用存放于内存中,由于持有了所有的Session的引用,故可以方便的实现用户单一登陆的功能(比如在第二次登陆的时候使之前登陆的账户所在的Session失效)。

而在集群环境下,由于用户的请求可能分布在不同的Web服务器上,继续将在线用户列表储存在单机内存中已经不能满足需要,不同的Web服务器将会产生不同的在线列表,并且不能有效的实现单一用户登陆的功能,因为某一用户可能并不在接受到退出请求的Web服务器的在线用户列表中(在集群中的某台服务器上完成的登陆操作,而在其他服务器上完成退出操作)。

现有解决方案:

1.将用户的在线情况记录进入数据库中,依靠数据库完成对登陆状况的检测

2.将在线列表放在一个公共的缓存服务器上

由于缓存服务器可以为缓存内容设置指定有效期,可以方便实现Session过期的效果,以及避免让数据库的读写性能成为系统瓶颈等原因,我们采用了Redis来作为缓存服务器用于实现该功能。

单机环境下的解决方案:

基于HttpSessionListener:

      
         1
      
      
        import
      
      
         java.util.Date;


      
      
         2
      
      
        import
      
      
         java.util.Hashtable;


      
      
         3
      
      
        import
      
      
         java.util.Iterator;


      
      
         4
      
      
        import
      
      
         javax.servlet.http.HttpSession;


      
      
         5
      
      
        import
      
      
         javax.servlet.http.HttpSessionEvent;


      
      
         6
      
      
        import
      
      
         javax.servlet.http.HttpSessionListener;


      
      
         7
      
      
        import
      
      
         com.xxx.common.util.StringUtil;


      
      
         8
      
      
        /**
      
      
         9
      
      
         * 


      
      
        10
      
      
         * @ClassName: SessionListener


      
      
        11
      
      
         * @Description: 记录所有登陆的Session信息,为在线列表做基础


      
      
        12
      
      
         * 
      
      
        @author
      
      
         libaoting


      
      
        13
      
      
         * @date 2013-9-18 09:35:13


      
      
        14
      
      
         *


      
      
        15
      
      
        */
      
      
        16
      
      
        public
      
      
        class
      
       SessionListener 
      
        implements
      
      
         HttpSessionListener {


      
      
        17
      
      
        //
      
      
        在线列表<uid,session>
      
      
        18
      
      
        private
      
      
        static
      
       Hashtable<String,HttpSession> sessionList = 
      
        new
      
       Hashtable<String, HttpSession>
      
        ();


      
      
        19
      
      
        public
      
      
        void
      
      
         sessionCreated(HttpSessionEvent event) {


      
      
        20
      
      
        //
      
      
        不做处理,只处理登陆用户的列表
      
      
        21
      
      
            }


      
      
        22
      
      
        public
      
      
        void
      
      
         sessionDestroyed(HttpSessionEvent event) {


      
      
        23
      
      
                removeSession(event.getSession());


      
      
        24
      
      
            }


      
      
        25
      
      
        public
      
      
        static
      
      
        void
      
      
         removeSession(HttpSession session){


      
      
        26
      
      
        if
      
      (session == 
      
        null
      
      
        ){


      
      
        27
      
      
        return
      
      
         ;


      
      
        28
      
      
                }


      
      
        29
      
               String uid=(String)session.getAttribute("clientUserId");
      
        //
      
      
        已登陆状态会将用户的UserId保存在session中
      
      
        30
      
      
        if
      
      (!StringUtil.isBlank(uid)){
      
        //
      
      
        判断是否登陆状态
      
      
        31
      
      
                    removeSession(uid);


      
      
        32
      
      
                }


      
      
        33
      
      
            }


      
      
        34
      
      
        public
      
      
        static
      
      
        void
      
      
         removeSession(String uid){


      
      
        35
      
               HttpSession session =
      
         sessionList.get(uid);


      
      
        36
      
      
        try
      
      
        {


      
      
        37
      
                   sessionList.remove(uid);
      
        //
      
      
        先执行,防止session.invalidate()报错而不执行
      
      
        38
      
      
        if
      
      (session != 
      
        null
      
      
        ){


      
      
        39
      
      
                        session.invalidate();


      
      
        40
      
      
                    }


      
      
        41
      
               }
      
        catch
      
      
         (Exception e) {


      
      
        42
      
                   System.out.println("Session invalidate error!"
      
        );


      
      
        43
      
      
                }


      
      
        44
      
      
            }


      
      
        45
      
      
        public
      
      
        static
      
      
        void
      
      
         addSession(String uid,HttpSession session){


      
      
        46
      
      
                sessionList.put(uid, session);


      
      
        47
      
      
            }


      
      
        48
      
      
        public
      
      
        static
      
      
        int
      
      
         getSessionCount(){


      
      
        49
      
      
        return
      
      
         sessionList.size();


      
      
        50
      
      
            }


      
      
        51
      
      
        public
      
      
        static
      
       Iterator<HttpSession>
      
         getSessionSet(){


      
      
        52
      
      
        return
      
      
         sessionList.values().iterator();


      
      
        53
      
      
            }


      
      
        54
      
      
        public
      
      
        static
      
      
         HttpSession getSession(String id){


      
      
        55
      
      
        return
      
      
         sessionList.get(id);


      
      
        56
      
      
            }


      
      
        57
      
      
        public
      
      
        static
      
      
        boolean
      
      
         contains(String uid){


      
      
        58
      
      
        return
      
      
         sessionList.containsKey(uid);


      
      
        59
      
      
            }


      
      
        60
      
      
        /**
      
      
        61
      
      
             * 


      
      
        62
      
      
             * @Title: isLoginOnThisSession


      
      
        63
      
      
             * @Description: 检测是否已经登陆


      
      
        64
      
      
             * 
      
      
        @param
      
      
        @param
      
      
         uid 用户UserId


      
      
        65
      
      
             * 
      
      
        @param
      
      
        @param
      
      
         sid 发起请求的用户的SessionId


      
      
        66
      
      
             * 
      
      
        @return
      
      
         boolean true 校验通过 


      
      
        67
      
      
        */
      
      
        68
      
      
        public
      
      
        static
      
      
        boolean
      
      
         isLoginOnThisSession(String uid,String sid){


      
      
        69
      
      
        if
      
      (uid==
      
        null
      
      ||sid==
      
        null
      
      
        ){


      
      
        70
      
      
        return
      
      
        false
      
      
        ;


      
      
        71
      
      
                }


      
      
        72
      
      
        if
      
      
        (contains(uid)){


      
      
        73
      
                   HttpSession session =
      
         sessionList.get(uid);


      
      
        74
      
      
        if
      
      (session!=
      
        null
      
      &&
      
        session.getId().equals(sid)){


      
      
        75
      
      
        return
      
      
        true
      
      
        ;


      
      
        76
      
      
                    }


      
      
        77
      
      
                }


      
      
        78
      
      
        return
      
      
        false
      
      
        ;


      
      
        79
      
      
            }


      
      
        80
      
       }
    

  用户的在线状态全部维护记录在sessionList中,并且可以通过sessionList获取到任意用户的session对象,可以用来完成使指定用户离线的功能(调用该用户的session.invalidate()方法)。

用户登录的时候调用addSession(uid,session)方法将用户与其登录的Session信息记录至sessionList中,再退出的时候调用removeSession(session) or removeSession(uid)方法,在强制下线的时候调用removeSession(uid)方法,以及一些其他的操作即可实现相应的功能。

基于Redis的解决方案:

该解决方案的实质是将在线列表的所在的内存共享出来,让集群环境下所有的服务器都能够访问到这部分数据,并且将用户的在线状态在这块内存中进行维护。

Redis连接池工具类:

      
          1
      
      
        import
      
      
         java.util.ResourceBundle;


      
      
          2
      
      
        import
      
      
         redis.clients.jedis.Jedis;


      
      
          3
      
      
        import
      
      
         redis.clients.jedis.JedisPool;


      
      
          4
      
      
        import
      
      
         redis.clients.jedis.JedisPoolConfig;


      
      
          5
      
      
        public
      
      
        class
      
      
         RedisPoolUtils {


      
      
          6
      
      
        private
      
      
        static
      
      
        final
      
      
         JedisPool pool;


      
      
          7
      
      
        static
      
      
        {


      
      
          8
      
               ResourceBundle bundle = ResourceBundle.getBundle("redis"
      
        );


      
      
          9
      
               JedisPoolConfig config = 
      
        new
      
      
         JedisPoolConfig();


      
      
         10
      
      
        if
      
       (bundle == 
      
        null
      
      
        ) {    


      
      
         11
      
      
        throw
      
      
        new
      
       IllegalArgumentException("[redis.properties] is not found!"
      
        );    


      
      
         12
      
      
                }


      
      
         13
      
      
        //
      
      
        设置池配置项值  
      
      
         14
      
               config.setMaxActive(Integer.valueOf(bundle.getString("jedis.pool.maxActive"
      
        )));    


      
      
         15
      
               config.setMaxIdle(Integer.valueOf(bundle.getString("jedis.pool.maxIdle"
      
        )));    


      
      
         16
      
               config.setMaxWait(Long.valueOf(bundle.getString("jedis.pool.maxWait"
      
        )));    


      
      
         17
      
               config.setTestOnBorrow(Boolean.valueOf(bundle.getString("jedis.pool.testOnBorrow"
      
        )));    


      
      
         18
      
               config.setTestOnReturn(Boolean.valueOf(bundle.getString("jedis.pool.testOnReturn"
      
        )));


      
      
         19
      
               pool = 
      
        new
      
       JedisPool(config, bundle.getString("redis.ip"),Integer.valueOf(bundle.getString("redis.port"
      
        )) );


      
      
         20
      
      
            }


      
      
         21
      
      
        /**
      
      
         22
      
      
             * 


      
      
         23
      
      
             * @Title: release


      
      
         24
      
      
             * @Description: 释放连接


      
      
         25
      
      
             * 
      
      
        @param
      
      
        @param
      
      
         jedis


      
      
         26
      
      
             * 
      
      
        @return
      
      
         void


      
      
         27
      
      
             * 
      
      
        @throws
      
      
         28
      
      
        */
      
      
         29
      
      
        public
      
      
        static
      
      
        void
      
      
         release(Jedis jedis){


      
      
         30
      
      
                pool.returnResource(jedis);


      
      
         31
      
      
            }


      
      
         32
      
      
        public
      
      
        static
      
      
         Jedis getJedis(){


      
      
         33
      
      
        return
      
      
         pool.getResource();


      
      
         34
      
      
            }


      
      
         35
      
      
        }


      
      
         36
      
      
        Redis在线列表工具类:


      
      
         37
      
      
        import
      
      
         java.util.ArrayList;


      
      
         38
      
      
        import
      
      
         java.util.Collections;


      
      
         39
      
      
        import
      
      
         java.util.Comparator;


      
      
         40
      
      
        import
      
      
         java.util.Date;


      
      
         41
      
      
        import
      
      
         java.util.List;


      
      
         42
      
      
        import
      
      
         java.util.Set;


      
      
         43
      
      
        import
      
      
         net.sf.json.JSONObject;


      
      
         44
      
      
        import
      
      
         net.sf.json.JsonConfig;


      
      
         45
      
      
        import
      
      
         net.sf.json.processors.JsonValueProcessor;


      
      
         46
      
      
        import
      
      
         cn.sccl.common.util.StringUtil;


      
      
         47
      
      
        import
      
      
         com.xxx.common.util.JsonDateValueProcessor;


      
      
         48
      
      
        import
      
      
         com.xxx.user.model.ClientUser;


      
      
         49
      
      
        import
      
      
         redis.clients.jedis.Jedis;


      
      
         50
      
      
        import
      
      
         redis.clients.jedis.Pipeline;


      
      
         51
      
      
        import
      
      
         tools.Constants;


      
      
         52
      
      
        /**
      
      
         53
      
      
         * 


      
      
         54
      
      
         * Redis缓存中存放两组key:


      
      
         55
      
      
         * 1.SID_PREFIX开头,存放登陆用户的SessionId与ClientUser的Json数据


      
      
         56
      
      
         * 2.UID_PREFIX开头,存放登录用户的UID与SessionId对于的数据


      
      
         57
      
      
         *


      
      
         58
      
      
         * 3.VID_PREFIX开头,存放位于指定页面用户的数据(与Ajax一起使用,用于实现指定页面同时浏览人数的限制功能)


      
      
         59
      
      
         * 


      
      
         60
      
      
         * @ClassName: OnlineUtils


      
      
         61
      
      
         * @Description: 在线列表操作工具类


      
      
         62
      
      
         * 
      
      
        @author
      
      
         BuilderQiu


      
      
         63
      
      
         * @date 2014-1-9 上午09:25:43


      
      
         64
      
      
         *


      
      
         65
      
      
        */
      
      
         66
      
      
        public
      
      
        class
      
      
         OnlineUtils {


      
      
         67
      
      
        //
      
      
        KEY值根据SessionID生成    
      
      
         68
      
      
        private
      
      
        static
      
      
        final
      
       String SID_PREFIX = "online:sid:"
      
        ;


      
      
         69
      
      
        private
      
      
        static
      
      
        final
      
       String UID_PREFIX = "online:uid:"
      
        ;


      
      
         70
      
      
        private
      
      
        static
      
      
        final
      
       String VID_PREFIX = "online:vid:"
      
        ;


      
      
         71
      
      
        private
      
      
        static
      
      
        final
      
      
        int
      
       OVERDATETIME = 30 * 60
      
        ;


      
      
         72
      
      
        private
      
      
        static
      
      
        final
      
      
        int
      
       BROADCAST_OVERDATETIME = 70;
      
        //
      
      
        ax每60秒发起一次,超过BROADCAST_OVERDATETIME时间长度未发起表示已经离开该页面
      
      
         73
      
      
        public
      
      
        static
      
      
        void
      
      
         login(String sid,ClientUser user){


      
      
         74
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
         75
      
               jedis.setex(SID_PREFIX+
      
        sid, OVERDATETIME, userToString(user));


      
      
         76
      
               jedis.setex(UID_PREFIX+
      
        user.getId(), OVERDATETIME, sid);


      
      
         77
      
      
                RedisPoolUtils.release(jedis);


      
      
         78
      
      
            }


      
      
         79
      
      
        public
      
      
        static
      
      
        void
      
      
         broadcast(String uid,String identify){


      
      
         80
      
      
        if
      
      (uid==
      
        null
      
      ||"".equals(uid)) 
      
        //
      
      
        异常数据,正常情况下登陆用户才会发起该请求
      
      
         81
      
      
        return
      
      
         ;


      
      
         82
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
         83
      
               jedis.setex(VID_PREFIX+identify+":"+
      
        uid, BROADCAST_OVERDATETIME, uid);


      
      
         84
      
      
                RedisPoolUtils.release(jedis);


      
      
         85
      
      
            }


      
      
         86
      
      
        private
      
      
        static
      
      
         String userToString(ClientUser user){


      
      
         87
      
               JsonConfig  config = 
      
        new
      
      
         JsonConfig();


      
      
         88
      
               JsonValueProcessor processor = 
      
        new
      
       JsonDateValueProcessor("yyyy-MM-dd HH:mm:ss"
      
        );


      
      
         89
      
               config.registerJsonValueProcessor(Date.
      
        class
      
      
        , processor);


      
      
         90
      
               JSONObject obj =
      
         JSONObject.fromObject(user, config);


      
      
         91
      
      
        return
      
      
         obj.toString();


      
      
         92
      
      
            }


      
      
         93
      
      
        /**
      
      
         94
      
      
             * 


      
      
         95
      
      
             * @Title: logout


      
      
         96
      
      
             * @Description: 退出


      
      
         97
      
      
             * 
      
      
        @param
      
      
        @param
      
      
         sessionId


      
      
         98
      
      
             * 
      
      
        @return
      
      
         void


      
      
         99
      
      
             * 
      
      
        @throws
      
      
        100
      
      
        */
      
      
        101
      
      
        public
      
      
        static
      
      
        void
      
      
         logout(String sid,String uid){


      
      
        102
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        103
      
               jedis.del(SID_PREFIX+
      
        sid);


      
      
        104
      
               jedis.del(UID_PREFIX+
      
        uid);


      
      
        105
      
      
                RedisPoolUtils.release(jedis);


      
      
        106
      
      
            }


      
      
        107
      
      
        /**
      
      
        108
      
      
             * 


      
      
        109
      
      
             * @Title: logout


      
      
        110
      
      
             * @Description: 退出


      
      
        111
      
      
             * 
      
      
        @param
      
      
        @param
      
      
         UserId  使指定用户下线


      
      
        112
      
      
             * 
      
      
        @return
      
      
         void


      
      
        113
      
      
             * 
      
      
        @throws
      
      
        114
      
      
        */
      
      
        115
      
      
        public
      
      
        static
      
      
        void
      
      
         logout(String uid){


      
      
        116
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        117
      
      
        //
      
      
        删除sid
      
      
        118
      
               jedis.del(SID_PREFIX+jedis.get(UID_PREFIX+
      
        uid));


      
      
        119
      
      
        //
      
      
        删除uid
      
      
        120
      
               jedis.del(UID_PREFIX+
      
        uid);


      
      
        121
      
      
                RedisPoolUtils.release(jedis);


      
      
        122
      
      
            }


      
      
        123
      
      
        public
      
      
        static
      
      
         String getClientUserBySessionId(String sid){


      
      
        124
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        125
      
               String user = jedis.get(SID_PREFIX+
      
        sid);


      
      
        126
      
      
                RedisPoolUtils.release(jedis);


      
      
        127
      
      
        return
      
      
         user;


      
      
        128
      
      
            }


      
      
        129
      
      
        public
      
      
        static
      
      
         String getClientUserByUid(String uid){


      
      
        130
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        131
      
               String user = jedis.get(SID_PREFIX+jedis.get(UID_PREFIX+
      
        uid));


      
      
        132
      
      
                RedisPoolUtils.release(jedis);


      
      
        133
      
      
        return
      
      
         user;


      
      
        134
      
      
            }


      
      
        135
      
      
        /**
      
      
        136
      
      
             * 


      
      
        137
      
      
             * @Title: online


      
      
        138
      
      
             * @Description: 所有的key


      
      
        139
      
      
             * 
      
      
        @return
      
      
         List  


      
      
        140
      
      
             * 
      
      
        @throws
      
      
        141
      
      
        */
      
      
        142
      
      
        public
      
      
        static
      
      
         List online(){


      
      
        143
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        144
      
               Set online = jedis.keys(SID_PREFIX+"*"
      
        );


      
      
        145
      
      
                RedisPoolUtils.release(jedis);


      
      
        146
      
      
        return
      
      
        new
      
      
         ArrayList(online);


      
      
        147
      
      
            }


      
      
        148
      
      
        /**
      
      
        149
      
      
             * 


      
      
        150
      
      
             * @Title: online


      
      
        151
      
      
             * @Description: 分页显示在线列表


      
      
        152
      
      
             * 
      
      
        @return
      
      
         List  


      
      
        153
      
      
             * 
      
      
        @throws
      
      
        154
      
      
        */
      
      
        155
      
      
        public
      
      
        static
      
       List onlineByPage(
      
        int
      
       page,
      
        int
      
       pageSize) 
      
        throws
      
      
         Exception{


      
      
        156
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        157
      
               Set onlineSet = jedis.keys(SID_PREFIX+"*"
      
        );


      
      
        158
      
               List onlines =
      
        new
      
      
         ArrayList(onlineSet);


      
      
        159
      
      
        if
      
      (onlines.size() == 0
      
        ){


      
      
        160
      
      
        return
      
      
        null
      
      
        ;


      
      
        161
      
      
                }


      
      
        162
      
               Pipeline pip =
      
         jedis.pipelined();


      
      
        163
      
      
        for
      
      
        (Object key:onlines){


      
      
        164
      
      
                    pip.get(getKey(key));


      
      
        165
      
      
                }


      
      
        166
      
               List result =
      
         pip.syncAndReturnAll();


      
      
        167
      
      
                RedisPoolUtils.release(jedis);


      
      
        168
      
               List<ClientUser> listUser=
      
        new
      
       ArrayList<ClientUser>
      
        ();


      
      
        169
      
      
        for
      
      (
      
        int
      
       i=0;i<result.size();i++
      
        ){


      
      
        170
      
      
                    listUser.add(Constants.json2ClientUser((String)result.get(i)));


      
      
        171
      
      
                }


      
      
        172
      
               Collections.sort(listUser,
      
        new
      
       Comparator<ClientUser>
      
        (){


      
      
        173
      
      
        public
      
      
        int
      
      
         compare(ClientUser o1, ClientUser o2) {


      
      
        174
      
      
        return
      
      
         o2.getLastLoginTime().compareTo(o1.getLastLoginTime());


      
      
        175
      
      
                    }


      
      
        176
      
      
                });


      
      
        177
      
               onlines=
      
        listUser;


      
      
        178
      
      
        int
      
       start = (page - 1) *
      
         pageSize;


      
      
        179
      
      
        int
      
       toIndex=(start+pageSize)>onlines.size()?onlines.size():start+
      
        pageSize;


      
      
        180
      
               List list =
      
         onlines.subList(start, toIndex);


      
      
        181
      
      
        return
      
      
         list;


      
      
        182
      
      
            }


      
      
        183
      
      
        private
      
      
        static
      
      
         String getKey(Object obj){


      
      
        184
      
               String temp =
      
         String.valueOf(obj);


      
      
        185
      
               String key[] = temp.split(":"
      
        );


      
      
        186
      
      
        return
      
       SID_PREFIX+key[key.length-1
      
        ];


      
      
        187
      
      
            }


      
      
        188
      
      
        /**
      
      
        189
      
      
             * 


      
      
        190
      
      
             * @Title: onlineCount


      
      
        191
      
      
             * @Description: 总在线人数


      
      
        192
      
      
             * 
      
      
        @param
      
      
        @return
      
      
        193
      
      
             * 
      
      
        @return
      
      
         int


      
      
        194
      
      
             * 
      
      
        @throws
      
      
        195
      
      
        */
      
      
        196
      
      
        public
      
      
        static
      
      
        int
      
      
         onlineCount(){


      
      
        197
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        198
      
               Set online = jedis.keys(SID_PREFIX+"*"
      
        );


      
      
        199
      
      
                RedisPoolUtils.release(jedis);


      
      
        200
      
      
        return
      
      
         online.size();


      
      
        201
      
      
            }


      
      
        202
      
      
        /**
      
      
        203
      
      
             * 获取指定页面在线人数总数


      
      
        204
      
      
        */
      
      
        205
      
      
        public
      
      
        static
      
      
        int
      
      
         broadcastCount(String identify) {


      
      
        206
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        207
      
               Set online = jedis.keys(VID_PREFIX+identify+":*"
      
        );


      
      
        208
      
      
                RedisPoolUtils.release(jedis);


      
      
        209
      
      
        return
      
      
         online.size();


      
      
        210
      
      
            }


      
      
        211
      
      
        /**
      
      
        212
      
      
             * 自己是否在线


      
      
        213
      
      
        */
      
      
        214
      
      
        public
      
      
        static
      
      
        boolean
      
      
         broadcastIsOnline(String identify,String uid) {


      
      
        215
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        216
      
               String online = jedis.get(VID_PREFIX+identify+":"+
      
        uid);


      
      
        217
      
      
                RedisPoolUtils.release(jedis);


      
      
        218
      
      
        return
      
       !StringUtil.isBlank(online);
      
        //
      
      
        不为空就代表已经找到数据了,也就是上线了
      
      
        219
      
      
            }


      
      
        220
      
      
        /**
      
      
        221
      
      
             * 获取指定页面在线人数总数


      
      
        222
      
      
        */
      
      
        223
      
      
        public
      
      
        static
      
      
        int
      
      
         broadcastCount() {


      
      
        224
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        225
      
               Set online = jedis.keys(VID_PREFIX+"*"
      
        );


      
      
        226
      
      
                RedisPoolUtils.release(jedis);


      
      
        227
      
      
        return
      
      
         online.size();


      
      
        228
      
      
            }


      
      
        229
      
      
        /**
      
      
        230
      
      
             * 


      
      
        231
      
      
             * @Title: isOnline


      
      
        232
      
      
             * @Description: 指定账号是否登陆


      
      
        233
      
      
             * 
      
      
        @param
      
      
        @param
      
      
         sessionId


      
      
        234
      
      
             * 
      
      
        @param
      
      
        @return
      
      
        235
      
      
             * 
      
      
        @return
      
      
         boolean 


      
      
        236
      
      
             * 
      
      
        @throws
      
      
        237
      
      
        */
      
      
        238
      
      
        public
      
      
        static
      
      
        boolean
      
      
         isOnline(String uid){


      
      
        239
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        240
      
      
        boolean
      
       isLogin = jedis.exists(UID_PREFIX+
      
        uid);


      
      
        241
      
      
                RedisPoolUtils.release(jedis);


      
      
        242
      
      
        return
      
      
         isLogin;


      
      
        243
      
      
            }


      
      
        244
      
      
        public
      
      
        static
      
      
        boolean
      
      
         isOnline(String uid,String sid){


      
      
        245
      
               Jedis jedis =
      
         RedisPoolUtils.getJedis();


      
      
        246
      
               String loginSid = jedis.get(UID_PREFIX+
      
        uid);


      
      
        247
      
      
                RedisPoolUtils.release(jedis);


      
      
        248
      
      
        return
      
      
         sid.equals(loginSid);


      
      
        249
      
      
            }


      
      
        250
      
       }
    

  由于在线状态是记录在Redis中的,并不单纯依靠Session的过期机制来实现,所以需要通过拦截器在每次发送请求的时候去更新Redis中相应的缓存过期时间来更新用户的在线状态。

登陆、退出操作与单机版相似,强制下线需要配合拦截器实现,当用户下次访问的时候,自己来校验自己的状态是否为已经下线,不再由服务器控制。

配合拦截器实现在线状态维持与强制登陆(使其他地方登陆了该账户的用户下线)功能:

      
         1
      
      
          ...


      
      
         2
      
      
        if
      
      (uid != 
      
        null
      
      ){
      
        //
      
      
        已登录
      
      
         3
      
      
        if
      
      (!
      
        OnlineUtils.isOnline(uid, session.getId())){


      
      
         4
      
      
                    session.invalidate();


      
      
         5
      
      
        return
      
      
         ai.invoke();


      
      
         6
      
               }
      
        else
      
      
        {


      
      
         7
      
                   OnlineUtils.login(session.getId(), (ClientUser)session.getAttribute("clientUser"
      
        ));


      
      
         8
      
      
        //
      
      
        刷新缓存
      
      
         9
      
      
                }


      
      
        10
      
      
            }


      
      
        11
      
           ...
    

注:Redis在线列表工具类中的部分代码是后来需要实现限制同时访问指定页面浏览人数功能而添加的,同样基于Redis实现,前端由Ajax轮询来更新用户停留页面的状态。

附录:

Redis连接池配置文件:

      ###redis##config########

#redis服务器ip # 

#redis.ip=
      
        localhost


      
      #redis服务器端口号#
      
        

redis
      
      .port=6379

###jedis##pool##config###

#jedis的最大分配对象#
      
        

jedis
      
      .pool.maxActive=1024

#jedis最大保存idel状态对象数 #
      
        

jedis
      
      .pool.maxIdle=200

#jedis池没有对象返回时,最大等待时间 #
      
        

jedis
      
      .pool.
      
        maxWait
      
      =1000

#jedis调用borrowObject方法时,是否进行有效检查#
      
        

jedis
      
      .pool.testOnBorrow=
      
        true


      
      #jedis调用returnObject方法时,是否进行有效检查 #
      
        

jedis
      
      .pool.testOnReturn=true
    

 

基于Redis的在线用户列表解决方案


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论