缓存在高平发和安全压力下的一些问题
是某一个热点key在高并发访问的情况下,突然失效,导致大量的并发大金mysql数据库的情况
是利用redis和mysql的机制(redis缓存一旦不存在,就访问mysql),直接让过缓存访问mysql,而制造的db请求压力
一般在代码中防止
解决: 为防止缓存穿透,将null或者空字符串设置给redis
缓存是采用了相同的过期时间,导致缓存在某一时刻同时全部失效,导致的db崩溃
解决:设计不同的缓存失效时间
分布式锁
穿透:利用不存在的key去攻击mysql数据库
雪崩:缓存中的很多key失效,导致数据库负载过重宕机
击穿:在正常的访问情况下,如果缓存失效,如果保护mysql,重启缓存的过程
使用redis数据库的分布式锁,解决mysql的访问压力问题
用完之后需要删除,不然别人不能访问。
错误自旋代码(B为孤儿线程)
正确自旋代码
问题1 如果在redis中的锁已经过期了,然后锁过期的那个请求又执行完毕,回来删锁,删除了其他线程的锁,怎么办?
问题2 如果碰巧在查询redis锁还没删除的时候,正在网络传输时,锁过期了,怎么办?
String script ="if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; jedis.eval(script, Collections.singletonList("lock"),Collections.singletonList(token));引入pom
<!-- https://mvnrepository.com/artifact/org.redisson/redisson --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.10.5</version> </dependency>配置
spring.redis.host=192.168.159.130 spring.redis.port=6379配置类
@Configuration public class GmallRedissonConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private String port; @Bean public RedissonClient redissonClient(){ Config config = new Config(); config.useSingleServer().setAddress("redis://"+host+":"+port); RedissonClient redisson = Redisson.create(config); return redisson; } }Redisson实现了juc的lock锁,并且可以在分布式的redis环境下使用
把需要的依赖添加的pom上
配置application.properties
# 服务端口 server.port=8082 # 日志级别 logging.level.root=info
RedissonController
package com.atguigu.gmallredisson.redissonTest; import com.atguigu.gmall.util.RedisUtil; import org.apache.commons.lang3.StringUtils; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import redis.clients.jedis.Jedis; @Controller public class RedissonController { @Autowired RedisUtil redisUtil; @Autowired RedissonClient redissonClient; @RequestMapping("testRedisson") @ResponseBody public String testRedisson(){ Jedis jedis = redisUtil.getJedis(); RLock lock = redissonClient.getLock("lock");// 声明锁 lock.lock();//上锁 try { String v = jedis.get("k"); if (StringUtils.isBlank(v)) { v = "1"; } System.out.println("->" + v); jedis.set("k", (Integer.parseInt(v) + 1) + ""); }finally { jedis.close(); lock.unlock();// 解锁 } return "success"; } }点击取消单一示例
https://www.apachehaus.com/cgi-bin/download.plx
修改服务的根目录路径:
查看443端口是否被占用
D:\ap\Apache24\bin>netstat -ano | findstr "443"没有被占用,启动httpd.exe
D:\ap\Apache24\bin>httpd.exeD:\apache24\bin>ab -c 200 -n 1000 http:nginx负载均衡/压力方法
测试:
D:\ap\Apache24\bin>ab -c 100 -n 10000 http://www.der-matech.com.cn/ public String testRedisson(){ Jedis jedis = redisUtil.getJedis(); RLock lock = redissonClient.getLock("lock");// 声明锁 lock.lock();//上锁 try { String v = jedis.get("k"); if (StringUtils.isBlank(v)) { v = "1"; } System.out.println("->" + v); jedis.set("k", (Integer.parseInt(v) + 1) + ""); }finally { jedis.close(); lock.unlock();// 解锁 } return "success"; }