看过很多文章讲述redis热点key的发现以及处理措施
1.客户端
在客户端get的时候进行统计
2.美团TMC框架
重写redis源代码进行统计
3.预先知道的热点key
比如我在一个大促的活动中,哪些key是热点的应该知道的吧
为了避免所有的请求都砸到redis上,一般处理方式:启动二级缓存,比如ehcache
讲下个人思路,当key请求次数达到一定数量时,我们把它放到ehcache缓存中,以后该key的请求从缓存里面读取
@Component public class RedisUtil { ConcurrentHashMap<String, Integer> concurrentHashMap = new ConcurrentHashMap(); private static final String CACHE_NAME = "cache"; @Resource private RedisTemplate redisTemplate; public String getRedis(String key) { if (concurrentHashMap.get(key) != null) { concurrentHashMap.put(key, concurrentHashMap.get(key) + 1); if(concurrentHashMap.get(key)>=1000){ return getCache(key); } } else { concurrentHashMap.put(key, 1); } return (String) redisTemplate.opsForValue().get(key); } @Cacheable(value = CACHE_NAME, key = "redis+'_'+#key") public String getCache(String key){ System.out.println("使用Cache"); return (String) redisTemplate.opsForValue().get(key); } }代码如上图,当请求超过1000个的时候缓存起来
控制器
@RestController public class RedisController { @Resource private RedisTemplate redisTemplate; @Autowired private RedisUtil redisUtil; @RequestMapping("/redis") public void getRedis() throws InterruptedException { long time=System.nanoTime(); String key = "dajitui"; redisTemplate.opsForValue().set(key, "0"); CountDownLatch countDownLatch = new CountDownLatch(5000); for (int i = 0; i < 30000; i++) { new Thread(new Runnable() { @Override public void run() { countDownLatch.countDown(); System.out.println(redisUtil.getRedis(key)); } }).start(); } countDownLatch.await(); long time1=System.nanoTime(); System.out.println("耗时"+(time1-time)); } @RequestMapping("/redis1") public void getRedis1() throws InterruptedException { long time=System.nanoTime(); String key = "dajitui"; redisTemplate.opsForValue().set(key, "0"); CountDownLatch countDownLatch = new CountDownLatch(5000); for (int i = 0; i < 30000; i++) { new Thread(new Runnable() { @Override public void run() { countDownLatch.countDown(); System.out.println(redisTemplate.opsForValue().get(key)); } }).start(); } countDownLatch.await(); long time1=System.nanoTime(); System.out.println("耗时"+(time1-time)); } }http://localhost:8080/redis1是没有使用二级缓存的,http://localhost:8080/redis使用了二级缓存
运行结果发现,没有用缓存的耗时6秒多,使用缓存的耗时2秒多
源码下载