引子:
1、命中率的概念:
客户端获取缓存数据的时候会出现命中率问题,那么命中率是什么那,通俗点说,
命中 (hit)就是查询到了缓存结果,没有命中(miss)就是没有查询到缓存结果。
用 命中 (hit)数量除( hit 加 没有命中miss 的 总数),得出的就是命中率。
公式如下:hits /( hits + miss)= 命中率 % 。2、在redis 如何查看命中率那?
我们可以使用redis-cli 连接服务端后,执行 info 命令查看。
127.0.0.1:6379> info返回redis-server 信息,其中包括了 keyspace_hits 和 keyspace_misses,在redis info 信息中有这样几个参数,我们先重点说一下:
keyspace_hits: 查询命中数。
keyspace_misses:查询未命中数。
expired_keys: 已过期 Key 个数。
evicted_keys: 由于 maxmemory 限制,而被回收内存的 key 的总数。
当内存使用达到设置的最大阀值 maxmemory 时,Redis 则会根据设置的 key 逐出策略,来选择性地删除一些 key 来保护内存不溢出。
#### evicted_keys 面试的时候经常有人问####
根据状态信息,redis的命中率计算就表示为:
keyspace_hits / ( keyspace_hits + keyspace_misses ) = 查询命中率。redis-server 启动的时候,hits 和 misses 都是 0。
当客户端请求的key不存在的时候,就会出现misses,这时候 misses ++ 执行。
keyspace_hits:0 keyspace_misses:0当然,你也可以使用 telnet 连接 redis-server ,telnet 129.0.0.139 6379,然后使用info 命令查看redis-server 状态及命中率指标。
一、缓存流程
当我们部署一个新系统或重启一个系统后,会将系统相关的数据写入到 redis 中,以提高系统的响应速度。
客户端在请求数据的时候首先访问redis获取数据,如果redis中有这条数据,命中:直接返回,redis keyspace_hits++ ;
如果redis中没有这条数据,没有命中:keyspace_misses++ ,这时候就要请求后端的数据源读取数据,并写入到redis中,这就是一个操作缓存的基本流程。
二、为什么会出现命中率低的问题那?
1、缓存的时效性直接影响缓存数据(key)过期时间设定,以及数据更新回填的策略。
2、redis 中 maxmemory 的限制,可以引发数据缓存的淘汰、逐出策略。
3、缓存数据结构的设计不合理,缓存内容的耦合的过高,导致缓存数据规则设计不合理。
三、如何提高命中率?
1、合理规划缓存时间、更新回填策略。对于时效性要求不高的数据,缓存的命中率越高,反之,命中率越低。缓存数据的有效期太短也会造成数据缓存的命中率降低。
2、单机部署容易出现性能瓶颈,建议使用分布式或redis cluster,既能保证redis 性能和稳定性,又能保证数据的安全。
3、应合理规划缓存数据,将缓存数据颗粒度降到最小,一般来说,对象缓存是缓存颗粒度最小的。
4、新系统上线或重启某个系统后要即使预热缓存(提前写入缓存数据),提高缓存效率。
5、除了以上问题,还有一个情况比较特殊,就是当redis 中缓存数据过期了,但并没有因为过期删除这个key,导致命中率问题。这个问题和我们上篇文章中描述那个并发产生过期的key没有删除应该是一样的,这个问题可以通过调整代码结构或优化redis配置来提高精度。
修改 redis.conf :
vim /data/redis/etc修改配置 hz 属性可以提高主动式处理机制,类似java gc ,可以删除过期的key和关闭超时redis链接。
hz属性默认值 10,但是设置这个值会提高cpu资源来提高计算次数和精度,hz 的取值范围是 1-500,建议不要超过 100,我这边测试过这个属性,超过100 时负载明显升高。
最后说一下,redi增加了一个dynamic-hz参数,默认开启动态hz,使得在客户端连接非常多时,自适应调整hz参数,临时增加hz参数,用于自适应调整的值,平衡空闲CPU的使用率和响应能力;
可以写一个脚本,测了一下1000w,过期时间为600s 的数据:
准备一个1000w.sh 脚本,写入有 1000w数据,生成一个文件 1000w.txt ,数据格式:
setex key:1 600 value:1编写脚本,1000w.sh ,循环写入 1000w 行数据:
#!/bin/bash var1="setex" var2=" key:" var3=" 600" var4=" val:" var5="\n" for((i=1;i<=1000000;i++)) do var6+=${var1}${var2}$i${var3}${var4}$i${var5} echo $i done echo -e $var6 >> 1000w.txt执行这个脚本,生成文档 1000w.txt
sh 1000w.txt我这个虚拟机大概执行了2分钟左右,生成了这个文档,执行的时候卡住了,就顺手查看了虚拟机负载情况,还凑合,哈。
并执行导入命令:
命令格式:
cat 1000w.txt | redis-cli -h 129.0.0.139 -p 6379 [-a "password"] -n 0 --pipe实际执行:
cat 1000w.txt | redis-cli -n 0 --pipe1000w 数据大概2分钟多一点写入完毕。
dbszie 查询一下(接了个电话,有的数据就过期了):
数据导进去了,想怎么测试,那就开始吧。
happy ending...