为了使reids配置更优,在使用redis的时候需要注意一些规范,首先要注意,redis和任何cache都不适合写操作比较多的场景,只时候读多写少的场景。
定义key的时候,加上前缀,防止不同业务的key冲突
trade:order:cloth:Tshirt:10011
不要再key里面加特殊字符,尽量的让key简洁,不要让key占太多空间
user:{uid}:friends:messages:{mid} ==> u:{uid}:fri:msg:{mid}
不要大量使用的bigkey,就是内容比较大的key。
bigkey可能导致的问题:
- 导致reids阻塞
- 网络拥塞,公司卖的网络的宽带是又限制的,大量的数在网络上传输会导致带宽被打满了,其他的请求进不来也出不去
- 过期删除时导致阻塞
Value的设计
String <= 10kb
集合元素<=5000
非字符串的bigkey不要使用del要使用hcan/sscan/zscan等渐进式删除。同时要避免一个很大的集合设置的有效期到期时自动触发删除导致的阻塞。
如何优化bigkey:
1. 拆
list1, list2, list3 ... list N
2. 使用合适的数据类型
利用hmset 而不是每个都设置一遍
3. 控制key的生命周期,建议使用expire设置过期时间,不要什么都放到redis里面来
4. 避免使用hgetall,lrange,smembers,zrange,sinter,又遍历需求时用hscan,sscan,zscan代替
5. 禁用命令,keys,flushall,flushdb,等命令,可以使用redis的rename机制来禁用命令
6. 使用批量操作提高效率
mget,mset,pipeline等等
- pipelline 是非原子操作
- pipleline可以打包不同的命令
- pipelline需要客户端和服务端的同时支持
7. Redis的事务功能较弱,可以用lua代替
8. Redis内核是串行的,所以不同的业务应该用不同的redis,不要所有业务都丢到一个redis中去
9. 使用带有连接池的客户端, 提高效率
连接池的使用实例:
JedisPoolConfig jedisPoolConfig =newJedisPoolConfig();
jedisPoolConfig.setMaxTotal(5);
jedisPoolConfig.setMaxIdle(2);
jedisPoolConfig.setTestOnBorrow(true);
JedisPool jedisPool =newJedisPool(jedisPoolConfig,"192.168.0.60",6379,3000,null);
Jedis jedis =null;
try{
jedis = jedisPool.getResource();
//具体的命令
jedis.executeCommand()
}catch(Exception e){
logger.error("op key {} error: "+ e.getMessage(), key, e);
}finally{
//注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。
if(jedis !=null)
jedis.close();
}
连接池优化建议:
MaxTotal 最大链接数 - 最多允许的链接数
maxindle最大空闲数 - 当空闲时,留多少不回收
并发量非常高的时候建议设置MaxTotal=MaxIdle即链接创建后就不回收了,一直保持最大数量。
redis预热链接的代码:
List<Jedis> minIdleJedisList =newArrayList<Jedis>(jedisPoolConfig.getMinIdle());
for(int i =0; i < jedisPoolConfig.getMinIdle(); i++){
Jedis jedis =null;
try{
jedis = pool.getResource();
minIdleJedisList.add(jedis);
jedis.ping();
}catch(Exception e){
logger.error(e.getMessage(), e);
}finally{
//注意,这里不能马上close将连接还回连接池,否则最后连接池里只会建立1个连接。。
//jedis.close();
}
}
//统一将预热的连接还回连接池
for(int i =0; i < jedisPoolConfig.getMinIdle(); i++){
Jedis jedis =null;
try{
jedis = minIdleJedisList.get(i);
//将连接归还回连接池
jedis.close();
}catch(Exception e){
logger.error(e.getMessage(), e);
}finally{
}
}//总之,要根据实际系统的QPS和调用redis客户端的规模整体评估每个节点所使用的连接池大小。
对于Reids过期的三种清除策略:
1. 被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key
2. 主动删除:Redis会定期主动淘汰一批已过期的key
3. 当前已用内存超过maxmemory限定时,触发主动清理策略
过期key的淘汰策略
一, 针对配置了过期时间的策略:
1. volatile-ttl:key越早过期的越先被删除。
2. volatile-random:进行随机删除。
3. volatile-lru:会使用 LRU 算法筛选设置了过期时间的键值对删除。
4. volatile-lfu:会使用 LFU 算法筛选设置了过期时间的键值对删除。
二,针对所有的key
5. allkeys-random:从所有键值对中随机选择并删除数据。
6. allkeys-lru:使用 LRU 算法在所有数据中进行筛选删除。
7. allkeys-lfu:使用 LFU 算法在所有数据中进行筛选删除。
8. noeviction:不会剔除任何数据,拒绝所有写入操作并返回客户端错误信息"(error)OOM command not allowed when used memory",此时Redis只响应读操作