Redis将Session 集中管理

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

<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="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxIdle" value="${redis.pool.maxIdle}" />
		<property name="maxTotal" value="${redis.pool.maxTotal}" />
		<property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}" />
		<property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />
	</bean>

	<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

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<Boolean>() {
				public Boolean doInRedis(RedisConnection connection)
						throws DataAccessException {
					/*这里是存入时,序列化操作,可选
					 * @SuppressWarnings("unchecked")
					 * RedisSerializer<onLineUserInfo> valueSerializer =
					 * (RedisSerializer<onLineUserInfo>) 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<Boolean>() {
				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 即你需要放入Session的登陆对象,可以自行编辑

public class onLineUserInfo implements Serializable{

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

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

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

转载于:https://my.oschina.net/yujuncai/blog/618685

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值