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

如何打死网站qq空间网站域名怎么做的

如何打死网站,qq空间网站域名怎么做的,网站建设与设计论文,上海搜索引擎优化seo黑马点评学习笔记 1.缓存穿透1.1 缓存穿透是什么#xff1f;1.2缓存穿透的解决方案1.2.1 缓存空对象1.2.2 布隆过滤1.2.3 其他解决方案 2.缓存雪崩2.1 缓存雪崩是什么#xff1f;2.2 缓存雪崩的解决方案 3.缓存击穿3.1缓存击穿是什么#xff1f;3.2缓存击穿的解决方案3.2.1互… 黑马点评学习笔记 1.缓存穿透1.1 缓存穿透是什么1.2缓存穿透的解决方案1.2.1 缓存空对象1.2.2 布隆过滤1.2.3 其他解决方案 2.缓存雪崩2.1 缓存雪崩是什么2.2 缓存雪崩的解决方案 3.缓存击穿3.1缓存击穿是什么3.2缓存击穿的解决方案3.2.1互斥锁3.2.2 逻辑过期3.2.3两种方案的优缺点对比1.互斥锁的优点2.互斥锁的缺点3.逻辑过期的优点4.逻辑过期的缺点5.总结 3.2.4 互斥锁解决缓存击穿问题的实现所要注意的细节3.2.5 逻辑过期解决缓存击穿问题的实现所要注意的细节 1.缓存穿透 1.1 缓存穿透是什么 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在这样缓存永远不会生效这些请求都会打到数据库。 1.2缓存穿透的解决方案 1.2.1 缓存空对象 缓存空对象是一种简单暴力的做法 思路就是 当我们客户端访问不存在的数据时先请求redis但是此时redis中没有数据此时会访问到数据库但是数据库中也没有数据这个数据穿透了缓存直击数据库。而数据库能够承载的并发不如redis这么高所以为了请求不访问到数据库我们就把空对象存储到redis里去。这样下次用户过来访问这个不存在的数据在redis中也能找到这个数据尽管命中的是null但请求不会再到数据库 优点实现简单 缺点有额外的内存消耗 例如随便传一个id不存在的数据就将我以空对象的形式缓存起来那么这也就是说随便传各种各样的id都会被缓存起来因此redis里面就会缓存了很多这样的垃圾。 但是这个问题可以被解决 解决方法就是我们在缓存null的时候添加一个ttlttl就是有效期我们可以给它设置一个比较短的ttl比如五分钟或者是两分钟。 在两分钟内缓存是有效的所以当有恶意的用户来访问的时候也可以起一定的保护作用同时它的有效期也不长所以说这些垃圾数据过段时间也会被清除掉也不会带来特别大的内存消耗 但是可能造成短期的不一致假设用户请求了一个ID这个id刚好不存在我们给他设置了null就在此时我们真的给这个id插入了一条数据那这个时候等于数据库里已经有了但是我们却缓存了一个null这个时候用户来查询查询到的是null而实际上是存在的这就出现了不一致只有当这个ttl过期以后用户才能查到最新的一个数据 针对这个问题只要我们在一定程度上控制ttl的时间在一定程度上是可以缓解的那么这个不一致的时间只要足够短其实也是可以接受的。 如果实在是无法接受这个不一致性我们可以在新增一条数据的时候我们主动的把这条数据插入到缓存中覆盖之前的null 1.2.2 布隆过滤 布隆过滤准确来讲是一种算法 思路就是 它的原理是在客户端和redis之间又加入了一层拦截当用户请求来了之后不是上来就查redis而是先去找布隆过滤问一问这个数据是存在还是不存在如果这个数据不存在会直接拒绝就不给机会继续往下走如果告诉你存在那么被允许去访问redis。 布隆过滤器其实采用的是哈希思想来解决这个问题通过一个庞大的二进制数组走哈希思想去判断当前这个要查询的这个数据是否存在如果布隆过滤器判断存在则放行这个请求会去访问redis哪怕此时redis中的数据过期了但是数据库中一定存在这个数据在数据库中查询出来这个数据后再将其放入到redis中 1.2.3 其他解决方案 以上两种方案都属于被动方案即已经发生了缓存穿透然后想办法弥补 但是我们也可以主动地采取一些措施去解决缓存穿透 增强id的复杂度避免被猜测id规律 这样就可以尽可能避免让别人猜到我们的id规律而输入自己编的一些id 做好数据的基础格式校验加强用户权限校验 即加强用户权限的管理比如说什么的用户能够访问我们这样的一个用户访问我们的时候有一个什么频率的限制 做好热点参数的限流 2.缓存雪崩 2.1 缓存雪崩是什么 缓存雪崩是指在同一时段大量的缓存key同时失效或者redis服务宕机导致大量请求到达数据库带来巨大压力 2.2 缓存雪崩的解决方案 给不同的Key的TTL添加随机值 我们平时在做缓存的时候为了做缓存的预热我们可能提前把数据库中的数据导入到我们的缓存当中这个导入一般是批量导入的。在批量导入的过程中因为是同一时刻导入的他们的ttl设置的是一样的值很有可能将来时间一到所有的都一起过期了那么就会出现雪崩 为了解决这个问题我们在做缓存预设批量的数据导入的时候我们可以给这个ttl后边跟上一个随机数比说我们的时间是30分钟有效期然后我们在后面跟上一个随机的1-5之间的一个随机数那么它的一个有效期就会在30-35分钟之间波动当然我们也可以扩大这个随机数这样的话就可以让这些key过期的时间分散在一个时间段内而不是一起失效 利用Redis集群提高服务的可用性 redis宕机导致的缓存雪崩是最严重的针对这个问题我们要尽可能避免redis的宕机那也就是提高整个redis的高可用性要想提高redis的高可用性我们就必须借助redis集群 例如rediis的哨兵机制redis哨兵可以实现服务的监控 如果说主机宕机了哨兵可以自动地从从机里面选出来一个去替代原来的主机这样就可以确保redis已知能够正常地对外提供服务而且我们的主从还可以实现一种数据的同步如果说主机宕机了从机上面还会有数据这样就可以在很大程度上保证redis的高可用性 给缓存业务添加降级限流策略 比方说出现了人们无法抗拒的一些超级严重的事故整个服务器挂了、整个机房挂了这些导致的就是整个redis都挂了整个集群都完蛋了 那这个时候的可用性如何保证呢 此时我们就可以给服务添加一些降级限流的策略 那这是什么意思呢 也就是提前做好一些容错处理 当我们发现redis出现故障时我们应该及时地去做服务降级 比如说快速失败拒绝服务而不是把这个请求继续发到我们的数据库上这样子做的话就可以保护我们的数据库了牺牲部分服务但是最终保护了我们整个数据库的一个健康 那这个降级如何实现的呢 还是与sprringclound相关内容有关 给业务添加多级缓存 何为多级缓存 缓存的使用场景是多种多样的不仅可以在应用层添加还可以在多个层面建立缓存这样redis这一环崩溃了那么还会有很多的缓存可以去弥补 通俗的说就是防弹衣穿了五层打了一层还有一层 具体来说请求从浏览器发出那么浏览器是可以添加缓存的但是浏览器的缓存一般缓存的是静态的数据而对于一些需要从数据库查询的动态数据是无法做缓存的对于这一部份我们可以在反向代理服务器nginx 层面去做缓存nginx未命中再去找redisredis未命中再到达jvm我们还可以在jum内部建立本地缓存最后就是数据库. 所以说通过多级缓存的方式就可以有效地避免雪崩导致的问题了 3.缓存击穿 3.1缓存击穿是什么 缓存击穿问题也叫热点key问题就是一个被高并发访问并缓存重建业务比较复杂的key突然失效了无数的请求访问会在瞬间给数据库带来巨大冲击 如何理解高并发访问 这个key被访问的非常非常多可能是正在做活动的某一件商品它的缓存同一时刻可能就会有无数的请求来访问这个key 如何理解缓存重建业务比较复杂 何为缓存重建呢 就是我们的缓存在redis中存着它到了一定的时间就会被清除缓存就会失效失效了之后我们需要重新从数据库里查询写redis 但是在实际的开发中从数据库里查询并且构建这个数据并不一定是在数据库查到什么就直接往redis里面存什么有时候一些业务比较复杂我们那需要从多个数据库的表中进行查询后要去做各种各样的表关联的运算最终得到的这个结果把它缓存起来 那这样一来一个业务它的耗时可能就会比较长达到几十毫秒上百毫秒甚至数百毫秒那这样一来在这么长的一个时间段内我们的redis等于一直没有缓存此时就会有无数请求来都无法命中了并将请求打到数据库这就有可能把数据库都整垮了 3.2缓存击穿的解决方案 3.2.1互斥锁 互斥锁比较好理解就是现在有无数的请求都进来尝试去做重建了我们用加锁的方式让这些请求都不要来创建只要有一个来创建就可以了 具体来说就是假如现在有一个线程它来查询的时候未命中那么它就会去做缓存重建但是为了避免无数的线程都来重建我们会加锁也就是线程发现未命中之后必须先获取锁只有获取锁成功的人才可以去重建这个缓存重建完之后把这个数据写入缓存紧接着就可以释放锁了。 线程获取锁失败它就会去重试但是不可以无限重试我们可以让它休眠一下再去重试重新查询是否命中如果说命中就不用再获取了 这个解决方案最大的缺点就是互相等待 比如说现在同一时刻有1000个线程来了其实只有一个线程在做重建其他的线程都在等待。那如果说这个重建的时间比较久达到比如说200ms甚至500ms那么在这一段时间内涌入的所有线程都只能等待因此就会导致性能比较差所以才有了第二种解决方案 3.2.2 逻辑过期 逻辑过期不是真的过期 可以认为是永不过期 这个方案就是当我们再向redis存储数据的时候我们不设置ttl了 缓存击穿就是因为设置了ttl缓存突然失效导致未命中然后需要重建 1.但是不设置ttl我们如何知道这个缓存是否过期 逻辑过期就是我们在存储一个数据的时候以前是存储一个k-v就结束了在valve里面加一个字段 比如说expire过期时间 这里的过期时间并不是ttl而是我们再去添加缓存的时候在当前时间基础上加上一个过期时间比如说30分钟得到的一个时间存储进去 也就是说我们逻辑上维护了这个时间 2.这个key没有ttl过期时间是不是意味着将来这个key一旦存储到redis里面就永远不会过期 加上我们配了合适的一些内存淘汰策略的话理论上可以认为只要这个key写到redis以后永远都能够查询的到不会出现未命中的情况。 一些热点key往往都是在做活动的时候我们去添加进去的那我们在做活动的同时直接给它设知道redis中添加上逻辑过期时间活动结束了我们再把它移除就可以了。 那因此任何的线程来查询这样的热点商品的时候理论上来讲都是可以命中的的唯一需要判断的就是逻辑上有没有过期如果说逻辑上已经过期了那可能说明这个key已经是一些旧的数据了需要更新 3.那接下来我们需要去做什么呢 就是要去重建这个缓存但是这个重建为了避免有多个线程都来重建他也要去获取锁那这里做的就跟前面的一样了也是要等待 但是为了避免获取锁以后等待时间过长那它拿到锁之后就会做一件事他不是自己选择构建而是开启一个独立的新的线程有这个线程去做查询数据重建写入缓存写入缓存以后要重置这个逻辑过期时间这些都做完之后就要去释放锁那也就是说这个耗时比较久的任务不再是线程一自己做了而是交给另一个线程去做该线程做完以后释放锁 4.那么在它写入缓存的这段时间内等于缓存的都是旧的数据那这个时候线程一开启新线程做这件事线程一干什么 直接返回旧的数据即可。那么其他线程来查询获取锁失败的时候也不会是等待而是返回旧数据因为他知道有人去帮我更新数据了那就可以直接把查到的旧数据返回就可以了 3.2.3两种方案的优缺点对比 1.互斥锁的优点 互斥锁这种方案没有额外的内存消耗 因为相对于逻辑过期来说逻辑过期会在原有的数据的基础上要多维护一个过期时间的字段这就会有额外的内存消耗。而互斥锁不需要去保存逻辑过期所以它这块内存占用是比较小的 互斥锁可以保证强的一致性 因为当一个线程来取缓存的时候如果发现未命中会尝试去更新而如果它发现已经有人拿到锁正在更新 他不会说去那点旧数据因为没有旧数据很多都是空的因为失效了就会删除而逻辑过期是永不删除所以这就是为什么逻辑过期可以拿大旧的数据而不是空的数据那么他就会等待缓存中有了数据那时候缓存中的一定是最新的数据所以说只要它拿到数据一定拿的是最新的他可以保证缓存和数据库之间的这种强的一致性 2.互斥锁的缺点 等待会降低性能 除此之外还有会有死锁的风险 假设说我们这个业务里有对多个缓存的查询需求而在同样一个业务里也有这个时候有可能你拿到了一把锁你要获取另外一个缓存的锁的时候结果发现是在其他业务里于是就会产生这种互相等待的死锁情况 3.逻辑过期的优点 因为逻辑过期不用等待所以它的性能就很好并发能力不会受到影响。 4.逻辑过期的缺点 但是也会有缺点他会返回旧数据当我看到是过期了但我也先用着这个数据所以这就造成数据不一致性。 代码实现比较复杂是要维护逻辑过期以及各种逻辑判断 5.总结 总的来说这两个方案都是在解决我们缓存重建的这一段时间内产生的并发问题 互斥锁的解决方案就是在缓存重建的这一段时间内让这些并发的线程串行执行或者互相等待从而确保安全那这种方案确保了数据的一致性但却牺牲了服务的可用性性能是有很大下降的而且在阻塞过程中可能甚至于不可用 而逻辑过期这种方案是在缓存重建的这段时间内保证了可用性大家来了都可以访问只不过访问得到的可能是旧数据与数据库不一致这牺牲了不一致性 也就是说一个选择了一致性一个选择了可用性 没有谁好谁不好 看我们需要什么就选择什么 3.2.4 互斥锁解决缓存击穿问题的实现所要注意的细节 这个锁不是我们平常用的那个锁平常用的是synchronize或者是lock这个锁我们要实现拿到了锁可以执行没拿到锁就要一直等待。但是这个执行逻辑是要我们自己去定义的所以说我们不能够使用前面的那种锁的方式了1.我们要采用一个自定义的锁 2.那要用什么方式来实现这种自定义的互斥锁呢 所谓的这种互斥锁就是说在多个线程并发执行的时候只能有一个人成功其他人失败 在我们学习的redis的string数据类型的时候它里面就有一个命令跟这个效果是非常接近的setnx set the value of a keyonly if the key does not exist就是说给key赋值当且仅当这个key不存在的时候去执行如果key存在就不执行了 3.它为什么会做到互斥呢 我们先用一个setnx 给一个key赋值 假设这个key是lock代表的就是一把锁 现在有这么一个对象一他要去获取这把锁setnx lock 1 这个返回值为1这个返回值代表的就是成功get lock 检查是否成功 这时候又有一个对象二想要获取这把锁setnx lock 2 这个返回值为0 再来一个对象执行同样的操作还是0 现在我们通过get lock看看lock的值有没有发生改变 没有改变依然是最开始设置的1 这就说明setnx是在key不存在的时候才能往里面写key如果已经存在了是无法写的 如果说现在有数百上千并发的线程一起来执行setnx操作只有第一个人会成功它成功写入了之后其他线程再来执行setnx得到的一定是一个0也就是失败的结果这就类似于我们讲的互斥只有一个人成功其他都失败 这就是自定义锁的一个方案 其实这也是分布式锁的基本原理当然真正的分布式锁会比这个要复杂得多 4.获取锁用setnx就可以了那释放锁呢 获取锁是给它赋值那释放锁其实非常简单就是把这个锁删除掉就可以了del lock删除掉了之后再有其他人来执行这个setnx操作的时候就能成功了 但是会有意外的情况比如说setnx设置了一把锁设置完了之后由于某种原因程序出问题了最后迟迟没有人去执行这个删除或者释放的动作那将来就很有可能这把锁就永远不会释放了 所以我们在利用setnx设置锁的时候往往会给它加一个有效期比如说设置有效期为十秒钟一般我们的业务执行在1秒钟以内那么在这个业务执行的过程中如果正常释放就行万一因为某种异常导致服务出现了故障锁永远不释放了将来十秒钟到了之后锁还能够自动释放 所以说我们再去设置这把锁的时候也会给它设置一个有效期来做兜底避免因为某种原因得不到释放产生死锁 5.在代码如何实现 在实现业务之前先去声明两个方法代表 获取锁和释放锁 setnx的方法名是setIfAbsent 注意我们不能直接返回setIfAbsent的执行结果这个结果在命令行中是0和1但是spring帮我们转换成了Boolean我们需要把这个结果转为基本类型之后才能返回如果直接把结果返回是会做拆箱的那么在这个拆箱过程中是有可能出现空指针的拆箱底层调用booleanValue方法如果flag为null的话就会空指针异常所以这里可以使用一个工具类BooleanUtil里的isTrue方法这个方法的意思是只有true的时候返回trueflase和null都返回false 为什么会有包装类因为不包装就是基本类型包装了就是一个类很多操作需要类才能进行 6.注意 注意在获取锁成功的时候应该再次检测redis缓存是否存在做DoubleCheck。如果存在则无需重建缓存获取锁失败的时候递归会有溢栈的风险这里还要处理异常不管有没有异常都要释放锁所以释放锁这块要放到finally里面去写 3.2.5 逻辑过期解决缓存击穿问题的实现所要注意的细节 逻辑过期不是真正的过期它要求我们在存储数据到redis的时候额外地要添加一个过期时间的字段这个key本身是不需要去设置ttl的所以它的过期时间不是由redis控制的而是有我们程序员自己去判断它是否过期的那这样我们的业务上就会复杂很多 理论上讲只要设置了逻辑过期就不会出现未命中的情况 首先key是不会过期的所以我们可以认为一旦这个key添加到了缓存里面它应该是会永久存在的除非活动结束我们再人工删除而像这种热点key往往是一些参加活动的一些商品我们会提前给他们加入缓存在那个时候就会给他设置一下逻辑过期时间所以说理论上讲所有的热点key都会提前添加好并且一直存在直到活动结束。因此我们去查询的时候其实可以不用去判断它有没有命中如果说真的查到了这个缓存不存在那只能说明一个问题就是说这个商品它不在活动当中不属于一个热点key 因此我们的核心逻辑就是默认缓存命中 在命中的情况下我们需要判断它有没有过期也就是它的逻辑过期时间 如果未过期则直接把这个数据返回给前端 但是如果过期了则说明需要做缓存重建不过不是任何人来了都可以做缓存重建所以这里也需要先尝试去获取这个互斥锁然后判断一下是否获取成功如果获取失败则返回旧数据获取成功则开启独立线程去做缓存重建查询数据库将数据写入缓存并设置逻辑过期时间 最后释放互斥锁自己返回旧数据 开启独立线程去做重建建议是使用一个线程池不要自己去写一个线程自己写一个线程性能不太好需要经常去创建和销毁所以我们就创建一个线程池 那这个逻辑过期时间怎么添加到数据里面呢 虽然我们可以直接在实体类中添加逻辑过期字段 这样在提交实体类数据到缓存的时候逻辑过期时间的字段也在缓存中设置好了 但是这种方法不够好因为这样会对原来的代码和业务逻辑做了修改 因此我们可以定义一个新的对象Redisdata里面定义一个字段 Local DataTime expireTime 这个就是我们设置的逻辑过期时间 现在想要我们的实体类具备这个逻辑过期时间的属性 1.第一种可以让我们的实体类继承redis Data那这个实体类自然就具备了这个属性了但是这个方法还是会去修改我们的实体类因此还是有一定的侵入性。 2.另一种就是在redisData里面去添加一个Object属性 data也就是说这个RedisData里面有过期时间 也有自带的一个数据这个数据就是我们想要存进redis即缓存里面的数据他是一个万能的存储数据的对象这种方案就完全不需要对原来的实体类做任何的修改 前面也说了像这种热点数据的缓存我们是会做提前导入的在实际的开发中会用到后台管理系统可以把某一些热点数据提前存储到缓存中 现在我们没有一个后台管理系统所以我们会给予一个单元测试的方法来把热点数据加入到缓存当中等于提前做一个缓存预热 但是我们需要先在service里面定义一个saveDataToRedis
http://www.zqtcl.cn/news/403400/

相关文章:

  • 房屋装修网站模板html5做网站
  • 网站建设需要的硬件网站建设知名公司排名
  • 绥化网站建设私自搭建vps犯法吗
  • 建设专业网站哪家比较好小程序源码是什么意思
  • 网站设计一般包括什么给公司做网站数据分析
  • 网站根目录在哪里1024cctvcom戊人影祝
  • wordpress转发微信南宁seo企业优化
  • 红旗渠建设集团网站昭通网络推广
  • 海陵区建设局网站计算机网站建设考试试卷
  • 佛山做网站3lue网站开发招标网
  • 粘贴以下代码到网站首页代码的与标签之间渭南软件开发
  • 企业网站建设必要性上海网站建设报价表
  • 陕西省建设厅申报网站一个主体如何添加网站
  • 做网站业务员提成几个点wordpress 地图导航代码
  • 软件下载网站排行住房和城乡建设部办公厅网站
  • 贵阳网站建设需要多少钱百度资源搜索平台
  • 做安全防护信息的网站wordpress初始密码
  • 广东企业网站seo哪里好微信公众号怎么创建文章
  • 建行网站登录不了wordpress好主题
  • 南屏网站建设湖北省建设厅的网站
  • 有没有做花卉种子的网站啊正规网站建设服务
  • 长沙网站建设公司招聘那个建设网站好
  • 网站开发视频下载网站优化关键词排名自己怎么做
  • 网站建设 流程咸宁网站建设哪家好
  • 建站公司兴田德润实惠钦州建设局网站
  • 高新区免费网站建设旅游网站开发设计与实现
  • 怎样做才能让网站帮忙送东西线上推广方案怎么做
  • 服装公司网站网页设计友情链接交换网站
  • 公司建设网站需要去哪报备网页挂马
  • 做网站需要代码吗秦皇岛在哪里