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

网站如何做微信推广做竞价推广大概多少钱

网站如何做微信推广,做竞价推广大概多少钱,怎么做地区网站,wordpress更改站点目录 一、解释说明 二、缓存穿透 1. 什么是缓存穿透#xff1f; 2. 常见的两种解决方案 #xff08;1#xff09;缓存空对象 #xff08;2#xff09;布隆过滤 3. 编码解决商品查询的缓存穿透问题 三、缓存雪崩 1. 什么是缓存雪崩#xff1f; 2. 缓存雪崩解决方…目录 一、解释说明 二、缓存穿透 1. 什么是缓存穿透 2. 常见的两种解决方案 1缓存空对象 2布隆过滤 3. 编码解决商品查询的缓存穿透问题 三、缓存雪崩 1.  什么是缓存雪崩 2.  缓存雪崩解决方案4种 四、缓存击穿 1.  什么是缓存击穿 2、缓存击穿解决方案2种 1互斥锁 2逻辑过期 3.  互斥锁与逻辑过期的对比分析​编辑 五、利用互斥锁解决缓存击穿问题 1首先我们声明一下获取锁、释放锁的方法tryLock()、unLock() 2互斥锁解决缓存击穿 queryWithMutex()  六、利用逻辑过期解决缓存击穿问题 1添加逻辑过期时间的字段 2逻辑过期解决缓存击穿问题 queryWithLogicalExpire() 七、封装 Redis 工具类 一、解释说明 Redis缓存穿透、缓存击穿和缓存雪崩都是缓存机制中的一些问题具体解释如下 1缓存穿透Cache Penetration指查询一个不存在的数据由于缓存中没有数据所以这个查询请求会直接穿过缓存层到达数据库层造成了数据库的压力。攻击者可以通过构造恶意请求使得缓存层无法命中任何数据从而导致请求直接访问数据库从而引起数据库压力过大。2缓存击穿Cache Breakdown指缓存中某个热点数据失效此时有大量并发请求同时访问这个失效的数据导致这些请求直接访问数据库造成数据库压力过大甚至导致数据库崩溃。通常是由于缓存中某个热点数据过期失效同时有大量并发请求访问该数据。3缓存雪崩Cache Avalanche指缓存中大量的数据失效导致大量请求直接访问数据库造成数据库压力过大。通常是由于缓存中大量的数据在同一时间失效导致大量请求直接访问数据库。 针对上述问题可以采取以下措施 1缓存穿透可以在查询缓存之前先对请求的参数进行合法性检查如过滤非法字符、判断参数范围等或者使用BloomFilter等数据结构对查询参数进行过滤只有在BloomFilter中判断有可能存在的情况下才会去查询数据库。2缓存击穿可以使用锁机制或者分布式锁机制避免大量并发请求同时访问失效的热点数据。另外可以设置热点数据的过期时间为随机时间避免在同一时间大量数据同时失效。3缓存雪崩可以采用多级缓存架构减少缓存层的压力或者设置不同的缓存过期时间避免大量数据同时失效。另外可以在缓存层和数据库层之间添加限流、熔断等措施避免因突发流量导致系统崩溃。 二、缓存穿透 1. 什么是缓存穿透 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在这样缓存永远不会生效这些请求都会打到数据库。 2. 常见的两种解决方案 1缓存空对象 简单的来说就是请求之后发现数据不存在就将null值打入Redis中。优点实现简单维护方便 缺点额外的内存消耗可能造成短期的不一致 思路分析当我们客户端访问不存在的数据时先请求 redis但是此时 redis 中没有数据 此时会访问到数据库但是数据库中也没有数据这个数据穿透了缓存直击数据库 我们都知道数据库能够承载的并发不如 redis 这么高如果大量的请求同时过来访问这种不存在的数据 这些请求就都会访问到数据库简单的解决方案就是哪怕这个数据在数据库中也不存在 我们也把这个数据存入到 redis 中去这样下次用户过来访问这个不存在的数据 那么在 redis 中也能找到这个数据就不会进入到数据库了。 2布隆过滤 在客户端与Redis之间加了一个布隆过滤器对于请求进行过滤。 布隆过滤器的大致的原理布隆过滤器中存放二进制位。数据库的数据通过hash算法计算其hash值并存放到布隆过滤器中之后判断数据是否存在的时候 就是判断该hash值是0还是1。但是这是一种概率上的统计当其判断不存在的时候就一定是不存在当其判断存在的时候就不一定存在。所以有一定的穿透风险 优点内存占用较少没有多余 key 缺点实现复杂 存在误判可能 综上所述 我们可以两种方案一起用这样子最为保险。据统计使用布隆过滤器一般可以避免90%的无效请求。黑马程序员视频里是使用方案一缓存空对象 3. 编码解决商品查询的缓存穿透问题 核心思路如下在原来的逻辑中我们如果发现这个数据在 mysql 中不存在直接就返回 404 了 这样是会存在缓存穿透问题的现在的逻辑中如果这个数据不存在我们不会返回 404 还是会把这个数据写入到 Redis 中 并且将 value 设置为空欧当再次发起查询时我们如果发现命中之后判断这个 value 是否是 null 如果是 null则是之前写入的数据证明是缓存穿透数据如果不是则直接返回数据。 我们在这里只要做两件事 当查询数据在数据库中不存在时将空值写入 redis判断缓存是否命中后再加一个判断是否为空值 Override public Result queryById(Long id) {// 从redis查询商铺缓存String key CACHE_SHOP_KEY id;String shopJson stringRedisTemplate.opsForValue().get(key);// 判断是否存在if (StrUtil.isNotBlank(shopJson)) {// 存在直接返回Shop shop JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}// 1.判断空值if (shopJson ! null) {// 返回一个错误信息return Result.fail(店铺不存在);}// 不存在根据id查询数据库Shop shop getById(id);// 不存在返回错误if (shop null) {// 2.防止穿透问题将空值写入redis!!!stringRedisTemplate.opsForValue().set(key,,CACHE_NULL_TTL,TimeUnit.MINUTES);return Result.fail(店铺不存在);}// 存在写入Redis// 把shop转换成为JSON形式写入Redis// 同时添加超时时间stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);return Result.ok(shop); } 总结 缓存穿透产生的原因是什么 用户请求的数据在缓存中和数据库中都不存在不断发起这样的请求给数据库带来巨大压力 缓存穿透的解决方案有哪些 1缓存 null 值 2布隆过滤 3增强 id 的复杂度避免被猜测 id 规律 4做好数据的基础格式校验 5加强用户权限校验 6做好热点参数的限流 三、缓存雪崩 1.  什么是缓存雪崩 缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机导致大量请求到达数据库带来巨大压力。 情况大致如下图所示 2.  缓存雪崩解决方案4种 1给不同的Key的TTL添加随机值推荐操作简单当我们在做缓存预热的时候就有可能在同一时间批量插入大量的数据 那么如果它们的TTL都一样的话就可能出现大量key同时过期的情况 所以我们需要在设置过期时间TTL的时候定义一个范围追加该范围内的一个随机数。2利用Redis集群提高服务的可用性使用集群提高可靠性后续讲解~~~之后写了会在这里贴上链接。3给缓存业务添加降级限流策略也是后续的微服务的知识~~~SpringCloud中有提4给业务添加多级缓存  请求到达浏览器nginx可以做缓存未命中找Redis再未命中找JVM最后到数据库...... 四、缓存击穿 1.  什么是缓存击穿 缓存雪崩是因为大量的key同时过期所导致的问题而缓存击穿则是部分key过期导致的严重后果。 为什么大量key过期会产生问题而少量的key也会有问题缓存击穿问题也叫热点Key问题就是⼀个被高并发访问并且缓存重建业务较复杂的key突然失效了 无数的请求访问会在瞬间给数据库带来巨大的冲击。 具体情况如下图所示 上述假设此时该热点key的TTL时间到失效了则查询缓存未命中会继续查询数据库并进行缓存重建工作。但是由于查询SQL逻辑比较复杂、重建缓存的时间较久并且该key又是热点key短时间内有大量的线程对其进行访问所以请求会直接 “打到” 数据库中数据库就有可能崩掉 2、缓存击穿解决方案2种 1互斥锁 简单的来说:并不是所有的线程都有 “ 资格 ” 去访问数据库只有持有锁的线程才可以对其进行操作。 不过该操作有一个很明显的问题就是会出现相互等待的情况。 2逻辑过期 不设置TTL之前所说导致缓存击穿的原因就是该key的TTL到期了所以我们在这就不设置TTL了 而是使用一个字段,例如expire表示过期时间逻辑上的。当我们想让它 “ 过期 ” 的时候 我们可以直接手动将其删除热点key即只是在一段时间内其被访问的频次很高。这种方案巧妙在于异步的构建缓存缺点在于在构建完缓存之前返回的都是脏数据。 3.  互斥锁与逻辑过期的对比分析 五、利用互斥锁解决缓存击穿问题 核心思路相较于原来从缓存中查询不到数据后直接查询数据库而言现在的方案是 进行查询之后 如果从缓存没有查询到数据则进行互斥锁的获取获取互斥锁后判断是否获得到了锁如果没有获得到 则休眠过一会再进行尝试直到获取到锁为止才能进行查询如果获取到了锁的线程再去进行查询查询后将数据写入 redis再释放锁返回数据 利用互斥锁就能保证只有一个线程去执行操作数据库的逻辑防止缓存击穿。 代码实现 1首先我们声明一下获取锁、释放锁的方法tryLock()、unLock() /*** 获取锁* param key* return */ private boolean tryLock(String key) {// setnx 就是 setIfAbsent 如果存在Boolean flag stringRedisTemplate.opsForValue().setIfAbsent(key, 1, 10, TimeUnit.MINUTES);// 装箱是将值类型装换成引用类型的过程拆箱就是将引用类型转换成值类型的过程// 不要直接返回flag可能为nullreturn BooleanUtil.isTrue(flag); }/*** 释放锁* param key*/ private void unLock(String key) {stringRedisTemplate.delete(key); } 注意这里的锁不是真正的线程锁而是redis里面的一个特殊的key。 2互斥锁解决缓存击穿 queryWithMutex()  /*** 互斥锁解决缓存击穿 queryWithMutex()* param id* return*/ public Shop queryWithMutex(Long id) {// 1.从redis查询商铺缓存String key CACHE_SHOP_KEY id;String shopJson stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isNotBlank(shopJson)) {return JSONUtil.toBean(shopJson, Shop.class);}// 判断空值if (shopJson ! null) {// 返回一个错误信息return null;}String lockKey lock:shop: id;Shop shop null;try {// 4.实现缓存重建// 4.1获取互斥锁boolean isLock tryLock(lockKey);// 4.2判断是否成功if (!isLock) {// 4.3失败则休眠并重试Thread.sleep(50);// 递归return queryWithMutex(id);}// 4.4成功根据id查询数据库shop getById(id);// 模拟延迟Thread.sleep(200);// 5.不存在返回错误if (shop null) {stringRedisTemplate.opsForValue().set(key,,CACHE_NULL_TTL,TimeUnit.MINUTES);return null;}// 6.存在写入redisstringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop),CACHE_SHOP_TTL,TimeUnit.MINUTES);} catch (InterruptedException ex) {throw new RuntimeException(ex);} finally {// 7.释放锁unLock(lockKey);}// 8.返回return shop; } 六、利用逻辑过期解决缓存击穿问题 需求修改根据id查询商铺的业务基于逻辑过期方式来解决缓存击穿问题 注意这里的key是否过期不是由redis控制的而是由我们自己去手动编写逻辑去控制的。  代码实现 1添加逻辑过期时间的字段 由于我们之前的Shop中是没有逻辑过期的字段那么我们要如何让它带有这个属性又不修改之前的代码呢 新建一个RedisData对象里面的data指的是Shop对象而expireTime是逻辑过期时间。 即我们可以使用 JSONUtil.toBean 将Shop对象通过序列化、反序列化到RedisData类的data属性中。 Data public class RedisData {// LocalDateTime 同时含有年月日时分秒的日期对象// 并且LocalDateTime是线程安全的private LocalDateTime expireTime;private Object data; } 2逻辑过期解决缓存击穿问题 queryWithLogicalExpire() 缓存重建 /*** 重建缓存,先缓存预热一下否则queryWithLogicalExpire() 的expire为null* param id* param expireSeconds*/ public void saveShopRedis(Long id, Long expireSeconds) {// 1.查询店铺数据Shop shop getById(id);// 2.封装逻辑过期时间RedisData redisData new RedisData();redisData.setData(shop);redisData.setExpireTime(LocalDateTime.now().plusSeconds(expireSeconds)); // 过期时间// 3.写入redisstringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY id, JSONUtil.toJsonStr(redisData)); } 先使用测试方法运行一下saveShopRedis()否则redis里面没有expireTime private static final ExecutorService CACHE_REBUILD_EXECUTOR Executors.newFixedThreadPool(10);/*** 逻辑过期解决缓存击穿问题 queryWithLogicalExpire()* 测试前要先缓存预热一下不然 data 与 expireTime 的缓存值是null* param id* return*/ public Shop queryWithLogicalExpire(Long id) {// 1.从redis查询商铺缓存String key CACHE_SHOP_KEY id;String shopJson stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isBlank(shopJson)) {return null;}// 4.命中需要将json反序列化为对象// redisData没有数据RedisData redisData JSONUtil.toBean(shopJson, RedisData.class);Shop shop JSONUtil.toBean((JSONObject) redisData.getData(), Shop.class);LocalDateTime expireTime redisData.getExpireTime();// 5.判断是否过期if (expireTime.isAfter(LocalDateTime.now())) {// 5.1未过期直接返回店铺信息return shop;}// 5.2已过期需要缓存重建// 6.缓存重建// 6.1.获取互斥锁String lockKey LOCK_SHOP_KEY id;boolean islock tryLock(lockKey);// 6.2.判断是否获取互斥锁成功if (islock) {// 6.3.成功开启独立线程实现缓存重建CACHE_REBUILD_EXECUTOR.submit( () - {try {// 重建缓存过期时间为20LsaveShopRedis(id,20L);} catch (Exception ex) {throw new RuntimeException(ex);} finally {unLock(lockKey);}});}// 6.4.返回过期店铺信息return shop; } 可以看到在测试的时候name的值为“100XXXX” 修改一下数据库将值改为“900XXXX”看看并发情况下缓存重建能否正确 通过Jmeter做压力测试 再查看Redis中的数据可以看到name的值已经被修改了而且上面的jmeter的每一个http都是正常的 七、封装 Redis 工具类 基于 StringRedisTemplate 封装一个缓存工具类满足下列需求 方法 1将任意 Java 对象序列化为 json 并存储在 string 类型的 key 中并且可以设置 TTL 过期时间 方法 2将任意 Java 对象序列化为 json 并存储在 string 类型的 key 中并且可以设置逻辑过期时间 用于处理缓 存击穿问题 方法 3根据指定的 key 查询缓存并反序列化为指定类型利用缓存空值的方式解决缓存穿透问题 方法 4根据指定的 key 查询缓存并反序列化为指定类型需要利用逻辑过期解决缓存击穿问题 将逻辑进行封装 Slf4j Component public class CacheClient {private final StringRedisTemplate stringRedisTemplate;private static final ExecutorService CACHE_REBUILD_EXECUTOR Executors.newFixedThreadPool(10);public CacheClient(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate;}public void set(String key, Object value, Long time, TimeUnit unit) {stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, unit);}public void setWithLogicalExpire(String key, Object value, Long time, TimeUnit unit) {// 设置逻辑过期RedisData redisData new RedisData();redisData.setData(value);redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));// 写入RedisstringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData));}public R,ID R queryWithPassThrough(String keyPrefix, ID id, ClassR type, FunctionID, R dbFallback, Long time, TimeUnit unit){String key keyPrefix id;// 1.从redis查询商铺缓存String json stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isNotBlank(json)) {// 3.存在直接返回return JSONUtil.toBean(json, type);}// 判断命中的是否是空值if (json ! null) {// 返回一个错误信息return null;}// 4.不存在根据id查询数据库R r dbFallback.apply(id);// 5.不存在返回错误if (r null) {// 将空值写入redisstringRedisTemplate.opsForValue().set(key, , CACHE_NULL_TTL, TimeUnit.MINUTES);// 返回错误信息return null;}// 6.存在写入redisthis.set(key, r, time, unit);return r;}public R, ID R queryWithLogicalExpire(String keyPrefix, ID id, ClassR type, FunctionID, R dbFallback, Long time, TimeUnit unit) {String key keyPrefix id;// 1.从redis查询商铺缓存String json stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isBlank(json)) {// 3.存在直接返回return null;}// 4.命中需要先把json反序列化为对象RedisData redisData JSONUtil.toBean(json, RedisData.class);R r JSONUtil.toBean((JSONObject) redisData.getData(), type);LocalDateTime expireTime redisData.getExpireTime();// 5.判断是否过期if(expireTime.isAfter(LocalDateTime.now())) {// 5.1.未过期直接返回店铺信息return r;}// 5.2.已过期需要缓存重建// 6.缓存重建// 6.1.获取互斥锁String lockKey LOCK_SHOP_KEY id;boolean isLock tryLock(lockKey);// 6.2.判断是否获取锁成功if (isLock){// 6.3.成功开启独立线程实现缓存重建CACHE_REBUILD_EXECUTOR.submit(() - {try {// 查询数据库R newR dbFallback.apply(id);// 重建缓存this.setWithLogicalExpire(key, newR, time, unit);} catch (Exception e) {throw new RuntimeException(e);}finally {// 释放锁unlock(lockKey);}});}// 6.4.返回过期的商铺信息return r;}public R, ID R queryWithMutex(String keyPrefix, ID id, ClassR type, FunctionID, R dbFallback, Long time, TimeUnit unit) {String key keyPrefix id;// 1.从redis查询商铺缓存String shopJson stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isNotBlank(shopJson)) {// 3.存在直接返回return JSONUtil.toBean(shopJson, type);}// 判断命中的是否是空值if (shopJson ! null) {// 返回一个错误信息return null;}// 4.实现缓存重建// 4.1.获取互斥锁String lockKey LOCK_SHOP_KEY id;R r null;try {boolean isLock tryLock(lockKey);// 4.2.判断是否获取成功if (!isLock) {// 4.3.获取锁失败休眠并重试Thread.sleep(50);return queryWithMutex(keyPrefix, id, type, dbFallback, time, unit);}// 4.4.获取锁成功根据id查询数据库r dbFallback.apply(id);// 5.不存在返回错误if (r null) {// 将空值写入redisstringRedisTemplate.opsForValue().set(key, , CACHE_NULL_TTL, TimeUnit.MINUTES);// 返回错误信息return null;}// 6.存在写入redisthis.set(key, r, time, unit);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {// 7.释放锁unlock(lockKey);}// 8.返回return r;}private boolean tryLock(String key) {Boolean flag stringRedisTemplate.opsForValue().setIfAbsent(key, 1, 10, TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);}private void unlock(String key) {stringRedisTemplate.delete(key);} }
http://www.pierceye.com/news/801947/

相关文章:

  • dede地方门户网站模板做网站备案
  • 域名访问网站的知识站酷网官网进入
  • 6入空间网站免费观看wordpress转盘抽奖源码
  • 手机网站怎么开发工具网站开发中如何实现gps定位
  • sql2008做网站焦作网站建设哪家便宜
  • hao123网站源码制作2015最新仿制作链接怎么做
  • 做网站源代码需要买吗做任务得佣金的网站
  • 网站开发php还是jsp中式风格装修效果图
  • 外贸网站建设优化营销昆明网站建设加q.479185700
  • 正安网站建设推荐友情链接
  • 织梦仿asp网站石家庄市制作网站公司
  • 全国较好的网站建设公司织梦网做网站步骤
  • dedecms小说网站模板自动生成网站地图的工具
  • 中国比较好的设计网站php网站怎么做静态化
  • Dedecms手机网站源码wordpress小程序制作
  • 成都网站建设备案重庆找网站推广
  • 商务网站建设的调研wordpress 视频 全屏
  • 网站策划案例广州高端网站定制开发价格
  • 大连网站制作优选ls15227微信公众号小程序搭建
  • 个人空间网站建设报告网站建设培训哪个好
  • wap微信网站模板在线网络培训平台
  • asp网站怎么做三语网络推广计划书格式
  • 徽州网站建设企业网站备案域名信息
  • 广州建设信息网官方网站火车头采集wordpress发布
  • 易记域名网站大全火车票网站建设多少
  • 怎么将网站权重提上去怎样在网站图片做超级链接
  • 网站建设需求分析报告功能百度官方电话24小时
  • 扬州市城市建设监察支队网站做空比特币网站
  • 石家庄做网站 vtkj网站空间怎样设置用户名和密码
  • 自考网页制作与网站建设网站虚拟主机建设