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

会员发布网站建设金华建设监理协会网站

会员发布网站建设,金华建设监理协会网站,建立网站流程图,海外域名可以在国内访问吗缓存预热 定义 缓存预热是一种优化方案#xff0c;它可以提高用户的使用体验。 缓存预热是指在系统启动的时候#xff0c;先把查询结果预存到缓存中#xff0c;以便用户后面查询时可以直接从缓存中读取#xff0c;节省用户等待时间 实现思路 把需要缓存的方法写在初始化方…缓存预热 定义 缓存预热是一种优化方案它可以提高用户的使用体验。 缓存预热是指在系统启动的时候先把查询结果预存到缓存中以便用户后面查询时可以直接从缓存中读取节省用户等待时间 实现思路 把需要缓存的方法写在初始化方法中让程序启动时自动加载数据并缓存数据。把需要缓存的方法挂在某个页面或是后端接口上手动触发缓存预热。设置定时任务定时进行缓存预热。 解决方案 使用 PostConstruct 初始化白名单数据 缓存雪崩(大量数据同时失效/Redis 崩了没有数据了) 定义 缓存雪崩是指在短时间内大量缓存同时过期导致大量请求直接查询数据库 从而对数据库造成巨大压力严重情况下可能会导致数据库宕机 解决方案 加锁排队起到缓冲作用防止大量请求同时操作数据库但缺点是增加了系统的响应时间降低了系统的吞吐量牺牲一部分用户体验。设置二级缓存二级缓存是除了 Redis 本身的缓存再设置一层缓存当 Redis 失效后就先去查询二级缓存随机化过期时间为了避免缓存同时过期可以设置缓存时添加随机时间这样就可以极大的避免大量缓存同时失效redis 缓存集群实现高可用 主从 哨兵Redis 集群开启Redis 持久化机制 aof / rdb尽快恢复缓存集群 服务降级 Hystrix 或者 sentinel 限流 降级 // 缓存原本的失效时间 int exTime 10 * 60; // 随机数⽣成类 Random random new Random(); // 缓存设置 jedis.setex(cacheKey, exTimerandom.nextInt(1000) , value);缓存穿透(黑客攻击/空数据/穿过 Redis 和数据库) 定义 缓存穿透是指查询数据库和缓存都无数据因此每次请求都会去查询数据库 解决方案 **缓存空结果**对查询的空结果也进行缓存如果是集合可以缓存一个空的的集合如果是缓存单个对象可以字段标识来区分避免请求穿透到数据库。**布隆过滤器处理**将所有可能对应的数据为空的 key 进行统一的存放并在请求前做拦截避免请求穿透到数据库这样的方式实现起来相对麻烦比较适合命中不高但是更新不频繁的数据。双锁锁策略机制 package com.redis.redis01.service;import com.redis.redis01.bean.RedisBs; import com.redis.redis01.mapper.RedisBsMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource; import java.beans.Transient; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock;Slf4j Service public class RedisBsService {//定义key前缀/命名空间public static final String CACHE_KEY_USER user:;Autowiredprivate RedisBsMapper mapper;Resourceprivate RedisTemplateString, Object redisTemplate;private static ReentrantLock lock new ReentrantLock();/*** 业务逻辑没有写错对于中小长(qps1000)可以使用但是大厂不行大长需要采用双检加锁策略** param id* return*/Transactionalpublic RedisBs findUserById(Integer id,int type,int qps) {//qps1000if(qps1000){return qpsSmall1000(id);}//qps1000return qpsBig1000(id, type);}/*** 加强补充避免突然key失效了或者不存在的key穿透redis打爆mysql做一下预防尽量不出现缓存击穿的情况进行排队等候* param id* param type 0使用synchronized重锁1ReentrantLock轻量锁* return*/private RedisBs qpsBig1000(Integer id, int type) {RedisBs redisBs null;String key CACHE_KEY_USER id;//1先从redis里面查询如果有直接返回没有再去查mysqlredisBs (RedisBs) redisTemplate.opsForValue().get(key);if (null redisBs) {switch (type) {case 0://加锁假设请求量很大缓存过期大厂用对于高qps的优化进行加锁保证一个请求操作让外面的redis等待一下避免击穿mysqlsynchronized (RedisBsService.class) {//第二次查询缓存目的防止加锁之前刚好被其他线程缓存了redisBs (RedisBs) redisTemplate.opsForValue().get(key);if (null ! redisBs) {//查询到数据直接返回return redisBs;} else {//数据缓存//查询mysql回写到redis中redisBs mapper.findUserById(id);if (null redisBs) {// 3 redismysql都没有数据防止多次穿透(redis为防弹衣mysql为人穿透直接伤人就是直接访问mysql)优化记录这个null值的key列入黑名单或者记录或者异常return new RedisBs(-1, 当前值已经列入黑名单);}//4 mysql有回写保证数据一致性//setifabsentredisTemplate.opsForValue().setIfAbsent(key, redisBs,7l, TimeUnit.DAYS);}}break;case 1://加锁大厂用对于高qps的优化进行加锁保证一个请求操作让外面的redis等待一下避免击穿mysqllock.lock();try {//第二次查询缓存目的防止加锁之前刚好被其他线程缓存了redisBs (RedisBs) redisTemplate.opsForValue().get(key);if (null ! redisBs) {//查询到数据直接返回return redisBs;} else {//数据缓存//查询mysql回写到redis中redisBs mapper.findUserById(id);if (null redisBs) {// 3 redismysql都没有数据防止多次穿透(redis为防弹衣mysql为人穿透直接伤人就是直接访问mysql)优化记录这个null值的key列入黑名单或者记录或者异常return new RedisBs(-1, 当前值已经列入黑名单);}//4 mysql有回写保证数据一致性redisTemplate.opsForValue().set(key, redisBs);}} catch (Exception e) {e.printStackTrace();} finally {//解锁lock.unlock();}}}return redisBs;}private RedisBs qpsSmall1000(Integer id) {RedisBs redisBs null;String key CACHE_KEY_USER id;//1先从redis里面查询如果有直接返回没有再去查mysqlredisBs (RedisBs) redisTemplate.opsForValue().get(key);if (null redisBs) {//2查询mysql回写到redis中redisBs mapper.findUserById(id);if (null redisBs) {// 3 redismysql都没有数据防止多次穿透(redis为防弹衣mysql为人穿透直接伤人就是直接访问mysql)优化记录这个null值的key列入黑名单或者记录或者异常return new RedisBs(-1, 当前值已经列入黑名单);}//4 mysql有回写保证数据一致性redisTemplate.opsForValue().set(key, redisBs);}return redisBs;}}package com.redis.redis01.service;import com.google.common.collect.Lists; import com.redis.redis01.bean.RedisBs; import com.redis.redis01.mapper.RedisBsMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service;import javax.annotation.Resource; import java.util.Arrays; import java.util.List; import java.util.concurrent.locks.ReentrantLock;Slf4j Service public class BitmapService {Resourceprivate RedisTemplateString, Object redisTemplate;private static ReentrantLock lock new ReentrantLock();Autowiredprivate RedisBsMapper redisBsMapper;/*** 场景一布隆过滤器解决缓存穿透问题(null/黑客攻击)利用redisbitmap实现* 有可能有没有一定没有* 无-------------》mysql查询* 有--------》redis查询----------》有-----------》返回* 请求-----》布隆过滤器-----------》* 无-------终止** param type:0初始化1常规查询*/public void booleanFilterBitmap(int type, Integer id) {switch (type) {case 0://初始化数据for (int i 0; i 10; i) {RedisBs initBs RedisBs.builder().id(i).name(赵三 i).phone(1580080569 i).build();//1 插入数据库redisBsMapper.insert(initBs);//2 插入redisredisTemplate.opsForValue().set(customer:info i, initBs);}//3 将用户id插入布隆过滤器中,作为白名单for (int i 0; i 10; i) {String booleanKey customer:booleanFilter: i;//3.1 计算hashvalueint abs Math.abs(booleanKey.hashCode());//3.2 通过abs和2的32次方取余获得布隆过滤器/bitmap对应的下标坑位/indexlong index (long) (abs % Math.pow(2, 32));log.info(坑位:{}, index);//3.3 设置redis里面的bitmap对应类型的白名单redisTemplate.opsForValue().setBit(whiteListCustomer, index, true);}break;case 1://常规查询//1 获取当前传过来的id对应的哈希值String inputBooleanKey customer:booleanFilter: id;int abs Math.abs(inputBooleanKey.hashCode());long index (long) (abs % Math.pow(2, 32));Boolean whiteListCustomer redisTemplate.opsForValue().getBit(whiteListCustomer, index);//加入双检锁//加锁大厂用对于高qps的优化进行加锁保证一个请求操作让外面的redis等待一下避免击穿mysqllock.lock();try {if (null whiteListCustomer) {whiteListCustomer redisTemplate.opsForValue().getBit(whiteListCustomer, index);if (null ! whiteListCustomer whiteListCustomer) {//布隆过滤器中存在则可能存在//2 查找redisObject queryCustomer redisTemplate.opsForValue().get(customer:info id);if (null ! queryCustomer) {log.info(返回客户信息:{}, queryCustomer);break;} else {//3 redis没有查找mysqlRedisBs userById redisBsMapper.findUserById(id);if (null ! userById) {log.info(返回客户信息:{}, queryCustomer);redisTemplate.opsForValue().set(customer:info id, userById);break;} else {log.info(当前客户信息不存在:{}, id);break;}}} else {//redis没有去mysql中查询//3 redis没有查找mysqlRedisBs userById redisBsMapper.findUserById(id);if (null ! userById) {log.info(返回客户信息:{}, userById);redisTemplate.opsForValue().set(customer:info id, userById);break;} else {log.info(当前客户信息不存在:{}, id);break;}}}} finally {lock.unlock();}log.info(当前客户信息不存在:{}, id);break;default:break;}} }缓存击穿(热点数据/刚失效/定点打击) 定义 缓存击穿是指某个经常使用的缓存在某一个时刻恰好失效了例如缓存过期并且此时刚好有大量的并发请求这些请求就会给数据库造成巨大的压力 解决方案 **加锁排队**和处理缓存雪崩的加锁类似都是在查询数据库的时候加锁排队缓存操作请求以此来减少服务器的运行压力。**设置永不过时**对于某些经常使用的缓存我们可以设置为永不过期这样就能保证缓存的稳定性但要注意在数据更改后要及时更新此热点缓存否则就会造成查询结果误差。 总结 脑裂 分布式session 分布式锁 分布式锁需要的条件和刚需 独占性 任何时刻有且只有一个线程持有这个锁 高可用 若redis集群环境下不能因为某一个节点挂了而出现获取锁和释放锁失败的情况高并发请求下依旧性能很好 防死锁 不能出现死锁问题必须有超时重试机制或者撤销操作有个终止跳出的途径 不乱抢 防止张冠李戴只能解锁自己的锁不能把别人的锁给释放了 重入性 同一节点的同一线程如果获得锁之后他可以再次获取这个锁 v 8.0 其实面对不是特别高的并发场景足够用了单机redis也够用了 要兼顾锁的重入性 setnx不满足了需要hash结构的hset 上锁和解锁都用 Lua 脚本来实现原子性引入工厂模式 DistributedLockFactory 实现 Lock 接口实现redis的可重入锁 lock() 加锁的关键逻辑 加锁 实际上就是在redis中给Key键设置一个值为避免死锁并给定一个过期时间自旋续期 unlock() 解锁关键逻辑将 Key 键删除但是也不能乱删只能自己删自己的锁 实现自动续期功能的完善后台自定义扫描程序如果规定时间内没有完成业务逻辑会调用加钟自动续期的脚本 Autowiredprivate DistributedLockFactory distributedLockFactory;/*** v8.0 实现自动续期功能的完善后台自定义扫描程序如果规定时间内没有完成业务逻辑会调用加钟自动续期的脚本** return*/public String sale() {String retMessage ;Lock redisLock distributedLockFactory.getDistributedLock(redis);redisLock.lock();try {//1 查询库存信息String result stringRedisTemplate.opsForValue().get(inventory001);//2 判断库存是否足够Integer inventoryNumber result null ? 0 : Integer.parseInt(result);//3 扣减库存if (inventoryNumber 0) {stringRedisTemplate.opsForValue().set(inventory001, String.valueOf(--inventoryNumber));retMessage 成功卖出一个商品库存剩余: inventoryNumber;// 演示自动续期的的功能 // try { // TimeUnit.SECONDS.sleep(120); // } catch (InterruptedException e) { // e.printStackTrace(); // }} else {retMessage 商品卖完了o(╥﹏╥)o;}} finally {redisLock.unlock();}return retMessage \t 服务端口号 port;}/*** v7.0 兼顾锁的可重入性 setnx不满足了需要hash结构的hset* 上锁和解锁都用 Lua 脚本实现原子性* 引入工厂模式 DistributedLockFactory 实现Lock接口 实现 redis的可重入锁** return*/ // //private Lock redisDistributedLock new RedisDistributedLock(stringRedisTemplate, xfcyRedisLock); // // public String sale() { // String retMessage ; // // Lock redisLock distributedLockFactory.getDistributedLock(redis); // redisLock.lock(); // // //redisDistributedLock.lock(); // try { // //1 查询库存信息 // String result stringRedisTemplate.opsForValue().get(inventory001); // //2 判断库存是否足够 // Integer inventoryNumber result null ? 0 : Integer.parseInt(result); // //3 扣减库存 // if (inventoryNumber 0) { // stringRedisTemplate.opsForValue().set(inventory001, String.valueOf(--inventoryNumber)); // retMessage 成功卖出一个商品库存剩余: inventoryNumber; // System.out.println(retMessage); // // // 测试可重入性 // //testReEntry(); // // } else { // retMessage 商品卖完了o(╥﹏╥)o; // } // } finally { // redisLock.unlock(); // //redisDistributedLock.unlock(); // } // return retMessage \t 服务端口号 port; // } // // private void testReEntry() { // Lock redisLock distributedLockFactory.getDistributedLock(redis); // redisLock.lock(); // // //redisDistributedLock.lock(); // try { // System.out.println(测试可重入锁); // } finally { // redisLock.unlock(); // //redisDistributedLock.unlock(); // } // } package com.xfcy.mylock;import cn.hutool.core.util.IdUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component;import java.util.concurrent.locks.Lock;/*** author 晓风残月Lx* date 2023/4/1 22:14*/ Component public class DistributedLockFactory {Autowiredprivate StringRedisTemplate stringRedisTemplate;private String lockName;private String uuidValue;public DistributedLockFactory() {this.uuidValue IdUtil.simpleUUID();}public Lock getDistributedLock(String lockType) {if (lockType null) {return null;}if (lockType.equalsIgnoreCase(REDIS)) {this.lockName xfcyRedisLock;return new RedisDistributedLock(stringRedisTemplate, lockName, uuidValue);}else if (lockType.equalsIgnoreCase(ZOOKEEPER)) {this.lockName xfcyZookeeperLock;// TODO zoookeeper 版本的分布式锁return null;}else if (lockType.equalsIgnoreCase(MYSQL)){this.lockName xfcyMysqlLock;// TODO MYSQL 版本的分布式锁return null;}return null;}} package com.xfcy.mylock;import cn.hutool.core.util.IdUtil; import com.sun.org.apache.xpath.internal.operations.Bool; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript;import java.util.Arrays; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock;/*** author 晓风残月Lx* date 2023/4/1 21:38* 自研的redis分布式锁实现 Lock 接口*/ // Component 引入DistributedLockFactory工厂模式从工厂获得即可 public class RedisDistributedLock implements Lock {Autowiredprivate StringRedisTemplate stringRedisTemplate;private String lockName; // KEYS[1]private String uuidValue; // ARGV[1]private long expireTime; // ARGV[2]public RedisDistributedLock(StringRedisTemplate stringRedisTemplate, String lockName, String uuidValue) {this.stringRedisTemplate stringRedisTemplate;this.lockName lockName;this.uuidValue uuidValue : Thread.currentThread().getId();this.expireTime 30L;}Overridepublic void lock() {tryLock();}Overridepublic boolean tryLock() {try {tryLock(-1L, TimeUnit.SECONDS);} catch (InterruptedException e) {e.printStackTrace();}return false;}Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {if (time -1L) {String script if redis.call(exists,KEYS[1]) 0 or redis.call(hexists,KEYS[1],ARGV[1]) 1 then redis.call(hincrby,KEYS[1],ARGV[1],1) redis.call(expire,KEYS[1],ARGV[2]) return 1 else return 0 end;System.out.println(lockName lockName \t uuidValue uuidValue);while (!stringRedisTemplate.execute(new DefaultRedisScript(script, Boolean.class), Arrays.asList(lockName), uuidValue, String.valueOf(expireTime))) {// 暂停 60msThread.sleep(60);}// 新建一个后台扫描程序来监视key目前的ttl是否到我们规定的 1/2 1/3 来实现续期resetExpire();return true;}return false;}Overridepublic void unlock() {String script if redis.call(HEXISTS,KEYS[1],ARGV[1]) 0 then return nil elseif redis.call(HINCRBY,KEYS[1],ARGV[1],-1) 0 then return redis.call(del,KEYS[1]) else return 0 end;// nil false 1 true 0 falseLong flag stringRedisTemplate.execute(new DefaultRedisScript(script, Long.class), Arrays.asList(lockName), uuidValue, String.valueOf(expireTime));if (null flag) {throw new RuntimeException(this lock doesnt exists0);}}private void resetExpire() {String script if redis.call(HEXISTS,KEYS[1],ARGV[1]) 1 then return redis.call(expire,KEYS[1],ARGV[2]) else return 0 end;new Timer().schedule(new TimerTask() {Overridepublic void run() {if (stringRedisTemplate.execute(new DefaultRedisScript(script, Boolean.class), Arrays.asList(lockName), uuidValue, String.valueOf(expireTime))) {resetExpire();}}}, (this.expireTime * 1000) / 3);}// 下面两个用不上// 下面两个用不上// 下面两个用不上Overridepublic void lockInterruptibly() throws InterruptedException {}Overridepublic Condition newCondition() {return null;} }
http://www.pierceye.com/news/137793/

相关文章:

  • 烟台建网站公司哪家好辽源做网站的公司
  • 建设企业网站地址网站空间 虚拟主机
  • h5网站模板免费下载网页源码提取工具
  • 网站设计和网页设计建网站必备软件
  • 中国建设银行上海市分行网站音乐网站开发可行性分析
  • 如何用天地图做网站做面包有哪些网站知乎
  • 买了域名之后怎么建设网站做网站一年赚一千万
  • 跟网站开发公司签合同主要要点个人网站logo需要备案吗
  • 免费询盘网站自我介绍ppt模板
  • 中国会议营销网站怎么做找优惠券的网站
  • 做网站的那些事wordpress改写
  • 仿造整个网站呼市网站建设公司
  • 网站被黑客入侵怎么办企业文化墙设计网站推荐
  • 建设网站的群婚礼婚庆网站建设需求分析
  • 全椒县城乡建设局网站网站怎么做营销策划
  • 响应式网站制作流程河北企业建网站
  • 常州新北区有做淘宝网站策划的吗什么建设网站
  • 成品网站源码68w68游戏wordpress php推送示例
  • 博优云软件官方网站wordpress 个人
  • 登封 网站建设烟台网站关键词推广
  • 深圳实惠的专业建站公司淘宝券商城网站制作
  • 珠海手机网站建设成都设计网站
  • 网站mp3播放器代码国家企业信息系统官方
  • 江西建设银行招聘网站pc网站还有必要做吗
  • 网站建设几个要素做网站需要学会什么软件
  • 做视频网站什么平台好站酷设计网站首页
  • 班级网站设计论文网站多国语言
  • 网站制作评价标准网站服务器怎么收费
  • 怎么建立自己的网站平台多少钱wordpress自建菜单
  • 深圳购物网站如何制作外贸网站 wordpress