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

国外的包装设计网站如何避免网站被降权

国外的包装设计网站,如何避免网站被降权,柳州网站建站费用,网站的宣传推广方式缓存有很多种#xff0c;如CPU 缓存、磁盘缓存、浏览器缓存等#xff1b;本文主要针对后端系统的缓存#xff0c;也就是将程序或系统经常要使用的对象存在内存中#xff0c;以便在使用时可以快速调用#xff0c;避免加载数据或者创建重复的实例#xff0c;以达到减少系统…缓存有很多种如CPU 缓存、磁盘缓存、浏览器缓存等本文主要针对后端系统的缓存也就是将程序或系统经常要使用的对象存在内存中以便在使用时可以快速调用避免加载数据或者创建重复的实例以达到减少系统开销提高系统效率的目的。 粉丝福利 免费领取C/C 开发学习资料包、技术视频/代码1000道大厂面试题内容包括C基础网络编程数据库中间件后端开发/音视频开发/Qt开发/游戏开发/Linuxn内核等进阶学习资料和最佳学习路线↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓ 为什么需要缓存 我觉得操作系统里面讲高速缓存CPU Cache的一句话特别好 为什么要使用CPU Cache 因为CPU 和内存访问性能的差距非常大为了弥补两者之间的性能差异充分利用 CPU现代 CPU 中引入了高速缓存(CPU Cache)。 因为我们一般都会把数据存放在关系型数据库中不管数据库的性能有多么好受限于磁盘IO性能和远程网络的原因一个简单的查询也要消耗毫秒级的时间这样我们的 QPS 就会被数据库的性能所限制。 而内存的性能高于磁盘也没有远程网络的花费。如果恰好这些数据的数据量不大不经常变动而且访问频繁。那么就非常适合引入缓存。 总结一下缓存使用场景数据不常变更且查询比较频繁是最好的场景如果查询量不够大或者数据变动太频繁缓存使用的意义不大甚至可能适得其反。 缓存的类型 常用的缓存可以分为内部缓存和外部缓存。 内部缓存是指存放在运行实例内部并使用实例内存的缓存这种缓存可以使用代码直接访问。 外部缓存是指存放在运行实例外部的缓存通常是通过网络获取反序列化后进行访问。 一般来说对于不需要实例间同步的都更加推荐内部缓存因为内部缓存有访问方便性能好的特点需要实例间同步的数据可以使用外部缓存。 内部缓存 内部缓存有容量的限制毕竟还是在 JVM 里的存放的数据总量不能超出内存容量。 本地缓存的优点 直接使用内存速度快通常存取的性能可以达到每秒千万级可以直接使用 Java 对象存取 本地缓存的缺点 数据保存在当前实例中无法共享重启应用会丢失 最简单内部缓存-Map 对于字典型的数据在项目启动的时候加载到 Map 中程序就可以使用了也很容易更新。 MapString, String configs Maps.newHashMap();public void reloadConfigs(){configs loadConfigFromDB();}public String getConfigs(String key){return configs.getOrDefault(key, null);} 但是JDK自带的Map做缓存存在一定的问题 1、hashmap的容量理论上是无上限的内存无限的情况下如果缓存太大会严重的占用内存甚至导致OutOfMemory异常因此应该限制缓存的容量容量达到上限后采取合适的淘汰策略。 有准备面试的童鞋应该知道这就是面试中常见的实现LRU缓存。 实现方式一可以通过继承LinkedHashMap重写removeEldestEntry()方法实现。 class LRUCache extends LinkedHashMapInteger, Integer{private int capacity;public LRUCache(int capacity) {super(capacity, 0.75F, true);this.capacity capacity;}public int get(int key) {return super.getOrDefault(key, -1);}public void put(int key, int value) {super.put(key, value);}Overrideprotected boolean removeEldestEntry(Map.EntryInteger, Integer eldest) {return size() capacity; } } 实现方式二通过HashMap加双向链表的方式实现。 public class LRUCache {class DLinkedNode {int key;int value;DLinkedNode prev;DLinkedNode next;public DLinkedNode() {}public DLinkedNode(int key, int value) {key key; value value;}}private MapInteger, DLinkedNode cache new HashMapInteger, DLinkedNode();private int size;private int capacity;private DLinkedNode head, tail;public LRUCache(int capacity) {this.size 0;this.capacity capacity;// 使用伪头部和伪尾部节点head new DLinkedNode();tail new DLinkedNode();head.next tail;tail.prev head;}public int get(int key) {DLinkedNode node cache.get(key);if (node null) {return -1;}// 如果 key 存在先通过哈希表定位再移到头部moveToHead(node);return node.value;}public void put(int key, int value) {DLinkedNode node cache.get(key);if (node null) {// 如果 key 不存在创建一个新的节点DLinkedNode newNode new DLinkedNode(key, value);// 添加进哈希表cache.put(key, newNode);// 添加至双向链表的头部addToHead(newNode);size;if (size capacity) {// 如果超出容量删除双向链表的尾部节点DLinkedNode tail removeTail();// 删除哈希表中对应的项cache.remove(tail.key);--size;}}else {// 如果 key 存在先通过哈希表定位再修改 value并移到头部node.value value;moveToHead(node);}}private void addToHead(DLinkedNode node) {node.prev head;node.next head.next;head.next.prev node;head.next node;}private void removeNode(DLinkedNode node) {node.prev.next node.next;node.next.prev node.prev;}private void moveToHead(DLinkedNode node) {removeNode(node);addToHead(node);}private DLinkedNode removeTail() {DLinkedNode res tail.prev;removeNode(res);return res;} } 2、无法设置过期时间。这一点是非常致命的我们在大多数场景都希望缓存可以在合理的时间后自动失效。 3、并发安全。HashMap、LinkedHashMap都是非并发安全的集合类型。所以应该使用ConcurrentHashMap。 使用ConcurrentHashMap、ReentrantLock 和ScheduledThreadPoolExecutor可以实现带过期时间线程安全的缓存设计。 4、清除数据时的回调通知。 由于代码篇幅过长见附录1 功能强大的内部缓存-Guava Cache 如果需要缓存有强大的性能或者对缓存有更多的控制可以使用 Guava 里的 Cache 组件。 它是 Guava 中的缓存工具包是非常简单易用且功能强大的 JVM 内缓存。 1、支持多种缓存过期策略基于容量回收、定时回收、基于引用回收 2、自动加载 3、显示清除缓存个别、批量、全量清除 4、移除监听器 5、统计功能缓存命中率加载新值的平均时间缓存项被回收的总数 LoadingCacheString, String configs CacheBuilder.newBuilder().maximumSize(1000) // 设置最大大小.expireAfterWrite(10, TimeUnit.MINUTES) // 设置过期时间 10分钟.build(new CacheLoaderString, String() {// 加载缓存内容public String load(String key) throws Exception {return getConfigFromDB(key);}public MapString, String loadAll() throws Exception {return loadConfigFromDB();}});//CacheLoader.loadAll// 获取某个key的值try {return configs.get(key);} catch (ExecutionException e) {throw new OtherException(e.getCause());}// 显式的放入缓存configs.put(key, value)// 个别清除缓存configs.invalidate(key)// 批量清除缓存configs.invalidateAll(keys)// 清除所有缓存项configs.invalidateAll() Guava Cache的使用 1、创建加载cache 两种方法 CacheLoader和Callable。 LoadingCache userCache CacheBuilder.newBuilder().maximumSize(100).expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader() {Overridepublic Object load(Object name) throws Exception {return getIdFromDBByName(name);}}); CacheString, String cache CacheBuilder.newBuilder().maximumSize(100).expireAfterAccess(30, TimeUnit.MINUTES).build(); String resultVal cache.get(hello, new CallableString() {Overridepublic String call() throws Exception {return hello heitao;} }); 以上两种都实现了一种逻辑先取缓存——娶不到再执行load 或者call方法来娶。 简单比较CacheLoader 是按key统一加载所有娶不到的统一执行一种load逻辑而callable方法允许在get的时候根据指定key值执行对应的call方法。 在使用缓存前拍拍自己的四两胸肌问自己一个问题有没有【默认方法】来加载或计算与键关联的值如果有的话你应当使用CacheLoader。如果没有或者想要覆盖默认的加载运算。你应该在调用get时传入一个Callable实例。 2、添加、插入key get : 要么返回已经缓存的值要么使用CacheLoader向缓存原子地加载新值 getUncheckedCacheLoader 会抛异常定义的CacheLoader没有声明任何检查型异常则可以 getUnchecked 查找缓存反之不能 getAll 方法用来执行批量查询 put : 向缓存显式插入值Cache.asMap()也能修改值但不具原子性 getIfPresent 该方法只是简单的把Guava Cache当作Map的替代品不执行load方法 3、清除key guava cache 自带 清除机制但仍旧可以手动清除 个别清除Cache.invalidate(key) 批量清除Cache.invalidateAll(keys) 清除所有缓存项Cache.invalidateAll() 4 refresh和expire刷新机制 expireAfterAccess(30, TimeUnit.MINUTES ) // 30min内没有被读或写就会被回收 expireAfterWrite(30, TimeUnit.MINUTES ) // 30min内没有没有更新就会被回收 refreshAfterAccess(30, TimeUnit.MINUTES) //上一次更新操作30min后再刷新 注意和redis的惰性回收机制一样 30min内没有被读或写就会被回收” 不等于 “30min内会被回收” 因为真正的过期/刷新操作是在key被读或写时发生的。 只有发生“取值”操作才会执行load然而为了防止“缓存穿透”在多线程的环境下任何时刻只允许一个线程操作执行load操作 。 但在执行load操作这个步骤expire 与 refresh 的线程机制不同 expire 在load 阶段——同步机制当前线程load未完成其他线程呈阻塞状态待当前线程load完成其他线程均需进行”获得锁--获得值--释放锁“的过程。这种方法会让性能有一定的损耗。 refresh 在load阶段——异步机制 当前线程load未完成其他线程仍可以取原来的值等当前线程load完成后下次某线程再取值时会判断系统时间间隔是否时超过设定refresh时间来决定是否设定新值。所以refresh机制的特点是设定30分钟刷新30min后并不一定就是立马就能保证取到新值 expire与refresh 都能控制key得回收究竟如何选择 答案是两个一起来 只要refresh得时间小于expire时间就能保证多线程在load取值时不阻塞也能保证refresh时间到期后取旧值向新值得平滑过渡当然仍旧不能解决取到旧值得问题。 5 监听 在guava cache中移除key可以设置相应得监听操作以便key被移除时做一些额外操作。缓存项被移除时RemovalListener会获取移除通知[RemovalNotification]其中包含移除原因[RemovalCause]、键和值。监听有同步监听和异步监听两种 : 同步监听 默认情况下监听器方法是被同步调用的在移除缓存的那个线程中执行,执行清理key的操作与执行监听是单线程模式当然监听器中抛出的任何异常都不会影响其正常使用顶多把异常写到日记了。 Testpublic void testCacheRemovedNotification(){CacheLoaderString, String loader CacheLoader.from(String::toUpperCase);RemovalListenerString, String listener notification - {if (notification.wasEvicted()){RemovalCause cause notification.getCause();System.out.println(remove case is : cause.toString());System.out.println(key: notification.getKey() value: notification.getValue());}};LoadingCacheString, String cache CacheBuilder.newBuilder().maximumSize(4).removalListener(listener).build(loader);cache.getUnchecked(maomao);cache.getUnchecked(wangwang);cache.getUnchecked(guava);cache.getUnchecked(cache);cache.getUnchecked(hello);} 异步监听 假如在同步监听模式下监听方法中的逻辑特别复杂执行效率慢那此时如果有大量的key进行清理会使整个缓存性能变得很低下所以此时适合用异步监听移除key与监听key的移除分属2个线程。 Testpublic void testCacheRemovedNotification(){CacheLoaderString, String loader CacheLoader.from(String::toUpperCase);RemovalListenerString, String listener notification - {if (notification.wasEvicted()){RemovalCause cause notification.getCause();System.out.println(remove case is : cause.toString());System.out.println(key: notification.getKey() value: notification.getValue());}};LoadingCacheString, String cache CacheBuilder.newBuilder().maximumSize(4).removalListener(RemovalListeners.asynchronous(listener, Executors.newSingleThreadExecutor())).build(loader);cache.getUnchecked(maomao);cache.getUnchecked(wangwang);cache.getUnchecked(guava);cache.getUnchecked(cache);cache.getUnchecked(hello);} 6 统计 guava cache还有一些其他特性比如weight 按权重回收资源统计等这里列出统计。CacheBuilder.recordStats()用来开启Guava Cache的统计功能。统计打开后Cache.stats()方法返回如下统计信息 hitRate()缓存命中率hitMiss(): 缓存失误率loadcount() ; 加载次数averageLoadPenalty()加载新值的平均时间单位为纳秒evictionCount()缓存项被回收的总数不包括显式清除。 Guava Cache 的替代者 Caffeine 外部缓存 最著名的外部缓存 - Redis / Memcached Redis / Memcached 都是使用内存作为存储所以性能上要比数据库要好很多再加上Redis 还支持很多种数据结构使用起来也挺方便所以作为很多人的首选。 Redis 确实不错不过即便是使用内存也还是需要通过网络来访问所以网络的性能决定了 Reids 的性能 在一些性能测试中在万兆网卡的情况下对于 Key 和 Value 都是长度为 20 Byte 的字符串的 get 和 set 是每秒10w左右的如果 Key 或者 Value 的长度更大或者使用数据结构这个会更慢一些 作为一般的系统来使用已经绰绰有余了从目前来看Redis 确实很适合来做系统中的缓存。 如果考虑多实例或者分布式可以考虑下面的方式 Jedis 的 ShardedJedis 调用端自己实现分片 twemproxy / codis 第三方组件实现代理 Redis Cluster 3.0 之后官方提供的集群方案 缓存的异常情况 缓存穿透 指的是对某个一定不存在的数据进行请求该请求将会穿透缓存到达数据库。 解决方案 对这些不存在的数据缓存一个空数据对这类请求进行过滤。 缓存击穿 指的是由于数据没有被加载到缓存中或者缓存数据在同一时间大面积失效过期又或者缓存服务器宕机导致大量的请求都到达数据库。 在有缓存的系统中系统非常依赖于缓存缓存分担了很大一部分的数据请求。当发生缓存雪崩时数据库无法处理这么大的请求导致数据库崩溃。 解决方案 为了防止缓存在同一时间大面积过期导致的缓存雪崩可以通过观察用户行为合理设置缓存过期时间来实现为了防止缓存服务器宕机出现的缓存雪崩可以使用分布式缓存分布式缓存中每一个节点只缓存部分的数据当某个节点宕机时可以保证其它节点的缓存仍然可用。也可以进行缓存预热避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩。 缓存一致性 缓存一致性要求数据更新的同时缓存数据也能够实时更新。 解决方案 在数据更新的同时立即去更新缓存在读缓存之前先判断缓存是否是最新的如果不是最新的先进行更新。 要保证缓存一致性需要付出很大的代价缓存数据最好是那些对一致性要求不高的数据允许缓存数据存在一些脏数据。 缓存“无底洞”现象 指的是为了满足业务要求添加了大量缓存节点但是性能不但没有好转反而下降了的现象。 产生原因缓存系统通常采用 hash 函数将 key 映射到对应的缓存节点随着缓存节点数目的增加键值分布到更多的节点上导致客户端一次批量操作会涉及多次网络操作这意味着批量操作的耗时会随着节点数目的增加而不断增大。此外网络连接数变多对节点的性能也有一定影响。 解决方案 优化批量数据操作命令减少网络通信次数降低接入成本使用长连接 / 连接池NIO 等。 附录 附录1 使用ConcurrentHashMap实现带过期时间的缓存 private static ScheduledExecutorService swapExpiredPool new ScheduledThreadPoolExecutor(10);private ReentrantLock lock new ReentrantLock();private ConcurrentHashMapString, Node cache new ConcurrentHashMap(1024);/*** 让过期时间最小的数据排在队列前在清除过期数据时* 只需查看缓存最近的过期数据而不用扫描全部缓存** see Node#compareTo(Node)* see SwapExpiredNodeWork#run()*/private PriorityQueueNode expireQueue new PriorityQueue(1024);public LocalCache() {//使用默认的线程池每5秒清除一次过期数据//线程池和调用频率 最好是交给调用者去设置。swapExpiredPool.scheduleWithFixedDelay(new SwapExpiredNodeWork(), 5, 5, TimeUnit.SECONDS);}public Object set(String key, Object value, long ttl) {Assert.isTrue(StringUtils.hasLength(key), key cant be empty);Assert.isTrue(ttl 0, ttl must greater than 0);long expireTime System.currentTimeMillis() ttl;Node newNode new Node(key, value, expireTime);lock.lock();try {Node old cache.put(key, newNode);expireQueue.add(newNode);//如果该key存在数据还要从过期时间队列删除if (old ! null) {expireQueue.remove(old);return old.value;}return null;} finally {lock.unlock();}}/*** 拿到的数据可能是已经过期的数据可以再次判断一下* ifn.expireTimeSystem.currentTimeMillis(){* return null;* }* 也可以直接返回整个节点Node 交给调用者去取舍* p* p* 无法判断不存在该key,还是该key存的是一个null值如果需要区分这两种情况* 可以定义一个全局标识标识key不存在* public static final NOT_EXIST new Object();* 返回值时* return nnull?NOT_EXIST:n.value;*/public Object get(String key) {Node n cache.get(key);return n null ? null : n.value;}/*** 删除KEY并返回该key对应的数据*/public Object remove(String key) {lock.lock();try {Node n cache.remove(key);if (n null) {return null;} else {expireQueue.remove(n);return n.value;}} finally {lock.unlock();}}/*** 删除已经过期的数据*/private class SwapExpiredNodeWork implements Runnable {Overridepublic void run() {long now System.currentTimeMillis();while (true) {lock.lock();try {Node node expireQueue.peek();//没有数据了或者数据都是没有过期的了if (node null || node.expireTime now) {return;}cache.remove(node.key);expireQueue.poll();} finally {lock.unlock();}}}}private static class Node implements ComparableNode {private String key;private Object value;private long expireTime;public Node(String key, Object value, long expireTime) {this.value value;this.key key;this.expireTime expireTime;}/*** see SwapExpiredNodeWork*/Overridepublic int compareTo(Node o) {long r this.expireTime - o.expireTime;if (r 0) {return 1;}if (r 0) {return -1;}return 0;}} 粉丝福利 免费领取C/C 开发学习资料包、技术视频/代码1000道大厂面试题内容包括C基础网络编程数据库中间件后端开发/音视频开发/Qt开发/游戏开发/Linuxn内核等进阶学习资料和最佳学习路线↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓
http://www.pierceye.com/news/850668/

相关文章:

  • 详细论述制作网站的步骤做网站需求 后期方便优化
  • 蒙icp备 网站建设学校网站建设管理
  • 做免费外贸网站册域名网站大全免黄
  • 祈网网站建设制作网站如何赚钱
  • 最讨厌网站门户类网站的主页设计
  • 国家建设环保局网站网站做的好赚钱吗
  • 如何设置网站服务器做标签的网站
  • 网站建设高端培训学校做网站交易平台
  • 公司网站建设收费优化网站排名解析推广
  • 昆明快速建站模板汽车网站建设多少钱
  • 网站注销主体注销广州联享网站建设公司怎么样
  • 中山seo建站新手建站教程报价单
  • 台州制作网站软件陈坤做直播在哪个网站
  • 北湖区网站建设公司企业主题wordpress 含演示数据
  • 网站建设简历自我评价做招聘信息的网站有哪些内容
  • 怎么和其它网站做友情链接网络营销师证怎么考
  • 百度推广要自己做网站吗做的视频传到哪个网站好
  • 个人建设门户网站 如何备案网站推广服务报价表
  • 广州企业网站建设哪家服务好西安家政公司网站建设
  • 住房与城乡建设部网站 黑龙江wordpress 采集系统
  • 阜阳网站建设云平台玉溪建设局门户网站
  • 网站建设什么原因最主要怎么制作网站首页
  • 网站建设深圳赶集网网页设计工程师工资
  • 哪家企业网站建设好闵行区网站制作
  • 重庆行业网站建设陕西省建设监理协会查询官方网站
  • 手机网站 尺寸网站规划的认识
  • 永川网站制作联系电话wordpress 参数 传递
  • 西宁市网站建设高端网站开发人员要求
  • 前端做商城网站需要多久yum wordpress
  • 便宜网站建设成都免费建网站视频教程