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

最专业 汽车网站建设html5模板开发wordpress主题

最专业 汽车网站建设,html5模板开发wordpress主题,公司域名查询官方网站,wordpress 首页静态什么是缓存? 缓存就是数据交换的缓冲区,是存贮数据的临时地方,一般读写性能较高。 怎么防止缓存穿透? 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到…

 什么是缓存?

缓存就是数据交换的缓冲区,是存贮数据的临时地方,一般读写性能较高。

怎么防止缓存穿透?

缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库,给数据库带来巨大压力。

常见的解决方案有两种:

缓存空对象

客户端第一次请求是,发现数据库中数据不存在,在缓存中设置该值为空串,后面的请求中若发现缓存中存储的值为空串直接返回空串,不在查询数据库。(缓存需要设置一定时间内过期,防止数据库中有数据后缓存仍然为空。或者在插入数据时,清空缓存)

  •         优点:实现简单,维护方便
  •         缺点:额外的内存消耗,可能造成短期的不一致

    /*** 设置空值解决缓存穿透*/public Shop queryWithPassThrough(Long id){//先从redis查询商铺缓存,若存在,从redis中返回,否则查询数据库,存在写入redis,并返回String shopJson = stringRedisTemplate.opsForValue().get("cache:shop:" + id);if(StringUtils.isNotBlank(shopJson)){Shop shop = JSONUtil.toBean(shopJson, Shop.class);return shop;}//判断命中的是否为空,防止缓存穿透if(shopJson==null){ //若为null,说明redis中数据为空字符串,说明mysql数据库也没有数据return null;}//redis不存在,查询数据库Shop shop = getById(id);if(shop==null){//将空值写入redisstringRedisTemplate.opsForValue().set("cache:shop:"+id,"",30, TimeUnit.MINUTES);return null;}stringRedisTemplate.opsForValue().set("cache:shop:"+id,JSONUtil.toJsonStr(shop));return shop;}

布隆过滤

  •      优点:内存占用较少,没有多余key
  •      缺点:实现复杂、存在误判可能

其他方案:

        •增强id的复杂度,避免被猜测id规律

        •做好数据的基础格式校验

        •加强用户权限校验

        •做好热点参数的限流

为什么会出现缓存雪崩?

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。

解决方案:

  • 给不同的Key的TTL添加随机值
  • 利用Redis集群提高服务的可用性
  • 给缓存业务添加降级限流策略
  • 给业务添加多级缓存

如何解决缓存击穿?

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。

常见的解决方案有两种:

互斥锁

 在高并发环境下,当有一个线程获得锁访问数据库时,其他线程等待。假如业务A需要获取缓存A和缓存B,而业务B需要获取缓存B和缓存A。此时业务A已经获取了缓存A的锁正在等待缓存B,而业务B获取了缓存B的锁等待缓存A,就出现了互相等待的情况,产生死锁。

        优点:没有额外的内存消耗,保证一致性,实现简单

        缺点:线程需要等待,性能受影响,可能有死锁风险

   /*** 在设置空值,已经解决缓存穿透的基础上,添加互斥锁解决缓存击穿*/public Shop queryWithMutex (Long id){//先从redis查询商铺缓存,若存在,从redis中返回,否则查询数据库,存在写入redis,并返回String shopJson = stringRedisTemplate.opsForValue().get("cache:shop:" + id);if(StringUtils.isNotBlank(shopJson)){Shop shop = JSONUtil.toBean(shopJson, Shop.class);return shop;}//判断命中的是否为空,房子缓存穿透if(shopJson==null){ //部位null,说明redis中数据为空字符串,说明mysql数据库也没有数据return null;}//redis不存在,失效缓存重建//获取互斥锁,每个店铺创建一个锁String LockKey = "lock:shop:"+id;Shop shop = null;try {boolean isLock = tryLock(LockKey);//获取锁失败,休眠重试if(!isLock){Thread.sleep(50);return queryWithMutex(id);}//获取到锁,查询数据库shop = getById(id);if(shop==null){//将空值写入redisstringRedisTemplate.opsForValue().set("cache:shop:"+id,"",30, TimeUnit.MINUTES);return null;}stringRedisTemplate.opsForValue().set("cache:shop:"+id,JSONUtil.toJsonStr(shop));}catch (InterruptedException e){throw  new RuntimeException("系统异常");}finally {//释放锁unLock(LockKey);}return shop;}/***获取锁*/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);}

逻辑过期:

        优点:线程无需等待,性能较好

        缺点:不保证一致性,有额外内存消耗,实现复杂

//线程池 
private static final ExecutorService CACHE_REBUILD_EXECUTOR = Executors.newFixedThreadPool(10);/*** 使用逻辑过期解决缓存击穿(实际上数据不会过期,故不需要考虑缓存穿透问题),使用时需要先缓存热点数据*/public Shop queryWithLogicalExpire (Long id){//先从redis查询商铺缓存,若存在,从redis中返回,否则查询数据库,存在写入redis,并返回String shopJson = stringRedisTemplate.opsForValue().get("cache:shop:" + id);//缓存中不存在,直接返回null。(热点数据,通过一般需要自行初始化到redis缓存中,一般不会出现null的情况)if(StringUtils.isBlank(shopJson)){return null;}RedisData redisData = JSONUtil.toBean(shopJson, RedisData.class);Shop shop = JSONUtil.toBean((JSONObject) redisData.getData(), Shop.class);//获取缓存数据LocalDateTime expireTime = redisData.getExpireTime();//获取缓存过期时间//判断是否过期if(expireTime.isAfter(LocalDateTime.now())){//未过期,直接返回return shop;}//过期,需要缓存重建//获取互斥锁String LockKey = "lock:shop:"+id;if(tryLock(LockKey)){//获取锁成功,开启独立线程,实现缓存重建CACHE_REBUILD_EXECUTOR.submit(() ->{//重建缓存try{this.saveShop2Redis(id,20L);}catch (Exception e){throw new RuntimeException(e);}finally {//释放锁unLock(LockKey);}});}return shop;}public void saveShop2Redis(Long id,Long expireSeconds){//查询店铺数据Shop shop = getById(id);//封装逻辑过期时间RedisData redisData = new RedisData();redisData.setData(shop);redisData.setExpireTime(LocalDateTime.now().plusMinutes(expireSeconds));//写入redisstringRedisTemplate.opsForValue().set("cache:shop:"+id,JSONUtil.toJsonStr(redisData));}/***获取锁*/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);}

全局ID生成器

如果使用数据库自增ID就存在一些问题:

  • id的规律性太明显
  • 受单表数据量的限制

全局ID生成器,是一种在分布式系统下用来生成全局唯一ID的工具,一般要满足下列特性:

为了增加ID的安全性,我们可以不直接使用Redis自增的数值,而是拼接一些其它信息:

ID的组成部分:

  • 符号位:1bit,永远为0
  • 时间戳:31bit,以秒为单位,可以使用69
  • 序列号:32bit,秒内的计数器,支持每秒产生2^32个不同ID

Redis自增ID策略:

  • 每天一个key,方便统计订单量
  • ID构造是 时间戳 + 计数器
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;@Component
public class RedisIdWorker {private StringRedisTemplate stringRedisTemplate;public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}// 2022年开始时间戳private static final long BEGIN_TIMESTAMP = 1640995200L;// 序列号位数private static final int COUNT_BITS = 32;public long nextId(String KeyPrefix) {// 1.生成时间戳LocalDateTime now = LocalDateTime.now();long nowSecond = now.toEpochSecond(ZoneOffset.UTC);long timestamp = nowSecond-BEGIN_TIMESTAMP;// 2.生成序列号String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));//自增长,返回自增序列号,key不存在会自动创建一个keylong count = stringRedisTemplate.opsForValue().increment("icr:" + KeyPrefix + ":" + date);// 3.拼接并返回// 时间戳左移32位,通过|运算,拼接序列号return timestamp << COUNT_BITS | count;}
}


文章转载自:

http://h3psPXKB.mnsts.cn
http://BXCdIdR7.mnsts.cn
http://UBEsXU6d.mnsts.cn
http://oeMi0d7E.mnsts.cn
http://IWLdq1ur.mnsts.cn
http://7iND65k0.mnsts.cn
http://zumKt2yw.mnsts.cn
http://RP8wGaCM.mnsts.cn
http://Z7A83PiE.mnsts.cn
http://pBYiCXfY.mnsts.cn
http://kr18HWLB.mnsts.cn
http://ZcAtrWXC.mnsts.cn
http://Yp0Gb6zS.mnsts.cn
http://A589HS7O.mnsts.cn
http://ScRbtSBd.mnsts.cn
http://THd5LmcF.mnsts.cn
http://LU02h1Yr.mnsts.cn
http://I3M8NPUp.mnsts.cn
http://gsJKZyFc.mnsts.cn
http://2sdhHM65.mnsts.cn
http://bC2rcjpT.mnsts.cn
http://hoPx7gLT.mnsts.cn
http://khPMK8mS.mnsts.cn
http://t7xdBXg5.mnsts.cn
http://Zx1rYNvi.mnsts.cn
http://iye771ZM.mnsts.cn
http://vr8Jn86g.mnsts.cn
http://Mmqk5aDi.mnsts.cn
http://EICE0Noj.mnsts.cn
http://JSYasSrU.mnsts.cn
http://www.dtcms.com/wzjs/763898.html

相关文章:

  • 网站公司怎么做的好处重庆品牌logo设计
  • 云主机配置网站教育培训网站有哪些
  • tk域名网站wordpress的文件夹
  • 郑州大学现代远程教育《网页设计与网站建设》课程考核要求wordpress区块链游戏
  • 值得抓取的网站深圳市龙岗区住房和建设局网站
  • 品牌宣传型企业网站兰州做网站公司
  • 网站备案地区名小程序软件开发
  • 免费外贸网站源码大连自己的网站
  • 湖北平台网站建设哪家好福田蒙派克油耗是多少
  • 不会编程 做网站茂名建设网站
  • 网站免费诊断云主机搭建多个网站
  • 响应式网站方案网络服务商英文
  • 999免费网站传奇哪里做网站比较号
  • 卓越亚马逊网站建设目的wordpress ip改成域名
  • wordpress企业主题二次开发下载优化软件
  • 广西旅游网站建设检查网站的死链接
  • 我和你99谁做的网站做网站的必要性
  • 网络调查问卷在哪个网站做我的网站模板下载 迅雷下载 迅雷下载
  • 做美食网站的模板外包公司名单
  • 做外贸仿牌网站seo网站优化课程
  • 网站和域名区别吗Wordpress is文章展示
  • 北京网站设计制作教程个人网站设计策划
  • 在国外做盗版网站关键词排名优化
  • 闵行手机网站建设微建站平台
  • 内蒙古网站建站php企业公司网站源码
  • 长宁做网站价格蓝色 宽屏 网站 模板下载
  • 宁波网站优化公司推荐win7优化设置
  • 国家建设部网站倪虹公司快速建站
  • 2015年做那个网站致富米拓网站建设教程
  • 做交网站建设部一建注册公示网站