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

网站建设的电销网站建设与管理专业自我评价

网站建设的电销,网站建设与管理专业自我评价,接app推广的单子在哪接,企业公司简介范文Redis缓存的基本概念和使用 什么是缓存Redis缓存缓存更新策略缓存穿透缓存雪崩缓存击穿缓存工具类封装 什么是缓存 缓存时数据交换的缓冲区#xff0c;存储数据的临时区#xff0c;读写性能较好。 例如计算机的三级缓存。CPU的计算速度超过内存的读写速度#xff0c;为了平… Redis缓存的基本概念和使用 什么是缓存Redis缓存缓存更新策略缓存穿透缓存雪崩缓存击穿缓存工具类封装 什么是缓存 缓存时数据交换的缓冲区存储数据的临时区读写性能较好。 例如计算机的三级缓存。CPU的计算速度超过内存的读写速度为了平衡两者速度使用了三级缓存把经常需要读写的数据放到三级缓存中。 例如DNS缓存浏览器缓存nginx缓存JVM进程缓存Redis缓存数据库缓存等。 缓存作用 1、降低后端负载。 2、提高读写效率降低响应时间。 缓存成本 1、缓存一致性。 2、复杂度。例如缓存穿透缓存击穿缓存雪崩等问题使代码复杂度提升。 3、运维成本。 Redis缓存 客户端先请求Redis缓存命中缓存则直接返回没有命中再请求数据库若数据不存在则返回404如果数据存在则把新数据写到Redis缓存中最后返回数据。 例如店铺信息缓存如下 Service public class ShopServiceImpl extends ServiceImplShopMapper, Shop implements IShopService {Autowiredprivate StringRedisTemplate stringRedisTemplate;Overridepublic Object queryById(Long id) {String key CACHE_SHOP_KEY id;String shopJson stringRedisTemplate.opsForValue().get(key);if (! StrUtil.isEmpty(shopJson)) {Shop shop JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}Shop shop getById(id);if (shop null) {return Result.fail(店铺不存在);}stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop));stringRedisTemplate.expire(key, CACHE_SHOP_TTL, TimeUnit.MINUTES);return Result.ok(shop);} }缓存更新策略 1、内存淘汰 使用Redis的内存淘汰策略内存不足时自己淘汰部分数据下次查询时更新缓存。 应用于一致性要求低几乎不需要维护成本的场景。 2、超时剔除 给数据添加过期时间到期后自动删除缓存下次查询时更新缓存。 应用于一致性要求一般维护成本较低的场景。 3、主动更新 编写业务逻辑在修改数据库数据时更新缓存。 适用一致性较好维护成本较高的场景。 业务场景 低一致性需求使用内存淘汰比如店铺类型的查询缓存。 高一致性需求使用主动更新并添加超时剔除作为兜底例如店铺详情的缓存。 主动更新策略有哪些 1、旁路缓存Cache Aside 缓存调用者在更新数据库时更新缓存。相对可控实际使用较多。 2、读穿/写穿Read/Write Through 缓存和数据库整合成一个服务调用者无需关心数据库和缓存一致性。 3、读后写Write Behind Caching 调用者只操作缓存其他线程异步地将数据从缓存持久化到数据库。 旁路缓存具体方案 1、删除缓存还是更新缓存 使用删除缓存因为如果使用更新缓存每次更新数据库都要更新缓存如果中间没有读取那么无效写操作太多。 2、如何保证操作数据库和缓存的同时成功和失败 单体系统将数据库和缓存的操作放在一个事务中。 分布式系统使用TCC等分布式事务。 3、先操作缓存还是先操作数据库 根据更新数据库时间更慢删除缓存时间更快。 如果先删缓存后更新数据库。 线程1刚把缓存删除还没有更新缓存线程2查询缓存未命中会查询数据库旧值并且更新到缓存中导致缓存数据是旧值。 如果先更新数据库再删除缓存。 缓存失效线程1查询缓存未命中查询到数据库线程2刚好修改数据库并且删除缓存线程2将旧数据写入缓存。 发生概率较小因为写入缓存时间较短需要在线程1查询完数据库写入缓存前把线程2的更新数据库和删除缓存都完成概率较小。 例如实现查询商铺的查询缓存添加主动更新和超时剔除策略。 1、查询时如果缓存未命中则查询数据库并且写入缓存设置超时时间。 2、更新时先修改数据库后删除缓存。 Override public Object queryById(Long id) {String key CACHE_SHOP_KEY id;String shopJson stringRedisTemplate.opsForValue().get(key);if (! StrUtil.isEmpty(shopJson)) {Shop shop JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}Shop shop getById(id);if (shop null) {return Result.fail(店铺不存在);}stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);return Result.ok(shop); }Override Transactional public Result updateShop(Shop shop) {Long id shop.getId();if (id null) {return Result.fail(店铺id不能为空);}updateById(shop);String key CACHE_SHOP_KEY id;stringRedisTemplate.delete(key);return Result.ok(); }缓存穿透 缓存穿透客户端请求的数据在缓存和数据库中都不存在缓存永远不会生效会打到数据库。 解决 1、缓存空对象。 优点实现简单。 缺点额外内存消耗可能有短期数据不一致。 2、布隆过滤器。 优点内存消耗更小。 缺点实现复杂存在误判不能解决删除元素问题。 编码实现这里使用缓存空对象。 Override public Object queryById(Long id) {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);}//命中之前缓存的空字符串if (.equals(shopJson)) {return Result.fail(店铺不存在);}Shop shop getById(id);if (shop null) {//写入空值解决缓存穿透stringRedisTemplate.opsForValue().set(key, , CACHE_NULL_TTL, TimeUnit.MINUTES);return Result.fail(店铺不存在);}stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);return Result.ok(shop); }缓存雪崩 缓存雪崩同一时段大量缓存key同时失效或者Redis服务宕机导致大量请求达到数据库。 解决 1、给不同key的过期时间ttl设置随机值。 2、使用Redis集群提高服务可用性。 3、添加降级限流策略。 4、添加多级缓存。 缓存击穿 缓存击穿热点key突然失效无数请求瞬间达到数据库带来巨大冲击。 解决 1、互斥锁。重建缓存时使用一个锁保证只有一个线程能重建缓存。可以结合两次if判断进行双重检查防止后面线程获取锁的开销。 优点实现简单保证一致性。 缺点性能受影响可能有死锁风险。 2、逻辑过期。即不设置ttlkey永不过期但是在value中设置expire字段。当线程1发现key过期时拿到互斥锁并开启新线程重建缓存。其他线程获取锁失败时直接拿旧数据。 优点线程无需等待性能较好。 缺点一致性更低有额外内存消耗。 区别逻辑过期也使用了互斥锁但是它和互斥锁的区别在于过期数据依然在Redis中因此其他线程可以先使用旧数据。 例子根据id查询商铺使用互斥锁解决缓存击穿。 public Shop queryWithMutex(Long id) {String key CACHE_SHOP_KEY id;String shopJson stringRedisTemplate.opsForValue().get(key);if (StrUtil.isNotBlank(shopJson)) {return JSONUtil.toBean(shopJson, Shop.class);}//命中之前缓存的空字符串解决缓存穿透if (.equals(shopJson)) {return null;}Shop shop null;String lockKey LOCK_SHOP_KEY id;try {while (!tryLock(lockKey)) {Thread.sleep(50);}//双重检查shopJson stringRedisTemplate.opsForValue().get(key);if (StrUtil.isNotBlank(shopJson)) {return JSONUtil.toBean(shopJson, Shop.class);}//命中之前缓存的空字符串解决缓存穿透if (.equals(shopJson)) {return null;}shop getById(id);if (shop null) {//写入空值解决缓存穿透stringRedisTemplate.opsForValue().set(key, , CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {unLock(lockKey);}return shop;}例子根据id查询商铺逻辑过期解决缓存击穿例子 public class RedisData {private LocalDateTime expireTime;private Object data; } public void saveShop2Redis(Long id, Long expireSeconds) {Shop shop getById(id);RedisData redisData new RedisData();redisData.setData(shop);redisData.setExpireTime(LocalDateTime.now().plusSeconds(expireSeconds));stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY id, JSONUtil.toJsonStr(redisData)); }//逻辑过期解决缓存击穿 public Shop queryWithLogicalExpire(Long id) {String key CACHE_SHOP_KEY id;String shopJson stringRedisTemplate.opsForValue().get(key);if (StrUtil.isBlank(shopJson)) {return null;}RedisData redisData JSONUtil.toBean(shopJson, RedisData.class);LocalDateTime expireTime redisData.getExpireTime();JSONObject jsonObject (JSONObject) redisData.getData();Shop shop JSONUtil.toBean(jsonObject, Shop.class);if (expireTime.isAfter(LocalDateTime.now())) {return shop;}String lockKey LOCK_SHOP_KEY id;if (tryLock(lockKey)) {CACHE_REBUILD_EXECUTOR.execute(()-{try {saveShop2Redis(id, 30L);} catch (Exception e) {throw new RuntimeException(e);} finally {unLock(lockKey);}});}return shop; }缓存工具类封装 缓存穿透缓存击穿缓存雪崩等业务逻辑较复杂如果每次使用缓存都需要写这部分代码可以考虑把这部分代码封装成一个工具类。 方法1将Java对象序列化成JSON字符串并且存储在string类型的Redis中并且可以设置过期时间。 方法2将Java对象序列化成JSON字符串并且存储在string类型的Redis中可以设置逻辑过期时间解决缓存击穿问题。 方法3根据指定key查询缓存并且反序列化成指定类型利用缓存空值的方式解决缓存穿透。 方法4根据指定key查询缓存并且反序列化成执行类型利用逻辑过期解决缓存击穿。 Slf4j Component public class CacheClient {private final StringRedisTemplate stringRedisTemplate;public CacheClient(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate;}private static final ExecutorService CACHE_REBUILD_EXECUTOR Executors.newFixedThreadPool(10);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)));stringRedisTemplate.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;String json stringRedisTemplate.opsForValue().get(key);if (StrUtil.isNotBlank(json)) {return JSONUtil.toBean(json, type);}if (.equals(json)) {return null;}R r dbFallBack.apply(id);if (r null) {//写入空值解决缓存穿透stringRedisTemplate.opsForValue().set(key, , CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}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;String json stringRedisTemplate.opsForValue().get(key);if (StrUtil.isBlank(json)) {return null;}RedisData redisData JSONUtil.toBean(json, RedisData.class);LocalDateTime expireTime redisData.getExpireTime();JSONObject jsonObject (JSONObject) redisData.getData();R r JSONUtil.toBean(jsonObject, type);if (expireTime.isAfter(LocalDateTime.now())) {return r;}String lockKey LOCK_SHOP_KEY id;if (tryLock(lockKey)) {CACHE_REBUILD_EXECUTOR.execute(()-{try {R r1 dbFallBack.apply(id);setWithLogicalExpire(key, r1, time, unit);} catch (Exception e) {throw new RuntimeException(e);} finally {unLock(lockKey);}});}return r;}private boolean tryLock(String key) {Boolean flag stringRedisTemplate.opsForValue().setIfAbsent(key, 1, LOCK_SHOP_TTL, TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);}private void unLock(String key) {stringRedisTemplate.delete(key);} }
http://www.w-s-a.com/news/868826/

相关文章:

  • 企业网站改自适应蛋糕方案网站建设
  • 网站开发技术职责网站升级中html
  • 天网网站建设百度权重高的网站
  • 明年做哪些网站致富网站站长 感受
  • 东莞营销网站建设优化怎么做微信网站推广
  • 网站建设一个多少钱php网站服务器怎么来
  • 引流用的电影网站怎么做2012服务器如何做网站
  • 什么网站可以做推广广州安全信息教育平台
  • 网站开发具备的相关知识wordpress简约文字主题
  • asp网站伪静态文件下载seo外包公司哪家好
  • 淘宝客网站根目录怎么建个废品网站
  • 网站备案更改需要多久百度免费网站空间
  • 外发加工是否有专门的网站wordpress主页 摘要
  • 企业网站优化系统浙江建设信息港证书查询
  • 很多年前的51网站如何做跨境电商需要哪些条件
  • 网站建设中 请稍后访问互联网营销设计
  • 软文网站名称用户浏览网站的方式
  • 大兴模版网站搭建哪家好网站建设与管理管理课程
  • 四川成都网站制作微信广告平台推广
  • 网站价格网页制作网站开发实训步骤
  • cms 导航网站鹤壁做网站价格
  • 微信营销软件免费版郑州关键词优化费用
  • 邢台专业做网站哪家好临沂网站建设中企动力
  • 建设网站是主营成本吗wordpress 后台
  • 猎头可以做单的网站企业网站建设
  • 建小程序需要网站吗在putty上怎样安装wordpress
  • 天津智能网站建设找哪家WordPress相册插件pro
  • 电脑网站页面怎么调大小济宁网站建设软件开发
  • 亿玛酷网站建设广州增城区最新消息
  • 企业网站视频栏目建设方案中企动力网站模板