发表于: 2017-11-22 23:09:35

2 610


今天做的事情:


                测试redis;


             

static String constr = "101.201.65.0" ;
public static Jedis getRedis(){
Jedis jedis = new Jedis(constr) ;
jedis.auth("123456");
return jedis;
}

public static void main(String[] args) {
Jedis j = Test.getRedis();
String output;
j.set("hello", "world");
output = j.get("hello");
System.out.println(output);
}
}


              运行无错误。


              思路: 使用jedis提供的缓存功能,在JDBC前面加上Redis,先从Redis中查询数据,如果Redis中没有该数据,就从数据库中查询,再把查询到的结果放入Redis中,下次再请求该接口的时候,就直接返回Redis中的数据。


             序列化和反序列化的使用

    接口查询到的数据是一个List集合,把集合对象通过序列化为字符串,放入到Redis中。使用的时候取出Redis中的数据,通过反序列化为对象使用。


             注意:是将从数据库查出来的数据序列化成字符串放进redis,显示回页面时,redis将字符串反序列化回对象。


            测试redis代码:

             service层

public List ioslist() {
Jedis resource = jedis.getResource();

List ioslist = null;
if(resource.get("ioslist".getBytes())!=null){
//redis服务器本身支持二进制安全的类型,所以可以把一个java对象序列化后存储到redis中,也可以反序列化得放入redis中
      //反序列化为对象
       List unserialize = (List) SerializeUtil.unserialize(resource.get("ioslist".getBytes()));
System.out.println("输出redis反序列化后的缓存ioslist:"+unserialize);
return unserialize;
}else{
//在数据库查询数据 返回 再放进缓存中
        ioslist = daoI.ioslist();
if(ioslist!=null){
//将对象序列化放进redis
           resource.set("ioslist".getBytes(), SerializeUtil.serialize(ioslist));
System.out.println("从数据库查的redis的缓存数据");
}
}

return ioslist;
}

           

            


              已经成功将从数据库查询的数据放进redis。下一步,测试数据库更新,缓存是否更新,更改代码。


             

public List ioslist() {
Jedis resource = jedis.getResource();

List ioslist = daoI.ioslist();

if(resource.get("ioslist".getBytes())!=null){
//redis服务器本身支持二进制安全的类型,所以可以把一个java对象序列化后存储到redis中,也可以反序列化得放入redis中
      //反序列化为对象
       List unserialize = (List) SerializeUtil.unserialize(resource.get("ioslist".getBytes()));
//  SerializeUtil.serialize(resource.get("ioslist".getBytes()));
       //如果redis的数据与从数据库查出最新的数据一样   resource.get("ioslist".getBytes(),SerializeUtil.serialize(ioslist)))
       if(resource.get("ioslist".getBytes()).equals(unserialize)){
System.out.println("输出原redis反序列化后的缓存ioslist:"+unserialize);
return unserialize;
}else{
//否则 将最新的序列化redis,输出
           List unserialize1 = (List) SerializeUtil.unserialize(resource.getSet("ioslist".getBytes(), SerializeUtil.serialize(ioslist)));
System.out.println("输出更新redis反序列化后的缓存ioslist:");
return unserialize1;
}

}else{
//在数据库查询数据 返回 再放进缓存中
        if(ioslist!=null){
//将对象序列化放进redis
           resource.set("ioslist".getBytes(), SerializeUtil.serialize(ioslist));
System.out.println("从数据库查的redis的缓存数据");
}
}

return ioslist;
}

              控制台信息:


           


              模拟数据穿透缓存的情况 ,看一下这个。            

         什么是缓存穿透?

一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。如果key对应的value是一定不存在的,并且对该key并发请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。 

                                 

有一个比较巧妙的作法是,可以将这个不存在的key预先设定一个值。
比如,"key" , “&&”。
在返回这个&&值的时候,我们的应用就可以认为这是不存在的key,那我们的应用就可以决定是否继续等待继续访问,还是放弃掉这次操作。如果继续等待访问,过一个时间轮询点后,再次请求这个key,如果取到的值不再是&&,则可以认为这时候key有值了,从而避免了透传到数据库,从而把大量的类似请求挡在了缓存之中。        

         

总结来看:

1、缓存穿透:查询一个必然不存在的数据。比如文章表,查询一个不存在的id,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成影响。

2、缓存失效:如果缓存集中在一段时间内失效,DB的压力凸显。这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。
当发生大量的缓存穿透,例如对某个失效的缓存的大并发访问就造成了缓存雪崩。

                




            1000 线程 


    




         

遇到的问题:


            暂无




收获:


              了解redis缓存与memcached区别与应用。










返回列表 返回列表
评论

    分享到