UDN-企业互联网技术人气社区

板块导航

浏览  : 1509
回复  : 0

[讨论交流] Redis将Session 集中管理

[复制链接]
葡萄柚的头像 楼主
发表于 2016-3-19 08:00:00 | 显示全部楼层 |阅读模式
  在分布式系统中.前提是分布式或者集群环境,常常需要多个系统中,保持Session . nginx可以配置IP的hash,实现每次都访问同一台应用容器,从而不需要共享Session ,也有tomcat的复制. 虽然tomcat等容器可以实现Session 的复制,但是在tomcat的数量过多时,复制的延迟和性能的损失 将因为tomcat的数量直线上升. 这里可以用redis简单的将Session 集中管理.线上环境将redis高可用即可.

  Java对Redis的操作可以用 Jedis.spring-data-redis封装Jedis,更加易用 本文采用 spring data redis作为Redis的连接工具. 采用Sping管理. Maven pom.xml引入
  1. <dependency>
  2.             <groupId>org.springframework.data</groupId>
  3.             <artifactId>spring-data-redis</artifactId>
  4.             <version>1.5.2.RELEASE</version>
  5.         </dependency>
  6.     <dependency>
  7.             <groupId>redis.clients</groupId>
  8.             <artifactId>jedis</artifactId>
  9.             <version>2.6.2</version>
  10.         </dependency>
复制代码

  spring-redis.xml 配置 Redis的连接池和连接
  1. <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
  2.         <property name="maxIdle" value="${redis.pool.maxIdle}" />
  3.         <property name="maxTotal" value="${redis.pool.maxTotal}" />
  4.         <property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}" />
  5.         <property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />
  6.     </bean>

  7.     <bean id="jedisConnFactory"
  8.         class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
  9.         p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"
  10.         p:use-pool="true" p:pool-config-ref="poolConfig" />

  11.     <!-- <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
  12.         <property name="connectionFactory" ref="connectionFactory" />
  13.     </bean> -->
  14.     <!-- redis template definition -->
  15.     <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
  16.         p:connection-factory-ref="jedisConnFactory" />
复制代码

  redis.properties 连接的配置肯定是需要的
  1. redis.host=x.x.x.x
  2. redis.port=6379
  3. redis.pass=
  4. redis.maxWait=30000
  5. redis.pool.maxTotal=1024
  6. redis.pool.maxIdle=200
  7. redis.pool.timeBetweenEvictionRunsMillis=30000
  8. redis.pool.testOnBorrow=true
复制代码

  在需要使用的类中注入
  1.         @Resource
  2.     protected RedisTemplate<Serializable, Serializable> redisTemplate;
复制代码

  组装一下key,统一设置前缀,可以方便的管理key
  1. private String getJointName(String sid) {
  2.         String key = RedisExpire.ONLINEUSER + ":" + sid;//":"为文件夹形式
  3.         return key;
  4.     }
复制代码

  准备常量
  1. public class RedisExpire {

  2.     /**
  3.      * Session 超时时间为30分钟
  4.      */

  5.     public final static Long  ThirtyMinuteSecend= 30*60L;//秒


  6.     public final static String  ONLINEUSER= "OnLineUser";


  7. }
复制代码

  然后即可开始操作...如在登陆时写入redis并设置Session时长.
  1. /**
  2.      * 添加在线用户
  3.      *
  4.      * @param sid 生成对用户的唯一id.即Session中的sessionid
  5.      *            source 为来源为后续app预留
  6.      * @param user
  7.      * @return
  8.      * @throws Exception
  9.      */
  10. public boolean addOnLinuUser(final String sid, final onLineUserInfo user,
  11.             final String source) throws Exception {
  12.         if (user != null && sid.trim().length() > 0) {
  13.             final String key;
  14.             key = getJointName(sid);
  15.             Boolean falg = redisTemplate.execute(new RedisCallback<Boolean>() {
  16.                 public Boolean doInRedis(RedisConnection connection)
  17.                         throws DataAccessException {
  18.                     /*这里是存入时,序列换操作,可选
  19.                      * @SuppressWarnings("unchecked")
  20.                      * RedisSerializer<onLineUserInfo> valueSerializer =
  21.                      * (RedisSerializer<onLineUserInfo>) redisTemplate
  22.                      * .getValueSerializer();
  23.                      */
  24.                     connection.select(2);//切换redis的DB可以不需要,redis默认配置为0-15共16个库,可以通过这行代码实现切换
  25.                     connection.setEx(key.getBytes(),
  26.                             RedisExpire.ThirtyMinuteSecend,
  27.                             stringToByte(JSONObject.toJSONString(user)));//序列化采用了fastjson
  28.                     return true;
  29.                 }
  30.             });

  31.             return falg;
  32.         }
  33.         return false;
  34.     }
复制代码

  同理删除和获取
  1. /**
  2.      * 移除在线登陆用户
  3.      *
  4.      * @param sid
  5.      *            source 为来源为后续app预留
  6.      * @return
  7.      * @throws Exception
  8.      */
  9.     public boolean removeOnLinuUser(final String sid, final String source)
  10.             throws Exception {
  11.         if (sid != null) {
  12.             final String key;
  13.             key = getJointName(sid);
  14.             Boolean falg = redisTemplate.execute(new RedisCallback<Boolean>() {
  15.                 public Boolean doInRedis(RedisConnection connection)
  16.                         throws DataAccessException {
  17.                     connection.select(2);
  18.                     Long del = connection.del(key.getBytes());
  19.                     if (del == 1) {
  20.                         return true;
  21.                     } else {
  22.                         return false;
  23.                     }

  24.                 }
  25.             });

  26.             return falg;
  27.         }
  28.         return false;
  29.     }



  30.     /**
  31.      * 获取在线用户信息
  32.      *
  33.      * @param sid
  34.      *            source 为来源为后续app预留
  35.      * @return
  36.      * @throws Exception
  37.      */
  38.     public onLineUserInfo getOnLinuUser(String sid, final String source)
  39.             throws Exception {
  40.         final String key;
  41.         key = getJointName(sid);
  42.         onLineUserInfo userInfo = redisTemplate
  43.                 .execute(new RedisCallback<onLineUserInfo>() {
  44.                     public onLineUserInfo doInRedis(RedisConnection connection)
  45.                             throws DataAccessException {
  46.                         connection.select(2);
  47.                         byte[] bs = connection.get(key.getBytes());
  48.                         String byteToString = byteToString(bs);
  49.                         onLineUserInfo userinfo = JSONObject.parseObject(
  50.                                 byteToString, onLineUserInfo.class);
  51.                         /*if (userinfo != null) {
  52.                             // 如果用户已登录,则增加在线时间
  53.                             connection.expire(key.getBytes(),
  54.                                     RedisExpire.ThirtyMinuteSecend);

  55.                         }*/
  56.                         return userinfo;
  57.                     }
  58.                 });

  59.         return userInfo;
  60.     }
  61. }
复制代码

  文中的 onLineUserInfo 即你需要放入Session的登陆对象,可以自行编辑
  1. public class onLineUserInfo implements Serializable{



  2.     private String name;// 用户名字
  3.             ..........
  4. }
复制代码

  不管存入cookie还是重写url...系统请求是需要带上sid即可.

原文作者:parkjun 来源:http://my.oschina.net/yujuncai/blog/618685

相关帖子

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部