首页 » SEO优化 » php恒等式技巧_Java互联网架构心潮彭湃续写Redis高机能缓存技能

php恒等式技巧_Java互联网架构心潮彭湃续写Redis高机能缓存技能

访客 2024-11-19 0

扫一扫用手机浏览

文章目录 [+]

redis是一个key-value存储系统。
和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(凑集)、zset(sorted set --有序凑集)和hash(哈希类型)。
这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
在此根本上,redis支持各种不同办法的排序。
与memcached一样,为了担保效率,数据都是缓存在内存中。
差异的是redis会周期性的把更新的数据写入磁盘或者把修正操作写入追加的记录文件,并且在此根本上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。
redis的涌现,很大程度补偿了memcached这类key/value存储的不敷,在部 分场合可以对关系数据库起到很好的补充浸染。
它供应了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,利用很方便。
[1]

php恒等式技巧_Java互联网架构心潮彭湃续写Redis高机能缓存技能

Redis支持主从同步。
数据可以从主理事器向任意数量的从做事器上同步,从做事器可以是关联其他从做事器的主理事器。
这使得Redis可实行单层树复制。
存盘可以故意无意的对数据进行写操作。
由于完备实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并吸收主理事器完全的发布记录。
同步对读取操作的可扩展性和数据冗余很有帮助。

php恒等式技巧_Java互联网架构心潮彭湃续写Redis高机能缓存技能
(图片来自网络侵删)

redis的官网地址,非常好记,是redis.io。
(特意查了一下,域名后缀io属于国家域名,是british Indian Ocean territory,即英属印度洋领地)

1、背景

缓存,在我们日常开拓中是必不可少的一种办理性能问题的方法。
大略的说,cache 便是为了提升系统性能而开辟的一块内存空间。

缓存的紧张浸染是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问利用。
在日常开拓的很多场合,由于受限于硬盘IO的性能或者我们自身业务系统的数据处理和获取可能非常费时,当我们创造我们的系统这个数据要求量很大的时候,频繁的IO和频繁的逻辑处理会导致硬盘和CPU资源的瓶颈涌现。
缓存的浸染便是将这些来自不易的数据保存在内存中,当有其他线程或者客户端须要查询相同的数据资源时,直接从缓存的内存块中返回数据,这样不但可以提高系统的相应韶光,同时也可以节省对这些数据的处理流程的资源花费,整体上来说,系统性能会有大大的提升。

缓存在很多系统和架构中都用广泛的运用,例如:

CPU缓存

操作系统缓存

本地缓存

分布式缓存

HTTP缓存

数据库缓存

等等,可以说在打算机和网络领域,缓存无处不在。
可以这么说,只要有硬件性能不对等,涉及到网络传输的地方都会有缓存的身影。

Guava Cache是一个全内存确当地缓存实现,它供应了线程安全的实现机制。
整体上来说Guava cache 是本地缓存的不二之选,大略易用,性能好。

2、适用性

Guava Cache 适用于:

你乐意花费一些内存空间来提升速率。

你预见到某些键会被查询一次以上。

缓存中存放的数据总量不会超出内存容量。
(Guava Cache 是单个运用运行时确当地缓存。
它不把数据存放到文件或外部做事器。
如果这不符合你的需求,请考试测验 Memcached 这类工具)

如果你的场景符合上述的每一条,Guava Cache 就适宜你。

Guava Cache 与 ConcurrentMap

二者很相似,但也不完备一样。
最基本的差异是 ConcurrentMap 会一贯保存所有添加的元素,直到显式地移除。
相对地,Guava Cache 为了限定内存占用,常日都设定为自动回收元素。
在某些场景下,只管 LoadingCache 不回收元素,它也是很有用的,由于它会自动加载缓存。

3、缓存创建

Guava Cache有两种创建办法:

CacheLoader

Callable

这两种创建办法有什么异同呢?

两种办法同样按照获取缓存-如果没有-则打算(get-if-absent-compute)的缓存规则对缓存数据进行的处理的。

不同之处在于:在缓存中没有得到value的时候,CacheLoader会定义一个比较宽泛的、统一的统一的根据key值load value的方法,而Callablee的办法较为灵巧,许可你在get的时候指定。

CacheLoader

public void testCacheLoader() throws ExecutionException{

LoadingCache<String,String> cahceBuilder = CacheBuilder

.newBuilder()

.build(new CacheLoader<String, String>() {

// 在load方法中定义value的加载方法;

// 这个方法要么返回已经缓存的值,要么利用 CacheLoader 向缓存原子地加载新值

@Override

public String load(String key) throws Exception {

String strProValue=\"大众hello \公众 + key + \"大众!\"大众;

return strProValue;

}

// 默认情形下,对每个不在缓存中的键,getAll 方法会单独调用 CacheLoader.load 来加载缓存项。
如果批量的加载比多个单独加载更高效,你可以重载 CacheLoader.loadAll 来利用这一点

@Override

public Map<String, String> loadAll(Iterable<? extends String> keys) throws Exception {

return super.loadAll(keys);

}

});

logger.info(\"大众jerry value:\"大众+cahceBuilder.apply(\"大众jerry\"大众));

logger.info((\"大众jerry value:\公众+cahceBuilder.get(\"大众jerry\"大众)));

logger.info((\公众peida value:\公众+cahceBuilder.get(\"大众peida\"大众)));

logger.info((\"大众peida value:\公众+cahceBuilder.apply(\"大众peida\"大众)));

logger.info((\"大众lisa value:\"大众+cahceBuilder.apply(\"大众lisa\"大众)));

cahceBuilder.put(\"大众harry\公众, \"大众ssdded\"大众);

logger.info((\"大众harry value:\公众+cahceBuilder.get(\"大众harry\"大众)));

}

非常

由于 CacheLoader 可能抛出非常,LoadingCache.get(K)也声明为抛出 ExecutionException 非常。
如果你定义的 CacheLoader 没有声明任何检讨型非常,则可以通过 getUnchecked(K)查找缓存;但必须把稳,一旦 CacheLoader 声明了检讨型非常,就不可以调用 getUnchecked(K)。

getAll(Iterable<? extends K>)方法

用来实行批量查询。
默认情形下,对每个不在缓存中的键,getAll 方法会单

独调用 CacheLoader.load 来加载缓存项。
如果批量的加载比多个单独加载更高效,你可以重载 CacheLoade

r.loadAll 来利用这一点。
getAll(Iterable)的性能也会相应提升

Callable

所有类型的 Guava Cache,不管有没有自动加载功能,都支持 get(K, Callable)方法。
这个方法返回缓存中相应的值,或者用给定的 Callable 运算并把结果加入到缓存中。
在全体加载方法完成前,缓存项干系的可不雅观察状态都不会变动。
这个方法简便地实现了模式\"大众如果有缓存则返回;否则运算、缓存、然后返回\"大众。

public void testCallable() throws ExecutionException{

Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build();

// 获取某个key时,在Cache.get中单独为其指定load方法

String resultVal = cache.get(\公众jerry\公众, new Callable<String>() {

public String call() {

String strProValue=\"大众hello \"大众+\"大众jerry\公众+\公众!\公众;

return strProValue;

}

});

logger.info(\"大众jerry value : \"大众 + resultVal);

// 获取某个key时,在Cache.get中单独为其指定load方法

resultVal = cache.get(\"大众peida\"大众, new Callable<String>() {

public String call() {

String strProValue=\"大众hello \"大众+\公众peida\公众+\"大众!\公众;

return strProValue;

}

});

logger.info(\公众peida value : \公众 + resultVal);

}

显式插入

利用 cache.put(key, value)方法可以直接向缓存中插入值,这会直接覆盖掉给定键之前映射的值。
利用 Cache.asMap()视图供应的任何方法也能修正缓存。
但请把稳,asMap 视图的任何方法都不能担保缓存项被原子地加载到缓存中。
进一步说,asMap 视图的原子运算在 Guava Cache 的原子加载范畴之外,以是比较于 Cache.asMap().putIfAbsent(K, V),Cache.get(K, Callable) 该当总是优先利用。

cache的参数解释:

回收的参数(这些参数在缓存回收时发挥浸染):

1. 大小的设置:CacheBuilder.maximumSize(long) CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long)

2. 韶光:expireAfterAccess(long, TimeUnit) expireAfterWrite(long, TimeUnit)

3. 引用:CacheBuilder.weakKeys() CacheBuilder.weakValues() CacheBuilder.softValues()

4. 明确的删除:invalidate(key) invalidateAll(keys) invalidateAll()

5. 删除监听器:CacheBuilder.removalListener(RemovalListener)

4、缓存回收

一个残酷的现实是,我们险些一定没有足够的内存缓存所有数据。
你必须决定:什么时候某个缓存项就不值得保留了?Guava Cache 供应了三种基本的缓存回收办法:

基于容量回收

定时回收

基于引用回收

基于容量的回收(size-based eviction)

如果要规定缓存项的数目不超过固定值,只需利用CacheBuilder.maximumSize(long)。
缓存将考试测验回收最近没有利用或总体上很少利用的缓存项。
——警告:在缓存项的数目达到限定值之前,缓存就可能进行回收操作——常日来说,这种情形发生在缓存项的数目逼近限定值时。

LoadingCache<String,String> cahceBuilder = CacheBuilder

.newBuilder()

.maximumSize(10000)

.build(new CacheLoader<String, String>() {

... ...

});

定时回收(Timed Eviction)

CacheBuilder 供应两种定时回收的方法:

expireAfterAccess(long, TimeUnit):缓存项在给定时间内没有被读/写访问,则回收。
请把稳这种缓存的回收顺序和基于大小回收一样。

expireAfterWrite(long, TimeUnit)::缓存项在给定时间内没有被写访问(创建或覆盖),则回收。
如果认为缓存数据总是在固定时候后变得迂腐不可用,这种回收办法是可取的。

如下文所谈论,定时回收周期性地在写操作中实行,偶尔在读操作中实行。

测试定时回收

瞄准时回收进行测试时,不一定非得花费两秒钟去测试两秒的过期。
你可以利用 Ticker 接口和 CacheBuilder.ticker(Ticker)方法在缓存中自定义一个韶光源,而不是非得用系统时钟。

基于引用的回收(Reference-based Eviction)

通过利用弱引用的键、或弱引用的值、或软引用的值,Guava Cache 可以把缓存设置为许可垃圾回收:

CacheBuilder.weakKeys():利用弱引用存储键。
当键没有其它(强或软)引用时,缓存项可以被垃圾回收。
由于垃圾回收仅依赖恒等式(==),利用弱引用键的缓存用==而不是 equals 比较键。

CacheBuilder.weakValues():利用弱引用存储值。
当值没有其它(强或软)引用时,缓存项可以被垃圾回收。
由于垃圾回收仅依赖恒等式(==),利用弱引用值的缓存用==而不是 equals 比较值。

CacheBuilder.softValues():利用软引用存储值。
软引用只有在相应内存须要时,才按照全局最近最少利用的顺序回收。
考虑到利用软引用的性能影响,我们常日建议利用更有性能预测性的缓存大小限定(见上文,基于容量回收)。
利用软引用值的缓存同样用==而不是 equals 比较值。

显式打消

任何时候,你都可以显式地打消缓存项,而不是等到它被回收:

个别打消:Cache.invalidate(key)

批量打消:Cache.invalidateAll(keys)

打消所有缓存项:Cache.invalidateAll()

移除监听器

通过 CacheBuilder.removalListener(RemovalListener),你可以声明一个监听器,以便缓存项被移除时做一些额外操作。
缓存项被移除时,RemovalListener 会获取移除关照RemovalNotification,个中包含移除缘故原由[RemovalCause]、键和值。

下面是一个数据库连接缓存的例子:

public void testRemovalListener(){

class DatabaseConnection{

// 实现省略

DatabaseConnection(String conn){}

void close(){}

}

// 创建loader

CacheLoader<String, DatabaseConnection> loader = new CacheLoader<String, DatabaseConnection> () {

public DatabaseConnection load(String key) throws Exception {

return new DatabaseConnection(key);

}

};

// 创建移除监听器

RemovalListener<String, DatabaseConnection> removalListener = new RemovalListener<String, DatabaseConnection>() {

public void onRemoval(RemovalNotification<String, DatabaseConnection> notification) {

DatabaseConnection conn = notification.getValue();

conn.close(); // tear down properly

}

};

Cache<String, DatabaseConnection> cache = CacheBuilder.newBuilder()

.expireAfterWrite(2, TimeUnit.MINUTES)

.removalListener(removalListener)

.build(loader);

}

警告:

默认情形下,监听器方法是在移除缓存时同步调用的。
由于缓存的掩护和要求相应常日是同时进行的,代价高昂的监听器方法在同步模式下会拖慢正常的缓存要求。
在这种情形下,你可以利用 RemovalListeners.asynchronous(RemovalListener, Executor)把监听器装饰为异步操作。

清理什么时候发生?

利用 CacheBuilder 构建的缓存不会\公众自动\"大众实行清理和回收事情,也不会在某个缓存项过期后立时清理,也没有诸如此类的清理机制。
相反,它会在写操作时顺带做少量的掩护事情,或者偶尔在读操作时做——如果写操作实在太少的话。

这样做的缘故原由在于:如果要自动地持续清理缓存,就必须有一个线程,这个线程会和用户操作竞争共享锁。
此外,某些环境下线程创建可能受限定,这样 CacheBuilder 就不可用了。

相反,我们把选择权交到你手里。
如果你的缓存是高吞吐的,那就无需担心缓存的掩护和清理等事情。
如果你的缓存只会偶尔有写操作,而你又不想清理事情阻碍了读操作,那么可以创建自己的掩护线程,以固定的韶光间隔调用 Cache.cleanUp()。
ScheduledExecutorService 可以帮助你很好地实现这样的定时调度。

刷新

刷新和回收不太一样。
正如 LoadingCache.refresh(K)所声明,刷新表示为键加载新值,这个过程可以是异步的。
在刷新操作进行时,缓存仍旧可以向其他线程返回旧值,而不像回收操作,读缓存的线程必须等待新值加载完成。

如果刷新过程抛出非常,缓存将保留旧值,而非常会在记录到日志后被丢弃。

重载 CacheLoader.reload(K, V)可以扩展刷新时的行为,这个方法许可开拓者在打算新值时利用旧的值。

CacheBuilder.refreshAfterWrite(long, TimeUnit)可以为缓存增加自动定时刷新功能。
和 expireAfterWrite相反,refreshAfterWrite 通过定时刷新可以让缓存项保持可用,但请把稳:缓存项只有在被检索时才会真正刷新(如果 CacheLoader.refresh 实现为异步,那么检索不会被刷新拖慢)。
因此,如果你在缓存上同时声明 expireAfterWrite 和 refreshAfterWrite,缓存并不会由于刷新盲目地定时重置,如果缓存项没有被检索,那刷新就不会真的发生,缓存项在过期韶光后也变得可以回收。

5、其他特性

统计

CacheBuilder.recordStats()用来开启 Guava Cache 的统计功能。
统计打开后,Cache.stats()方法会返回 CacheStats 工具以供应如下统计信息:

hitRate():缓存命中率;

averageLoadPenalty():加载新值的均匀韶光,单位为纳秒;

evictionCount():缓存项被回收的总数,不包括显式打消。

此外,还有其他很多统计信息。
这些统计信息对付调度缓存设置是至关主要的,在性能哀求高的运用中我们建议密切关注这些数据。

asMap 视图

asMap 视图供应了缓存的 ConcurrentMap 形式,但 asMap 视图与缓存的交互须要把稳:

cache.asMap()包含当前所有加载到缓存的项。
因此相应地,cache.asMap().keySet()包含当前所有已加载键;

asMap().get(key)本色上等同于 cache.getIfPresent(key),而且不会引起缓存项的加载。
这和 Map 的语义约定同等。

所有读写操作都会重置干系缓存项的访问韶光,包括Cache.asMap().get(Object)方法和 Cache.asMap().put(K, V)方法,但不包括 Cache.asMap().containsKey(Object)方法,也不包括在 Cache.asMap()的凑集视图上的操作。
比如,遍历 Cache.asMap().entrySet()不会重置缓存项的读取韶光。

中断

6、Guava Cache的不敷之处

是单个运用运行时确当地缓存,数据没有持久化存放到文件或外部做事器

单机缓存,受机器内存限定,重启运用缓存数据会丢失,运用分布式支配会涌现缓存数据不一致的情形

分布式支配时如何保持缓存的同等性?

7、Redis

Redis是一个开源的/利用C写的基于内存的、支持网络的、可持久化的、日志型的、供应多种措辞API的Key-Value数据库。

Redis的特点

KV NoSQL

缓存在内存

支持多种数据构造

可持久化:AOF / RDB

高性能、高可靠

支持主从复制

[ 主从复制 ] 是用来建立一个和主数据库完备一样的数据库环境,称为从数据库;主数据库一样平常是实时的业务数据库,从数据库的浸染和利用场合一样平常有几个: 一是作为后备数据库,主数据库做事器故障后,可切换到从数据库连续事情; 二是可在从数据库作备份、数据统计等事情,这样不影响主数据库的性能;

支持事务

总结

到这里,心潮澎湃续写Redis高性能缓存技能就结束了,,不敷之处还望大家多多包涵!

以为收成的话可以点个关注收藏转发一波喔,感激大佬们支持。
(吹一波,233~~)

下面和大家互换几点编程的履历:

1、多写多敲代码,好的代码与踏实的根本知识一定是实践出来的

2丶 测试、测试再测试,如果你不彻底测试自己的代码,那恐怕你开拓的就不但是代码,可能还会声名散乱。

3丶 简化编程,加快速率,代码风骚,在你完成编码后,应转头并且优化它。
从长远来看,这里或那里一些的改进,会让后来的支持职员更加轻松。

末了,每一位读到这里的网友,感谢你们能耐心地看完。
希望在成为一名更精良的Java程序员的道路上,我们可以一起学习、一起进步。

内部互换群569068099 欢迎各位前来互换和分享, 验证:(007)

Java小毛驴,头条出品,每天一篇干货,喜好就收藏+关注

标签:

相关文章

我国土地利用分类代码的构建与应用

土地利用分类代码是我国土地管理的重要组成部分,是土地资源调查、规划、利用和保护的依据。土地利用分类代码的构建与应用显得尤为重要。本...

SEO优化 2025-02-18 阅读1 评论0

微信跳转微信支付便捷支付体验的秘密武器

移动支付已成为人们日常生活中不可或缺的一部分。作为我国领先的社交平台,微信支付凭借其便捷、安全的支付方式,深受广大用户的喜爱。而微...

SEO优化 2025-02-18 阅读1 评论0

探寻会计科目代码背后的奥秘分类与

会计科目代码是会计信息系统中不可或缺的组成部分,它将企业的经济活动进行分类和归纳,为会计核算、财务分析和决策提供重要依据。本文将从...

SEO优化 2025-02-18 阅读1 评论0