当前位置: 首页 > news >正文

网站结构模板成武网站建设

网站结构模板,成武网站建设,宁波网站推广工具,汽车行业网站建设比较目录 缓存穿透原理#xff1a; 缓存穿透一般有几种解决方案#xff1a; 1.缓存空值 2.使用锁 3.布隆过滤器 优缺点 布隆过滤器误判理解 布隆过滤器的简单使用流程 4.组合方案 那么当我们高并发的访问短链接或者人为的去穿透的时候呢#xff1f; 最近做项目遇到了缓…目录 缓存穿透原理 缓存穿透一般有几种解决方案 1.缓存空值 2.使用锁 3.布隆过滤器 优缺点 布隆过滤器误判理解 布隆过滤器的简单使用流程 4.组合方案 那么当我们高并发的访问短链接或者人为的去穿透的时候呢 最近做项目遇到了缓存的一些问题总结一下解决方法 缓存穿透原理 缓存穿透是指在缓存中查询一个一定不存在的数据由于缓存不命中导致请求直接访问数据库这将导致大量的请求打到数据库上可能会导致数据库压力过大。 具体原理 缓存穿透一般有几种解决方案 1.缓存空值 当查询结果为空时也将结果进行缓存但是设置一个较短的过期时间。这样在接下来的一段时间内如果再次请求相同的数据就可以直接从缓存中获取而不是再次访问数据库。 这种方式是比较简单的一种实现方案可以很好解决缓存穿透问题但是会存在一些弊端。那就是当短时间内存在大量恶意请求缓存系统会存在大量的内存占用。如果要解决这种海量恶意请求带来的内存占用问题需要搭配一套风控系统对用户请求缓存不存在数据进行统计进而封禁用户。整体设计就较为复杂不推荐使用。 2.使用锁 当请求发现缓存不存在时可以使用锁机制来避免多个相同的请求同时访问数据库只让一个请求去加载数据其他请求等待。 这种方式可以解决数据库压力过大问题如果会出现“误杀”现象那就是如果缓存中不存在但是数据库存在这种情况也会等待获取锁用户等待时间过长不推荐使用。 3.布隆过滤器 布隆过滤器是一种数据结构用于快速判断一个元素是否存在于一个集合中。具体来说布隆过滤器包含一个位数组和一组哈希函数。位数组的初始值全部置为 0。在插入一个元素时将该元素经过多个哈希函数映射到位数组上的多个位置并将这些位置的值置为 1。 在查询一个元素是否存在时会将该元素经过多个哈希函数映射到位数组上的多个位置如果所有位置的值都为 1则认为元素存在如果存在任一位置的值为 0则认为元素不存在。 优缺点 优点 高效地判断一个元素是否属于一个大规模集合。节省内存。 缺点 可能存在一定的误判。 布隆过滤器误判理解 布隆过滤器要设置初始容量。容量设置越大冲突几率越低。布隆过滤器会设置预期的误判值。 布隆过滤器的特点 查询是否存在如果返回存在可能数据是不存在的。查询是否存在如果返回不存在数据一定不存在。 布隆过滤器的简单使用流程 1.导入依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId /dependencydependencygroupIdorg.redisson/groupIdartifactIdredisson-spring-boot-starter/artifactId /dependency 2.配置Redis参数 spring:data:redis:host: 127.0.0.1port: 6379password: 123456 3.配置布隆过滤器 import org.redisson.api.RBloomFilter; import org.redisson.api.RedissonClient; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;/*** 布隆过滤器配置*/ Configuration public class RBloomFilterConfiguration {/*** 防止用户注册查询数据库的布隆过滤器*/Beanpublic RBloomFilterString userRegisterCachePenetrationBloomFilter(RedissonClient redissonClient) {RBloomFilterString cachePenetrationBloomFilter redissonClient.getBloomFilter(userRegisterCachePenetrationBloomFilter);cachePenetrationBloomFilter.tryInit(10000000L, 0.001);return cachePenetrationBloomFilter;} } 注意 tryInit 有两个核心参数 expectedInsertions预估布隆过滤器存储的元素长度。falseProbability运行的误判率。 错误率越低位数组越长布隆过滤器的内存占用越大。 错误率越低散列 Hash 函数越多计算耗时较长。 4.使用 4.1先注入private final RBloomFilterString userRegisterCachePenetrationBloomFilter; 4.2 userRegisterCachePenetrationBloomFilter.contains(xxx) 这个判断元素是否存在布隆过滤器 userRegisterCachePenetrationBloomFilter.add(xxx)  把元素加入布隆过滤器 4.组合方案 上面的这些方案或多或少都会有些问题应该用三者进行组合用来解决缓存穿透问题。如果说缓存不存在那么就通过布隆过滤器进行初步筛选然后判断是否存在缓存空值如果存在直接返回失败。如果不存在缓存空值使用锁机制避免多个相同请求同时访问数据库。最后如果请求数据库为空那么将为空的 Key 进行空对象值缓存。 1.当我们生成短链接的时候因为完整短链接是唯一的我们用布隆过滤器判断不存在才生成。 ​ ​private String generateSuffix(ShortLinkCreateReqDTO shortLinkCreateReqDTO) {int count 0;String shortUri;while (true) {if (count 10) {throw new ServiceException(短链接创造频繁请稍后再试);}//加上当前毫秒数减少重复可能shortUri HashUtil.hashToBase62(shortLinkCreateReqDTO.getOriginUrl() System.currentTimeMillis());if (!shortUriCreateCachePenetrationBloomFilter.contains(shortLinkCreateReqDTO.getDomain() / shortUri)) {break;}count;}return shortUri;}​​ 2.当上一步的布隆过滤器误判了明明存在但判断不存在。当我们插入短链接的时候去查一次数据库。如果存在数据证明布隆过滤器误判。 try {baseMapper.insert(shortLinkDO);shortLinkGotoMapper.insert(shortLinkGotoDO);// basemapper的插入 这个异常是 插入mysql 是 key重复了 因为布隆过滤器误判才会如此// 存在的 判断为 不存在} catch (DuplicateKeyException ex) {// TODO 布隆过滤器误判咋办// 那就去数据库查在判断一次ShortLinkDO ifExit this.baseMapper.selectOne(Wrappers.lambdaQuery(ShortLinkDO.class).eq(ShortLinkDO::getFullShortUrl, full_short_link));if (ifExit ! null) {log.warn(短链接{} 重复入库, full_short_link);throw new ServiceException(短链接存在了);}} 3.成功插入之后把完整短链接加入布隆过滤器。同时缓存预热key为原始连接 stringRedisTemplate.opsForValue().set(String.format(GOTO_SHORT_LINK_KEY,full_short_link),shortLinkCreateReqDTO.getOriginUrl(),LinkUtil.getLinCacheValidDate(shortLinkCreateReqDTO.getValidDate()),TimeUnit.MILLISECONDS);shortUriCreateCachePenetrationBloomFilter.add(full_short_link); 以上是插入一条短链接的判断大致流程 那么当我们高并发的访问短链接或者人为的去穿透的时候呢 比如下面有人恶意请求毫秒级触发大量请求去一个插入的短链接 1.先从缓存中拿原始链接这个访问当时是之前我们已经通过插入mysql时候预热到缓存中的拿到就跳转这里跳转不了 2.布隆过滤器判断是否包含完整的短链接明显没有如果误判的话逻辑下走 3.这个要调回头再看第一次明显不走 4.分布式锁双检加锁策略。 5.因为数据本就不存在所以shortLinkGotoDO null存入信息到IS_NO_SHORK_LINK对应了第3步 以上步骤我们判断了布隆过滤器查看了是否为空值加了分布式锁。 6.一直向向下乃至释放锁是正常访问的流程。 SneakyThrowsOverridepublic void restoreUrl(String shortUri, ServletRequest request, ServletResponse response) {String serverName request.getServerName();String full_short_url serverName / shortUri;//1.先从缓存中那 跳转的原始链接 拿到的话直接跳转String origin_url stringRedisTemplate.opsForValue().get(String.format(GOTO_SHORT_LINK_KEY, full_short_url));if (StrUtil.isNotBlank(origin_url)) {HttpServletResponse response1 (HttpServletResponse) response;response1.sendRedirect(origin_url);return;}// 判断布隆过滤器是否存在 完整短连接 这个full_short_url 在添加短连接的时候就添加到布隆过滤器里面了// 这个避免了 穿透 乱输入的链接地址 PS : 误判的话逻辑向下走 通过redis的路由表 在判断一次boolean contains shortUriCreateCachePenetrationBloomFilter.contains(full_short_url);if(!contains) {((HttpServletResponse) response).sendRedirect(/page/notfound);return;}//缓存的路由信息 存在String isNoShortGotoLink stringRedisTemplate.opsForValue().get(String.format(GOTO_IS_NOLL_SHORT_LINK_KEY, full_short_url));if(StrUtil.isNotBlank(isNoShortGotoLink)) {((HttpServletResponse) response).sendRedirect(/page/notfound);return;}//分布式锁RLock lock redissonClient.getLock(String.format(LOCK_GOTO_SHORT_LINK_KEY, full_short_url));lock.lock();try {origin_url stringRedisTemplate.opsForValue().get(String.format(GOTO_SHORT_LINK_KEY, full_short_url));if(StrUtil.isNotBlank(origin_url)) {HttpServletResponse response1 (HttpServletResponse) response;response1.sendRedirect(origin_url);return;}//根据 full_short_url 查找路由表ShortLinkGotoDO shortLinkGotoDO shortLinkGotoMapper.selectOne(Wrappers.lambdaQuery(ShortLinkGotoDO.class).eq(ShortLinkGotoDO::getFullShortUrl, full_short_url));if (shortLinkGotoDO null) {// 这个旨在解决布隆过滤器误判stringRedisTemplate.opsForValue().set(String.format(GOTO_IS_NOLL_SHORT_LINK_KEY, full_short_url),-,30, TimeUnit.MINUTES);((HttpServletResponse) response).sendRedirect(/page/notfound);return;}//根据路由表的Gid 和 full_short_url 查找 shortLinkDOShortLinkDO shortLinkDO baseMapper.selectOne(Wrappers.lambdaQuery(ShortLinkDO.class).eq(ShortLinkDO::getGid, shortLinkGotoDO.getGid()).eq(ShortLinkDO::getEnableStatus, 0).eq(ShortLinkDO::getDelFlag, 0).eq(ShortLinkDO::getFullShortUrl, shortLinkGotoDO.getFullShortUrl()));if (shortLinkDO ! null) {//这是解决短链接 已经过期的问题if(shortLinkDO.getValidDate() !null shortLinkDO.getValidDate().before(new Date())) {stringRedisTemplate.opsForValue().set(String.format(GOTO_IS_NOLL_SHORT_LINK_KEY, full_short_url),-,30, TimeUnit.MINUTES);((HttpServletResponse) response).sendRedirect(/page/notfound);return;}stringRedisTemplate.opsForValue().set(String.format(GOTO_SHORT_LINK_KEY, full_short_url),shortLinkDO.getOriginUrl(),LinkUtil.getLinCacheValidDate(shortLinkDO.getValidDate()),TimeUnit.MILLISECONDS);HttpServletResponse response1 (HttpServletResponse) response;response1.sendRedirect(shortLinkDO.getOriginUrl());}} finally {lock.unlock();}}
http://www.pierceye.com/news/878948/

相关文章:

  • 毕设做购物网站容易吗网上商城是什么意思
  • 1688阿里巴巴官方网站杭州网站建设seo
  • 建设网站选什么地方的主机网站上漂亮的甘特图是怎么做的
  • 用什么软件来建网站立创电子元器件商城官网
  • 做视频网站成本如何定制微信小程序
  • 南宁市有哪些做网站的外包企业青州网站建设公司
  • 网站排名点击中国建筑是国企还是央企
  • 广告联盟的网站怎么做太仓苏州网站建设
  • 杭州 seo网站建设 网络服务包头企业网站
  • 网站导航字体企业网站建设及维护
  • 买东西网站产品设计网张
  • 国外有哪些设计网站嵌入式软件开发工具有哪些
  • 做网站推广的销售电话开场白wordpress小工具插件
  • 简单网站建设公司flashfxp上传wordpress
  • 网站建设策划包括哪些内容展馆设计图
  • 网站建设中 翻译六安市 网站集约化建设
  • 全国卫生机构建设管理系统网站公司网站维护费用计哪个科目
  • 学做川菜最好的网站商标综合查询
  • 网站开发培训 价格哪些网站可以找到兼职做报表的
  • 网站建设功能分为几种北京自考网址
  • 购买网站域名怎么做会计分录广告机免费投放
  • 网上做网站赚钱深圳市无限空间工业设计有限公司
  • 商贸网站建设怎么查看wordpress版本
  • 电子商务网站建设哪本教材比较适合中等专业学校用网站建设yankt
  • 局域网网站建设需要什么条件企业建网站的目的
  • 高校专业建设网站桂林漓江竹筏
  • 自已做个网站怎么做网站网络的可用性
  • 深圳网站设计建设永州做网站
  • 怎么制作网站应用wordpress 淘宝客赚钱
  • 网站在政务新媒体建设方案打开手机网站速度慢