6.缓存雪崩应对
缓存的层级位于客户端和存储层之间,能够有效的降低存储层的压力,但缓存可能存在不可用的情况,如何应对这种情形?
首先自然是降低缓存层的宕机几率,有条件可以使用Redis Sentinel和Redis Cluster。
其次隔离缓存和存储层的数据获取接口,防止缓存的宕机影响存储层的数据获取。
最后在项目上线前演练缓存宕机的情形,在此基础上做一预案设定。

好的架构和代码都需要有一个好的设计,如果设计阶段就出了偏差,那么在编程阶段无论怎么调整都难以弥补。
使用阶段
我们从数据存储和数据获取两个方面来说明开发时的注意事项。
1.数据存储
因为内存空间的局限性,注定了能存储的数据量有限,如何在有限的空间内存储更多的数据信息是我们应该关注的。java多线程死锁Redis内存储的都是键值对,那么如何减小键值对所占据的内存空间就是空间优化的本质。
在能清晰表达业务含义的基础上尽可能缩减Key的字符长度,比如一个键是user:{id}:logintime ,可以使用业务属性的简写来u:{id}:lgt,只要能清晰表达业务意义,使用简写形式是有其必要性的。
在不影响使用的情况下,缩减Value的数据大小。如果Value是较大的数据信息,比如图片,大文本等,可以使用压缩工具压缩过后再存入Redis;如果Value是对象序列化或者gson信息,可以考虑去除非必要的业务属性。
减少键值对的数量,对于大量的String类型的小对象,可以尝试使用Hash的形式组合他们,在Hash对象内Field数量少于1000,且Value的字符长度小于40时,内部使用ziplist的编码形式,能够极大的降低小对象占据的内存空间。
Redis内维护了一个[0-9999]的整数对象池,类似Java内的运行时常量池,只创建一个常量,使用时都去引用这个常量,所以当存储的value是这个范围内的数字时均是引用向都一个内存地址,所以能够降低一些内存空间耗费。但是共享对象池和maxmemory+LRU的内存回收策略冲突,因为共享Value对象的lru值也共享,难以通过lru知道哪个Key的最后引用时间,所以永远也不能回收内存。
如果多次数据操作要求原子性,可使用Multi来实现Redis的事务。
2.数据查询
Redis是一种,和其他一样,操作时也需要有连接对象,连接对象的创建和销毁也需要耗费资源,复用连接对象很有必要,所以推荐使用连接池来管理连接。Redis数据存储在内存中,查询很快,但不代表连接也很快。一次Redis查询可能IO部分占据了请求时间的绝大部分比例,缩短IO时间是开发过程中很需要注意的一点。
对于一个业务内的多次查询,考虑使用Pipeline,将多次查询合并为一次查询,命令会被执行多次,但是只有一个IO传输,能够有效的提高响应速度。
对于多次String类型的查询,使用mget,将多次请求合并为一次,同时命令和会被合并为一次,能有效提高响应速度,对于Hash内多个Field查询,使用hmget,起到和mget同样的效果。java多线程死锁
Redis是单线程执行的,也就是说同一时间只能执行一条命令,如果一条命令执行的时间较长,其他线程在此期间均会被阻塞,所以在操作Redis时要注意操作指令的涉及的数据量,尽量降低单次操作的执行时间。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-63783-2.html