转载

每日一博 | Redis 将 Session 集中管理

redis将sesstion集中管理

发表于20小时前(2016-02-22 12:51)   阅读( 401 ) | 评论( 0 0 人收藏此文章,

0

3月19日 深圳 OSC 源创会开始报名啦 —— React Native 实践 每日一博 | Redis 将 Session 集中管理

摘要

在分布式系统中.前提是分布式或者集群环境,常常需要多个系统中,保持sesstion. nginx可以配置IP的hash,实现每次都访问同一台应用容器,从而不需要共享sesstion,也有tomcat的复制. 虽然tomcat等容器可以实现sesstion的复制,但是在tomcat的数量过多时,复制的延迟和性能的损失 将因为tomcat的数量直线上升. 这里可以用redis简单的将sesstion集中管理.线上环境将redis高可用即可.

redis sesstion共享 jedis 分布式sesstion管理

Java对Redis的操作可以用 Jedis.spring-data-redis封装Jedis,更加易用 本文采用 spring data redis作为Redis的连接工具. 采用Sping管理. Maven pom.xml引入

` <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.5.2.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.6.2</version> </dependency>

`

spring-redis.xml 配置 Redis的连接池和连接 ```

<bean id="jedisConnFactory"     class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"     p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"     p:use-pool="true" p:pool-config-ref="poolConfig" />  <!-- <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">     <property name="connectionFactory" ref="connectionFactory" /> </bean> --> <!-- redis template definition --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"     p:connection-factory-ref="jedisConnFactory" />
` redis.properties 连接的配置肯定是需要的

` redis.host=x.x.x.x redis.port=6379 redis.pass= redis.maxWait=30000 redis.pool.maxTotal=1024 redis.pool.maxIdle=200 redis.pool.timeBetweenEvictionRunsMillis=30000 redis.pool.testOnBorrow=true

` 在需要使用的类中注入
@Resource protected RedisTemplate<Serializable, Serializable> redisTemplate; ``

组装一下key,统一设置前缀,可以方便的管理key

`<br /> private String getJointName(String sid) { String key = RedisExpire.ONLINEUSER + ":" + sid;//":"为文件夹形式 return key; }
准备常量 ``

public class RedisExpire {

/**  * sesstion超时时间为30分钟  */  public final static Long  ThirtyMinuteSecend= 30*60L;//秒   public final static String  ONLINEUSER= "OnLineUser";

} ```

然后即可开始操作...如在登陆时写入redis并设置seestion时长. ``` /* * 添加在线用户 * * @param sid 生成对用户的唯一id.即sesstion中的sesstionid * source 为来源为后续app预留 * @param user * @return * @throws Exception / public boolean addOnLinuUser(final String sid, final onLineUserInfo user, final String source) throws Exception { if (user != null && sid.trim().length() > 0) { final String key; key = getJointName(sid); Boolean falg = redisTemplate.execute(new RedisCallback () { public Boolean doInRedis(RedisConnection connection) throws DataAccessException { / 这里是存入时,序列换操作,可选 * @SuppressWarnings("unchecked") * RedisSerializer valueSerializer = * (RedisSerializer ) redisTemplate * .getValueSerializer(); / connection.select(2);//切换redis的DB可以不需要,redis默认配置为0-15共16个库,可以通过这行代码实现切换 connection.setEx(key.getBytes(), RedisExpire.ThirtyMinuteSecend, stringToByte(JSONObject.toJSONString(user)));//序列化采用了fastjson return true; } });

return falg;      }     return false; }

```

同理删除和获取

``` /* * 移除在线登陆用户 * * @param sid * source 为来源为后续app预留 * @return * @throws Exception / public boolean removeOnLinuUser(final String sid, final String source) throws Exception { if (sid != null) { final String key; key = getJointName(sid); Boolean falg = redisTemplate.execute(new RedisCallback () { public Boolean doInRedis(RedisConnection connection) throws DataAccessException { connection.select(2); Long del = connection.del(key.getBytes()); if (del == 1) { return true; } else { return false; }

}         });          return falg;     }     return false; }    /**  * 获取在线用户信息  *   * @param sid  *            source 为来源为后续app预留  * @return  * @throws Exception  */ public onLineUserInfo getOnLinuUser(String sid, final String source)         throws Exception {     final String key;     key = getJointName(sid);     onLineUserInfo userInfo = redisTemplate             .execute(new RedisCallback<onLineUserInfo>() {                 public onLineUserInfo doInRedis(RedisConnection connection)                         throws DataAccessException {                     connection.select(2);                     byte[] bs = connection.get(key.getBytes());                     String byteToString = byteToString(bs);                     onLineUserInfo userinfo = JSONObject.parseObject(                             byteToString, onLineUserInfo.class);                     /*if (userinfo != null) {                         // 如果用户已登录,则增加在线时间                         connection.expire(key.getBytes(),                                 RedisExpire.ThirtyMinuteSecend);                      }*/                     return userinfo;                 }             });      return userInfo; }

}

` 文中的 onLineUserInfo 即你需要放入sesstion的登陆对象,可以自行编辑

` public class onLineUserInfo implements Serializable{

private String name;// 用户名字         ..........

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

PS:有人问我为什么要用顶级的key,不用Hash,因为redis的key是有上限的.主要是只有顶级的key才能有过期时间一说.这里牵涉到Redis的一些内部特征,大家可以去查阅关于Redis的文章.

原文  http://my.oschina.net/yujuncai/blog/618685?fromerr=KR4xkwVQ
正文到此结束
Loading...