• 1
  • 2
  • 3
  • 4
  • 5
mssql数据库问题 首 页  »  帮助中心  »  数据库  »  mssql数据库问题
Redis将Session 集中管理的说明
发布日期:2016-4-24 13:4:27

  在分布式系统中.前提是分布式或者集群环境,常常会需要多个系统中,保持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引入

  org.springframework.data

  spring-data-redis

  1.5.2.RELEASE

  redis.clients

  jedis

  2.6.2

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

  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" />

  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 redisTemplate;

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

  private String getJointName(String sid) {

  String key = RedisExpire.ONLINEUSER + ":" + sid;//":"为文件夹形式

  return key;

  }

  准备常量

  public class RedisExpire {

  /**

  * Session 超时时间为30分钟

  */

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

  public final static String ONLINEUSER= "OnLineUser";

  }

  然后就可以开始操作,如在登陆时写入redis并设置Session时长.

  /**

  * 添加在线用户

  *

  * @param sid 生成对用户的唯一id.即Session中的sessionid

  * 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() {

  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 即你需要放入Session的登陆对象,可以自行编辑

  public class onLineUserInfo implements Serializable{

  private String name;// 用户名字

  ..........

  }

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

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