当前位置: 首页 > 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.huolong8.cn/news/458496/

相关文章:

  • 代做广联达 的网站网站出现弹窗
  • php与python做网站兰州seo整站优化服务商
  • 2017主流网站开发语言wordpress 用户组权限设置
  • 怎么找人做淘宝网站吗网上商城网站建设体会
  • 做网站用多大的服务器广州注册公司必看
  • 西瓜网站建设wordpress不自动安装插件
  • 东莞手机网站建设网站怎么做视频背景
  • 深圳建设网站公司哪家好在线工具seo
  • 太原北京网站建设学做面包的网站
  • 芜湖网站建设怎么做五指山住房建设局网站
  • 网站管理员怎么做板块建设商城网站都有什么功能模块
  • 怎么做可以访问网站连接加密短视频策划模板
  • 如何查询网站的备案号网站建设构成
  • 网站建设论文任务书网站建好了 如何推广
  • 式网站四川seo技术培训
  • 做网站怎么引用字体怎样做网站吸引人
  • 电话用网站做综合布线郑州网站排名优化外包
  • 北京朝阳做网站wordpress设置数据库密码
  • 网站被百度降权北京平面设计网站
  • 做甲基化黑点的网站如何建个人网站教程
  • 做网站 淘宝公司企业邮箱优势
  • 徐汇做网站写作网站哪个能得稿费
  • 潍坊网站设计好处长沙专业的网站设计
  • 坂田网站建设费用明细现在什么推广效果好呢
  • 做个网站在线投稿页面wordpress主题如何导入演示
  • 网站建设与网页制作论文深圳商城网站建设
  • 做网站用什么后缀格式做好游戏开发网
  • 专门做库存的网站太原关键词网站排名
  • 做电子相册的大网站使用html制作个人主页
  • 建筑工程行业网站建设方案杭州定制网站