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

wordpress发广告邮件插件seo整站优化系统

wordpress发广告邮件插件,seo整站优化系统,WordPress网盘下载插件,河北seo关键词排名优化为什么需要缓存变更通知机制?如果我们使用的是本地缓存或者多级缓存(本地缓存远程缓存),当其中一个节点的本地缓存变更之后,为了保证缓存尽量的一致性,此时其他节点的本地缓存也需要去变更,这时…

为什么需要缓存变更通知机制?如果我们使用的是本地缓存或者多级缓存(本地缓存+远程缓存),当其中一个节点的本地缓存变更之后,为了保证缓存尽量的一致性,此时其他节点的本地缓存也需要去变更,这时候常用的做法就是需要接入一个通知机制,只要有节点的本地缓存变更了,那么这时候就广播出一个缓存变更消息,其他节点会去订阅这个消息,最终消费这个消息的时候把本地缓存的数据进行更新或删除。当然,通知机制的实现有很多,比如可以利用redis的发布订阅机制,也可以接入mq这种消息中间件作为消息通知,不过相比之下,mq就稍微重了点,所以JetCache则是使用redis的发布订阅机制去实现缓存变更通知机制

缓存监视器CacheMonitor

@FunctionalInterface
public interface CacheMonitor {void afterOperation(CacheEvent event);}

如果我们想要监控缓存的每一次操作,或者在缓存的每一次操作的时候进行一些埋点扩展,那么JetCache提供了CacheMonitor接口可以让我们用户自己去进行一些自定义的实现,当然在JetCache内部也有默认的一些缓存监视器的实现:

  • DefaultCacheMonitor

该monitor主要是监控缓存的每一次操作,比如get,put,remove等,基于监控这些操作之下就可以采集到各种操作指标,例如缓存命中次数,获取缓存次数,加载数据次数等等,详细的采集的指标如下:

protected String cacheName;
protected long statStartTime;
protected long statEndTime;protected long getCount;
protected long getHitCount;
protected long getMissCount;
protected long getFailCount;
protected long getExpireCount;
protected long getTimeSum;
protected long minGetTime = Long.MAX_VALUE;
protected long maxGetTime = 0;protected long putCount;
protected long putSuccessCount;
protected long putFailCount;
protected long putTimeSum;
protected long minPutTime = Long.MAX_VALUE;
protected long maxPutTime = 0;protected long removeCount;
protected long removeSuccessCount;
protected long removeFailCount;
protected long removeTimeSum;
protected long minRemoveTime = Long.MAX_VALUE;
protected long maxRemoveTime = 0;protected long loadCount;
protected long loadSuccessCount;
protected long loadFailCount;
protected long loadTimeSum;
protected long minLoadTime = Long.MAX_VALUE;
protected long maxLoadTime = 0;
  • CacheNotifyMonitor

该monitor看名字大概就知道它的作用是用来监控缓存变更之后发送通知的,监控的缓存操作有4种,分别是put,putAll,remove,removeAll,这4个操作都是会让缓存产生变更的操作,代码如下:

@Override
public void afterOperation(CacheEvent event) {if (this.broadcastManager == null) {return;}AbstractCache absCache = CacheUtil.getAbstractCache(event.getCache());if (absCache.isClosed()) {return;}AbstractEmbeddedCache localCache = getLocalCache(absCache);if (localCache == null) {return;}// put事件if (event instanceof CachePutEvent) {CacheMessage m = new CacheMessage();m.setArea(area);m.setCacheName(cacheName);m.setSourceId(sourceId);CachePutEvent e = (CachePutEvent) event;m.setType(CacheMessage.TYPE_PUT);m.setKeys(new Object[]{convertKey(e.getKey(), localCache)});broadcastManager.publish(m);}// remove事件else if (event instanceof CacheRemoveEvent) {CacheMessage m = new CacheMessage();m.setArea(area);m.setCacheName(cacheName);m.setSourceId(sourceId);CacheRemoveEvent e = (CacheRemoveEvent) event;m.setType(CacheMessage.TYPE_REMOVE);m.setKeys(new Object[]{convertKey(e.getKey(), localCache)});broadcastManager.publish(m);}// putAll事件else if (event instanceof CachePutAllEvent) {CacheMessage m = new CacheMessage();m.setArea(area);m.setCacheName(cacheName);m.setSourceId(sourceId);CachePutAllEvent e = (CachePutAllEvent) event;m.setType(CacheMessage.TYPE_PUT_ALL);if (e.getMap() != null) {m.setKeys(e.getMap().keySet().stream().map(k -> convertKey(k, localCache)).toArray());}broadcastManager.publish(m);}// removeAll事件else if (event instanceof CacheRemoveAllEvent) {CacheMessage m = new CacheMessage();m.setArea(area);m.setCacheName(cacheName);m.setSourceId(sourceId);CacheRemoveAllEvent e = (CacheRemoveAllEvent) event;m.setType(CacheMessage.TYPE_REMOVE_ALL);if (e.getKeys() != null) {m.setKeys(e.getKeys().stream().map(k -> convertKey(k, localCache)).toArray());}broadcastManager.publish(m);}
}

缓存变更消息发布器/订阅器BroadcastManager

上面我们知道了JetCache中会通过CacheNotifyMonitor来监控缓存的变更,但是发送缓存变更的消息通知则是交给BroadcastManager去做的。BroadcastManager是一个抽象类,提供了两个抽象方法:

/*** 发布缓存变更消息* @param cacheMessage  cacheMessage*/
public abstract CacheResult publish(CacheMessage cacheMessage);/*** 订阅缓存变更消息*/
public abstract void startSubscribe();

publish方法是发布广播缓存变更消息的方法,传入的CacheMessage参数就是缓存变更消息,而startSubscribe方法则是订阅缓存变更消息的,这两个方法具体由子类进行实现,目前JetCache中主要提供了4种实现,这4种实现都是基于redis的订阅发布机制实现的,只是使用的redis客户端不一样的区别

  • LettuceBroadcastManager
  • RedisBroadcastManager
  • RedissonBroadcastManager
  • SpringDataBroadcastManager

我们这里可以以RedissonBroadcastManager为例,去看它是怎样实现缓存变更消息通知机制的

public class RedissonBroadcastManager extends BroadcastManager {private static final Logger logger = LoggerFactory.getLogger(RedissonBroadcastManager.class);private final RedissonCacheConfig<?, ?> config;private final String channel;private final RedissonClient client;private volatile int subscribeId;private final ReentrantLock reentrantLock = new ReentrantLock();public RedissonBroadcastManager(final CacheManager cacheManager, final RedissonCacheConfig<?, ?> config) {super(cacheManager);checkConfig(config);this.config = config;this.channel = config.getBroadcastChannel();this.client = config.getRedissonClient();}@Overridepublic void startSubscribe() {reentrantLock.lock();try {if (this.subscribeId == 0 && Objects.nonNull(this.channel) && !this.channel.isEmpty()) {this.subscribeId = this.client.getTopic(this.channel).addListener(byte[].class, (channel, msg) -> processNotification(msg, this.config.getValueDecoder()));}}finally {reentrantLock.unlock();}}@Overridepublic void close() {reentrantLock.lock();try {final int id;if ((id = this.subscribeId) > 0 && Objects.nonNull(this.channel)) {this.subscribeId = 0;try {this.client.getTopic(this.channel).removeListener(id);} catch (Throwable e) {logger.warn("unsubscribe {} fail", this.channel, e);}}}finally {reentrantLock.unlock();}}@Overridepublic CacheResult publish(final CacheMessage cacheMessage) {try {if (Objects.nonNull(this.channel) && Objects.nonNull(cacheMessage)) {final byte[] msg = this.config.getValueEncoder().apply(cacheMessage);this.client.getTopic(this.channel).publish(msg);return CacheResult.SUCCESS_WITHOUT_MSG;}return CacheResult.FAIL_WITHOUT_MSG;} catch (Throwable e) {SquashedLogger.getLogger(logger).error("jetcache publish error", e);return new CacheResult(e);}}
}

首先当调用Cache实例的put,putAll,remove,removeAll这些方法的时候,就会去触CacheNotifyMonitor,CacheNotifyMonitor这时候就会去创建一个缓存变更信息然后交给RedissonBroadcastManager去调用publish方法,在publish方法就会使用redisson的发布api去广播出这条缓存变更消息,当然订阅也是使用redisson的订阅api,当监听到有缓存变更消息的时候,这时候就会去回调processNotification方法,该方法是父类BroadcastManager的方法:

protected void processNotification(byte[] message, Function<byte[], Object> decoder) {try {if (message == null) {logger.error("notify message is null");return;}Object value = decoder.apply(message);if (value == null) {logger.error("notify message is null");return;}if (value instanceof CacheMessage) {processCacheMessage((CacheMessage) value);} else {logger.error("the message is not instance of CacheMessage, class={}", value.getClass());}} catch (Throwable e) {SquashedLogger.getLogger(logger).error("receive cache notify error", e);}
}private void processCacheMessage(CacheMessage cacheMessage) {// 条件成立:说明这个缓存消息是自己发送的,这时候不用处理if (sourceId.equals(cacheMessage.getSourceId())) {return;}// 根据area和cacheName从缓存管理器中获取到对应的Cache实例Cache cache = cacheManager.getCache(cacheMessage.getArea(), cacheMessage.getCacheName());if (cache == null) {logger.warn("Cache instance not exists: {},{}", cacheMessage.getArea(), cacheMessage.getCacheName());return;}// 如果这个Cache实例不是一个多级缓存的Cache实例,那么就直接return,因为这里主要是针对多级缓存的情况下进行处理的Cache absCache = CacheUtil.getAbstractCache(cache);if (!(absCache instanceof MultiLevelCache)) {logger.warn("Cache instance is not MultiLevelCache: {},{}", cacheMessage.getArea(), cacheMessage.getCacheName());return;}// 获取到多级缓存中所有的Cache实例Cache[] caches = ((MultiLevelCache) absCache).caches();// 获取到缓存有变动的keySet<Object> keys = Stream.of(cacheMessage.getKeys()).collect(Collectors.toSet());// 遍历所有的Cache实例for (Cache c : caches) {Cache localCache = CacheUtil.getAbstractCache(c);// 只针对本地缓存的Cache实例,把缓存有变动的key从本地缓存中移除if (localCache instanceof AbstractEmbeddedCache) {((AbstractEmbeddedCache) localCache).__removeAll(keys);} else {break;}}
}

最终会调用到processCacheMessage方法,需要注意的是如果是自己发送的消息则不需要再去消费,所以会使用一个sourceId去进行过滤,并且还会去判断当前的Cache实例是否是一个多级缓存实例,如果是多级缓存,那么就把这个多级缓存种的所有本地缓存都取出来,然后最后根据缓存变更消息里面的key把对应的本地缓存都remove掉,可能有人问为什么这里对本地缓存进行remove而不是update呢?因为如果使用update的话,还需要考虑并发的场景,比如这个key进行了两次更新,先后会发布两次缓存变更消息,但是订阅者去消费这两个消息的时候并不能去保证它们的先后顺序,此时就会有可能造成更新顺序的问题,但是使用remove就可能完全避免这种并发问题了

总结

在JetCache中提供了对于缓存操作的后置扩展接口,也叫做缓存监控器,我们可以自己去实现自己的缓存监控器来对缓存操作之后做一些自定义的功能,默认地JetCache提供了两个缓存监视器的实现,一个是采集缓存操作的一些指标信息DefaultCacheMonitor,一个是在缓存变更之后发送缓存变更通知的CacheNotifyMonitor,其中CacheNotifyMonitor在监控到缓存变更之后会去使用BroadcastManager去进行消息的发布订阅,BroadcastManager是发布者也是订阅者,在订阅消费的时会根据缓存变更消息里面的keys去把当前Cache实例的本地缓存进行remove,也就是依赖于这样的一个缓存变更消息通知机制,就可以保证当使用多级缓存的时候,多节点间的本地缓存尽量达成一致


文章转载自:
http://dinncobirdshit.ydfr.cn
http://dinncooutwork.ydfr.cn
http://dinncoinebrious.ydfr.cn
http://dinncohypocrinism.ydfr.cn
http://dinncorocketeer.ydfr.cn
http://dinncocybele.ydfr.cn
http://dinncouptore.ydfr.cn
http://dinncofratch.ydfr.cn
http://dinncoenuresis.ydfr.cn
http://dinncorocketman.ydfr.cn
http://dinncostigmatize.ydfr.cn
http://dinncobullnecked.ydfr.cn
http://dinnconortheaster.ydfr.cn
http://dinncovervain.ydfr.cn
http://dinncodarshan.ydfr.cn
http://dinncocorydon.ydfr.cn
http://dinncozloty.ydfr.cn
http://dinncojavanese.ydfr.cn
http://dinncosortition.ydfr.cn
http://dinncodought.ydfr.cn
http://dinncododdering.ydfr.cn
http://dinncoskupshtina.ydfr.cn
http://dinncocitrus.ydfr.cn
http://dinncojolo.ydfr.cn
http://dinncostearic.ydfr.cn
http://dinncokiruna.ydfr.cn
http://dinncobrowny.ydfr.cn
http://dinncoscandinavian.ydfr.cn
http://dinncoshahaptin.ydfr.cn
http://dinncoinobservancy.ydfr.cn
http://dinnconazism.ydfr.cn
http://dinncoslantindicular.ydfr.cn
http://dinncosnowhole.ydfr.cn
http://dinncoforelock.ydfr.cn
http://dinncoodovacar.ydfr.cn
http://dinncodomineer.ydfr.cn
http://dinncomacchinetta.ydfr.cn
http://dinncoindological.ydfr.cn
http://dinncomaas.ydfr.cn
http://dinncofuzzbuzz.ydfr.cn
http://dinncoheliborne.ydfr.cn
http://dinncoomnificent.ydfr.cn
http://dinncoestriol.ydfr.cn
http://dinncoembolic.ydfr.cn
http://dinncotextbook.ydfr.cn
http://dinncobleeding.ydfr.cn
http://dinncoferberite.ydfr.cn
http://dinncomozarab.ydfr.cn
http://dinncofaithfully.ydfr.cn
http://dinncopekin.ydfr.cn
http://dinncocalvinism.ydfr.cn
http://dinncoindaba.ydfr.cn
http://dinncoinstrumentalism.ydfr.cn
http://dinncorostrated.ydfr.cn
http://dinncocyanoacrylate.ydfr.cn
http://dinncodelian.ydfr.cn
http://dinncorooinek.ydfr.cn
http://dinncocollinear.ydfr.cn
http://dinncofunnel.ydfr.cn
http://dinncopitchpole.ydfr.cn
http://dinncomanageress.ydfr.cn
http://dinncoheelball.ydfr.cn
http://dinncofreemason.ydfr.cn
http://dinncocornus.ydfr.cn
http://dinncoaggregate.ydfr.cn
http://dinncohectometer.ydfr.cn
http://dinncozhuhai.ydfr.cn
http://dinncoadditament.ydfr.cn
http://dinncointerstitialcy.ydfr.cn
http://dinncoaquiferous.ydfr.cn
http://dinncocentripetence.ydfr.cn
http://dinncocalory.ydfr.cn
http://dinncokithe.ydfr.cn
http://dinncovalinomycin.ydfr.cn
http://dinncolionhearted.ydfr.cn
http://dinncounitarity.ydfr.cn
http://dinncocodex.ydfr.cn
http://dinncoskat.ydfr.cn
http://dinncosensation.ydfr.cn
http://dinncoapprover.ydfr.cn
http://dinncosavine.ydfr.cn
http://dinncolatifoliate.ydfr.cn
http://dinncopiggy.ydfr.cn
http://dinncocholecystitis.ydfr.cn
http://dinncoevent.ydfr.cn
http://dinncodeflector.ydfr.cn
http://dinncodomesticable.ydfr.cn
http://dinncosalpinges.ydfr.cn
http://dinncotarantism.ydfr.cn
http://dinncohoagie.ydfr.cn
http://dinnconephelometry.ydfr.cn
http://dinncofestilogy.ydfr.cn
http://dinncodamaskeen.ydfr.cn
http://dinncolingo.ydfr.cn
http://dinncocornhusking.ydfr.cn
http://dinncohomozygously.ydfr.cn
http://dinncocoercing.ydfr.cn
http://dinncometacommunication.ydfr.cn
http://dinncodorian.ydfr.cn
http://dinncochieftainship.ydfr.cn
http://www.dinnco.com/news/106939.html

相关文章:

  • wordpress电影列表页重庆优化seo
  • iis7 网站无法显示该页面免费关键词优化工具
  • 遵义做网站淘宝店铺怎么免费推广
  • 做网站的集团近期的重大新闻
  • 做网站准备材料2021网络营销成功案例
  • 网站建设加排名要多少seo体系
  • 网站制作公司前十排名域名注册价格及续费
  • 做愛4p視頻网站是什么宁波网站建设网站排名优化
  • 用dw制作网站建设淘宝运营培训班哪里有
  • 山西营销型网站建设湖南网站推广
  • 我的网址注册百度seo怎么做
  • 大型网站建设兴田德润专业零基础学什么技术好
  • 做AE视频素材在哪些网站上可以找百度统计app下载
  • 盐城做网站的windows优化大师有什么功能
  • 个人网站主页设计模板专业的制作网站开发公司
  • google 网站质量问题全自动精准引流软件
  • 阳江市住房和城乡规划建设局网站石家庄网站建设seo公司
  • 青岛做网站推广公司哪家好seo网站营销推广
  • 女生做网站运营天津搜索引擎优化
  • 昆山市有没有做网站设计的沈阳网站建设
  • 网站升级改版需要多久深圳搜索seo优化排名
  • 宁德公司做网站百度seo优化是什么
  • 织梦系统做的网站打开慢新网站快速收录
  • html格式的网站地图网站推广软件ky99
  • 怎么用html做图片展示网站百度关键词排名突然没了
  • 网页制作中的网站维护seo外包方法
  • 长安公司网站设计百度软文推广怎样收费
  • 用bootstrap3做的网站百度资源平台
  • xx企业网站建设方案书网站优化技巧
  • 电商网站建设新闻永久免费建站系统