在登陆服务中,如果将数据全部存储到tomcat中,当存在多个tomcat的时候,数据是无法同步的,这就导致了数据的共享问题:

1、每台服务器中都有完整的一份session数据,服务器压力过大。
2、session拷贝数据时,可能会出现延迟
解决办法就是采用redis, redis完美的符合了以下的要求:
1.同步性
2.基于内存,高效率
3.满足key-value结构
同时注意,redis的string与hashset的区别

优化后的流程如下图
 首先我们很容易想到,将用户的登录手机号作为key,而后对于存储到redis中的用户的凭证,我们选择生成随机的token,使用token是为了不暴露用户的手机号(隐私处理).同时我们还要注意,session是能在tomcat中自动同步的,但是token是做不到的,我们需要手动同步token.而token是怎么做到帮助我们识别用户的登录状态的呢,答案就是在每次的服务器回传的过程中,都会在头部添加一个token字段.
首先我们很容易想到,将用户的登录手机号作为key,而后对于存储到redis中的用户的凭证,我们选择生成随机的token,使用token是为了不暴露用户的手机号(隐私处理).同时我们还要注意,session是能在tomcat中自动同步的,但是token是做不到的,我们需要手动同步token.而token是怎么做到帮助我们识别用户的登录状态的呢,答案就是在每次的服务器回传的过程中,都会在头部添加一个token字段.




指的是客户端在请求数据的过程中,缓存和数据库中都没有要请求的数据,这样缓存永远都不会生效,请求都会打到数据库.这样就导致数据库在频繁的查找数据.服务器性能大幅度下降.
解决办法:1.缓存空对象: 对于同一个请求的资源,比如请求不存在的id= -1的资源,在缓存中添加id=-1的键,将其值设置为null,这样避免了同样的id导致的反复查找,下次查找id=-1的资源可以直接从缓存中查出来.
优点: 实现简单,维护方便
缺点: 一旦请求的资源变换,还是需要继续查找.
额外的内存消耗
可能造成短期的不一致(第一次请求的时候数据没有,缓存中设置为null,但是第二次请求时数据库中已经有了上次请求的id对应的数据,仍然会返回null)
2.添加布隆过滤器:它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
优点: 内存占用少,没有多余的key
缺点: 实现很复杂,并且存在误判的可能

private boolean tryLock(String key){
        Boolean ifAbsent = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 2, TimeUnit.MINUTES);
        //如果直接返回的话会自动拆箱,可能导致出现空值
        return BooleanUtil.isTrue(ifAbsent);
    }如果是redis中设置锁的语句就如下所示:
//给线程1设置锁
setnx lock thread1
//设置锁的时长
expire lock 5
//合并起来
//(nx指的是不存在的时候才可以设置)
set lock thread1 ex 5 nx
//删除锁
del lock 
使用lua脚本
lua脚本数组是从下标为1开始的



java代码的改造:
改造之前:
@Override
    public void deleteLock() {
        //判断redis中的锁和当前的锁是否是同一把
        //当前的锁
        String threadNameUUID = ID_NAME + Thread.currentThread().getId();
        //redis数据库里面的数据是否一致
        String redisLock = stringRedisTemplate.opsForValue().get(KEY_NAME + name);
        if(threadNameUUID.equals(redisLock)){
            stringRedisTemplate.delete(KEY_NAME + name);
        }
    }改造后:
unlock.lua在resources目录下
//初始化lua脚本
    private static final DefaultRedisScriptUNLOCK_LUA;
    
    //在static]块中初始化
    static{
        UNLOCK_LUA = new DefaultRedisScript<>();
        UNLOCK_LUA.setLocation(new ClassPathResource("unlock.lua"));
        UNLOCK_LUA.setResultType(Long.class);
    } unlock.lua
--比较线程标识与redis锁中的标识是否一致
if(redis.call('get', KEYS[1]) == ARGV[1])  then
    --释放锁
    return redis.call('del', KEYS[1])
end
return 0调用代码:
@Override
    public void deleteLock() {
        //调用lua脚本
        stringRedisTemplate.execute(
                UNLOCK_LUA,
                Collections.singletonList(KEY_NAME + name),
                ID_NAME + Thread.currentThread().getId());
    }下面举例:
Long execute = stringRedisTemplate.execute(SECKILL_SCRIPT,
        Collections.emptyList(),
          voucherId.toString(), id.toString());你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
文章标题:redis应用笔记-创新互联
网页网址:http://www.scyingshan.cn/article/pjphh.html

 建站
建站
 咨询
咨询 售后
售后
 建站咨询
建站咨询 
 