Lightning Platform 平台缓存层提供更快的性能和更好的可靠性 缓存 Salesforce 会话和组织数据时。指定要缓存的内容以及不缓存多长时间 使用自定义对象和设置或重载 Visualforce 视图状态。平台缓存 通过分配缓存空间来提高性能,使某些应用程序或操作不会 从他人那里窃取容量。
因为 Apex 在多租户环境中运行,缓存数据在内部并存 缓存数据,缓存对核心 Salesforce 流程的干扰最小。
- 平台缓存功能平台缓存 API 允许您存储和检索与 Salesforce 会话绑定或在整个组织中共享的数据。使用 Cache 命名空间中的 、 、 和 类放置、检索或删除缓存值。使用“设置”中的“平台缓存分区”工具创建或删除组织分区,并分配其缓存容量,以平衡跨应用的性能。SessionOrgSessionPartitionOrgPartition
- 平台缓存注意事项 在使用平台缓存时
,请查看这些注意事项。 - 平台缓存限制 使用平台缓存时,这些限制
适用。 - 平台缓存分区
使用平台缓存分区可以提高应用程序的性能。分区允许您以最适合您的应用程序的方式分配缓存空间。将数据缓存到指定的分区可确保它不会被其他应用程序或不太重要的数据覆盖。 - 平台缓存内部
平台缓存使用本地缓存和最少最近使用的 (LRU) 算法来提高性能。 - 存储和检索会话平台缓存
中的值 使用 和 类管理会话缓存中的值。若要管理任何分区中的值,请使用类中的方法。如果要管理一个分区中的缓存值,请改用这些方法。Cache.SessionCache.SessionPartitionCache.SessionCache.SessionPartition - 从组织平台缓存
中存储和检索值 使用 和 类来管理组织缓存中的值。若要管理任何分区中的值,请使用类中的方法。如果要管理一个分区中的缓存值,请改用这些方法。Cache.OrgCache.OrgPartitionCache.OrgCache.OrgPartition - 将 Visualforce 全局变量用于平台缓存 您可以从具有全局变量的 Visualforce 页面访问存储在会话或组织缓存中的缓存
值。 - 使用 CacheBuilder 接口
安全缓存值 平台缓存最佳实践是通过测试返回 null 的缓存请求来确保您的 Apex 代码处理缓存未命中。您可以自己编写此代码。或者,您可以使用该接口,该接口可以轻松地安全地将值存储和检索到会话或组织缓存中。Cache.CacheBuilder - 平台缓存最佳实践
平台缓存可以大大提高应用程序的性能。但是,请务必遵循这些准则以获得最佳缓存性能。通常,缓存几个大项目比单独缓存多个小项目更有效。还要注意缓存限制,以防止意外的缓存逐出。
平台缓存功能
Platform Cache API 允许您存储和检索绑定的数据 到 Salesforce 会话或在整个组织中共享。放置、检索或删除缓存值 使用 Cache 命名空间中的 、 、 和 类。使用 安装程序中的平台缓存分区工具,用于创建或删除组织分区并分配其 缓存容量,用于平衡跨应用的性能。SessionOrgSessionPartitionOrgPartition有两种类型的缓存:
- 会话缓存 – 存储单个用户会话的数据。例如,在应用中 在指定区域内查找客户,在用户运行时运行的计算 在地图上浏览不同的位置被重复使用。会话缓存与用户并存 会期。会话的最长寿命为 8 小时。会话缓存在其 达到指定的生存时间(值)或会话时 八小时后过期,以先到者为准。ttlsecs
- 组织缓存 – 存储组织中任何用户重复使用的数据。例如,内容 基于用户配置文件动态显示菜单项的导航栏是 重用。与会话缓存不同,组织缓存可以跨会话、请求和 组织用户和配置文件。组织缓存在其指定的生存时间时过期 ( 值)。ttlsecs
此外,Salesforce 还提供 3 MB 的免费平台缓存容量,用于安全审查 通过称为“无提供程序容量”的容量类型托管包。您可以分配 会话缓存和组织缓存的容量来自提供程序免费容量。要缓存的最佳数据是:
- 在整个会话中重复使用
- 静态(不快速变化)
- 否则检索成本高昂
对于会话缓存和组织缓存,您可以构造调用,以便缓存的数据位于一个命名空间中 不会被另一个中的类似数据覆盖。(可选)使用枚举指定 Apex 代码是否可以访问 在调用命名空间之外的命名空间中缓存数据。Cache.Visibility
每个缓存操作都取决于运行该操作的 Apex 事务。如果整个 事务失败,则该事务中的所有缓存操作都将回滚。
试用平台缓存
要在您自己的组织中使用平台缓存来测试性能改进,您可以请求 生产组织的试用缓存。 企业版、无限制版和性能版现已推出 使用一些缓存,但添加更多缓存通常可提供更高的性能。当您的试用期 请求获得批准时,您可以为分区分配容量,并尝试使用 缓存用于不同的场景。通过试用测试缓存,您可以做出明智的决定 决定是否购买缓存。
有关试用缓存的详细信息,请参阅“请求平台缓存试用” 在 Salesforce 帮助中。
您可以请求额外的缓存空间来提高应用程序的性能。为 有关请求其他缓存的详细信息,请参阅“请求其他平台缓存” 在 Salesforce 帮助中。
有关提供程序免费容量缓存的详细信息,请参阅“设置平台” Salesforce 帮助中的“使用提供程序可用容量缓存分区”。
注意
专业版不支持平台缓存。
平台缓存注意事项
使用平台缓存时,请查看这些注意事项。
- 缓存不会持久化。无法保证不会丢失数据。
- 当您修改组织中的 Apex 类时,部分或全部缓存将失效。
- 缓存中的数据未加密。
- 组织缓存支持跨多个同时 Apex 的并发读取和写入 交易。例如,事务使用 值 Fido。同时,另一个事务更新 与值 Felix 相同的键。两次写入都成功,但其中一个 任意选择两个值作为获胜者,然后交易读取该值 价值。但是,这种任意选择是按键而不是按事务进行的。例如 假设一个事务写入 PetType=“Cat” 和 PetName=“Felix”。然后,在同一时刻,另一笔交易 写入 PetType=“Dog” 和 PetName=“Fido”。在这个 情况下,PetType 获胜值可能来自第一笔交易, PetName 获胜值可能来自第二笔交易。 对这些键的后续调用将返回 PetType=“Cat” 和 PetName=“Fido”。get()
- 可能会发生缓存未命中。我们建议在构造代码时考虑以下情况: 找不到以前缓存的项目。或者,使用 CacheBuilder 接口,该接口检查缓存 错过。
- 所有平台缓存统计方法:、、、 从缓存服务器重新启动时开始的数据,不包括之前的数据 重新启动。getAvgGetSize()getAvgGetTime()getMaxGetSize()getMaxGetTime()getMissRate()
- 分区必须遵守 Salesforce 中的限制。
- 会话缓存最多可以存储 8 小时的值。组织缓存可以存储值 至 48 小时。
- 对于使用 Salesforce Flow 的组织:
- 当进程包含计划操作时,请确保 进程不会调用用于存储或检索会话缓存中值的 Apex 代码。 会话缓存限制适用于 Apex 操作和进程的更改 make 到导致 Apex 触发器触发的数据库。
- 当流程包含 Pause 元素时,请确保流程中的后续元素 不要调用用于存储或检索会话缓存中的值的 Apex 代码。这 session-cache 限制适用于 Apex 操作和流所做的更改 添加到导致 Apex 触发器触发的数据库。
平台缓存限制
使用平台缓存时,这些限制适用。
平台缓存限制
特定于版本的限制
下表显示了可用于不同类型组织的平台缓存量。自 购买更多缓存,请联系您的 Salesforce 代表。
版 | 缓存大小 |
---|---|
企业 | 10兆字节 |
无限和性能 | 30兆字节 |
所有其他 | 0 兆字节 |
分区大小限制
限制 | 价值 |
---|---|
最小分区大小 | 1 兆字节 |
会话缓存限制
限制 | 价值 |
---|---|
单个缓存项的最大大小(用于方法)put() | 100 知识库 |
分区的最大本地缓存大小, 每个请求1 | 500 知识库 |
开发人员分配的最短生存时间 | 300 秒(5 分钟) |
开发人员分配的最长生存时间 | 28,800 秒(8 小时) |
最大会话缓存生存时间 | 28,800 秒(8 小时) |
组织缓存限制
限制 | 价值 |
---|---|
单个缓存项的最大大小(用于方法)put() | 100 KB |
分区的最大本地缓存大小, 每个请求1 | 1,000 知识库 |
开发人员分配的最短生存时间 | 300 秒(5 分钟) |
开发人员分配的最长生存时间 | 172,800 秒 (48 小时) |
默认组织缓存生存时间 | 86,400 秒(24 小时) |
1本地缓存是应用程序服务器的内存中容器 客户端在请求期间与之交互。
平台缓存分区
使用平台缓存分区可提高应用程序的性能。 分区允许您以最适合您的应用程序的方式分配缓存空间。 将数据缓存到指定的分区可确保它不会被其他应用程序覆盖,或者 不太重要的数据。
要使用平台缓存,请首先使用平台缓存分区工具设置分区 设置。设置分区后,可以使用Platform Cache Apex API。
要访问“设置”中的“分区”工具,请输入“快速查找”框,然后选择Platform Cache使用分区工具可以:
- 设置具有无提供程序容量的平台缓存分区。
- 请求试用缓存。
- 创建、编辑或删除缓存分区。
- 分配每个分区的会话缓存和组织缓存容量以平衡 跨应用的性能。
- 查看组织的当前缓存容量、细分和分区的快照 分配(以 KB 或 MB 为单位)。
- 查看每个分区的详细信息。
- 将任何分区设置为默认分区。
要使用平台缓存,请至少创建一个分区。每个分区都有一个会话缓存 和一个组织缓存段,您可以为每个段分配单独的容量。会期 缓存可用于存储单个用户会话的数据,而组织缓存用于存储以下数据 组织中的任何用户都可以访问。您可以将组织的缓存空间分布在任意数量的 分区。会话和组织缓存分配可以为零,也可以是 5 或更大,并且它们必须 是整数。所有分区分配的总和,包括默认分区, 等于平台缓存总分配。所有缓存段的总分配容量 必须小于或等于组织的整体容量。
您可以将任何分区定义为默认分区,但只能有一个默认分区 分区。当分区没有分配时,缓存操作(如 get 和 put)不会 调用,并且不会返回任何错误。
在默认分区内执行缓存操作时,可以省略该分区 密钥中的 name。
设置分区后,您可以使用 Apex 代码对 分区。例如,使用 和 类来放置、检索或 删除特定分区缓存上的值。使用 和 获取 使用完全限定的密钥对缓存操作进行分区或执行缓存操作。Cache.SessionPartitionCache.OrgPartitionCache.SessionCache.Org
打包平台缓存分区
打包使用平台缓存的应用程序时,请将任何引用的分区添加到 您的包。分区不会像其他分区那样自动拉入包中 依赖关系是。分区验证在运行时进行,而不是在编译时进行。 因此,如果包中缺少分区,则不会在 编译时。
注意
如果平台缓存代码用于包,请不要使用默认值 分区。相反,显式引用并打包非默认值 分区。无法部署任何包含默认分区的包。
平台缓存内部结构
平台缓存使用本地缓存和最少最近使用的 (LRU) 算法来改进 性能。
本地缓存
平台缓存使用本地缓存来提高性能,确保高效使用 网络,并支持原子事务。本地缓存是应用程序服务器的内存 客户端在请求期间与之交互的容器。缓存操作不交互 直接与缓存层,而是与本地缓存交互。
对于会话缓存,所有缓存项在首次请求时都会加载到本地缓存中。都 后续交互使用本地缓存。同样,组织缓存获取操作检索 缓存层中的值,并将其存储在本地缓存中。后续请求 此值是从本地缓存中检索的。所有可变操作,例如 put 和 remove,也对本地缓存执行。成功完成 request,可变操作被提交。
注意
本地缓存不支持并发操作。可变操作,例如 put 和 remove,针对本地缓存执行,并且仅在整个 Apex 时提交 请求成功。因此,其他并发请求看不到 可变操作。
原子事务
每个缓存操作都取决于它运行的 Apex 请求。如果整个请求 失败时,将回滚该请求中的所有缓存操作。在幕后,使用 本地缓存支持这些原子事务。
逐出算法
如果可能,平台缓存会使用 LRU 算法从缓存中逐出密钥。什么时候 达到缓存限制,密钥将被逐出,直到缓存减少到 100% 能力。如果使用会话缓存,系统将从所有现有缓存中均匀删除缓存 会话缓存实例。本地缓存还使用 LRU 算法。当最大本地 达到分区的缓存大小时,将从 本地缓存。
从会话缓存中存储和检索值
使用 和 类来管理会话缓存中的值。要管理任何分区中的值,请使用 类中的方法。如果您正在管理 将值缓存在一个分区中,请改用这些方法。
Cache.SessionCache.SessionPartitionCache.SessionCache.SessionPartition
Cache.Session 方法
若要在会话缓存中存储值,请调用该方法并提供键和值。密钥名称位于 格式。例如,对于 命名空间 ns1、分区 partition1 和键 orderDate,完全 限定的密钥名称为 。Cache.Session.put()namespace.partition.keyns1.partition1.orderDate
此示例存储一个缓存值,其中包含 钥匙。接下来,代码段检查密钥是否在缓存中,如果是,则检索值 从缓存中。DateTimeorderDateorderDate
// Add a value to the cache
DateTime dt = DateTime.parse('06/16/2015 11:46 AM');
Cache.Session.put('ns1.partition1.orderDate', dt);
if (Cache.Session.contains('ns1.partition1.orderDate')) {
DateTime cachedDt = (DateTime)Cache.Session.get('ns1.partition1.orderDate');
}
若要引用调用类的默认分区和命名空间,请省略前缀并指定键名称。namespace.partition
Cache.Session.put('orderDate', dt);
if (Cache.Session.contains('orderDate')) {
DateTime cachedDt = (DateTime)Cache.Session.get('orderDate');
}
前缀是指 运行代码的当前组织,无论组织是否具有命名空间 定义。如果组织的命名空间定义为 ns1,则以下两个语句是 等效。local
Cache.Session.put('local.myPartition.orderDate', dt);
Cache.Session.put('ns1.myPartition.orderDate', dt);
注意
中的前缀 已安装的托管软件包是指订阅者组织的命名空间,而不是 包的命名空间。缓存调用不是 允许在调用类不拥有的分区中。localput
该方法有多个版本(或 重载),每个版本采用不同的参数。例如,要指定 缓存的值不能被其他命名空间覆盖,设置这个的最后一个参数 方法设置为。以下示例还将 缓存值的生存期(3600 秒或 1 小时),并使该值可用于任何 命名空间。put()true
// Add a value to the cache with options
Cache.Session.put('ns1.partition1.totalSum', '500', 3600, Cache.Visibility.ALL, true);
若要从会话缓存中检索缓存的值,请调用该方法。由于返回一个对象,因此建议您强制转换返回的对象 值设置为特定类型。Cache.Session.get()Cache.Session.get()
// Get a cached value
Object obj = Cache.Session.get('ns1.partition1.orderDate');
// Cast return value to a specific data type
DateTime dt2 = (DateTime)obj;
Cache.SessionPartition 方法
如果要管理一个分区中的缓存值,请改用这些方法。获取分区对象后, 添加和检索缓存值的过程与使用这些方法类似。这些方法更易于使用,因为您只指定了 不带命名空间和分区前缀的键名称。Cache.SessionPartitionCache.SessionCache.SessionPartition
首先,获取会话分区并指定所需的分区。分区名称 包括命名空间前缀:。你 可以通过在 获取的 Partition 对象。以下示例获取 myNs 命名空间。接下来,如果缓存包含带有 key 的值,则检索此缓存值。一个新值是 添加了密钥和今天的日期。namespace.partitionBookTitleorderDate
// Get partition
Cache.SessionPartition sessionPart = Cache.Session.getPartition('myNs.myPartition');
// Retrieve cache value from the partition
if (sessionPart.contains('BookTitle')) {
String cachedTitle = (String)sessionPart.get('BookTitle');
}
// Add cache value to the partition
sessionPart.put('OrderDate', Date.today());
此示例在分区上调用该方法 一个表达式,而不将分区实例分配给变量。get
// Or use dot notation to call partition methods
String cachedAuthor = (String)Cache.Session.getPartition('myNs.myPartition').get('BookAuthor');
从组织缓存中存储和检索值
使用 和 类管理组织缓存中的值。若要管理任何分区中的值,请使用 类。如果要管理 一个分区,使用方法 相反。
Cache.OrgCache.OrgPartitionCache.OrgCache.OrgPartition
Cache.Org方法
若要在组织缓存中存储值,请调用该方法并提供键和值。密钥名称的格式为 。例如,对于命名空间 ns1、partition partition1 和 key orderDate,完全限定键 名称为 。Cache.Org.put()namespace.partition.keyns1.partition1.orderDate
此示例存储一个缓存值,其中包含 钥匙。接下来,代码段检查密钥是否在缓存中,如果是,则检索值 从缓存中。DateTimeorderDateorderDate
// Add a value to the cache
DateTime dt = DateTime.parse('06/16/2015 11:46 AM');
Cache.Org.put('ns1.partition1.orderDate', dt);
if (Cache.Org.contains('ns1.partition1.orderDate')) {
DateTime cachedDt = (DateTime)Cache.Org.get('ns1.partition1.orderDate');
}
若要引用调用类的默认分区和命名空间,请省略前缀并指定键名称。namespace.partition
Cache.Org.put('orderDate', dt);
if (Cache.Org.contains('orderDate')) {
DateTime cachedDt = (DateTime)Cache.Org.get('orderDate');
}
前缀是指 运行代码的当前组织。前缀 指运行代码的当前组织的命名空间,无论是否 组织定义了一个命名空间。如果组织的命名空间定义为 ns1,则以下内容 两个语句是等效的。locallocal
Cache.Org.put('local.myPartition.orderDate', dt);
Cache.Org.put('ns1.myPartition.orderDate', dt);
注意
中的前缀 已安装的托管软件包是指订阅者组织的命名空间,而不是 包的命名空间。缓存调用不是 允许在调用类不拥有的分区中。localput
该方法有多个版本(或 重载),每个版本采用不同的参数。例如,要指定 缓存的值不能被其他命名空间覆盖,设置这个的最后一个参数 方法设置为。以下示例还将 缓存值的生存期(3600 秒或 1 小时),并使该值可用于任何 命名空间。put()true
// Add a value to the cache with options
Cache.Org.put('ns1.partition1.totalSum', '500', 3600, Cache.Visibility.ALL, true);
若要从组织缓存中检索缓存的值,请调用该方法。由于返回一个对象,因此建议您强制转换返回的值 更改为特定类型。Cache.Org.get()Cache.Org.get()
// Get a cached value
Object obj = Cache.Org.get('ns1.partition1.orderDate');
// Cast return value to a specific data type
DateTime dt2 = (DateTime)obj;
Cache.OrgPartition 方法
如果要管理一个分区中的缓存值,请改用这些方法。获取分区对象后, 添加和检索缓存值的过程与使用这些方法类似。这些方法更易于使用,因为您只指定密钥 不带命名空间和分区前缀的名称。Cache.OrgPartitionCache.OrgCache.OrgPartition
首先,获取组织分区并指定所需的分区。分区名称包括 命名空间前缀:。您可以 通过在 获取的 Partition 对象。以下示例获取 myNs 命名空间。如果缓存包含带有 key 的值,则检索此缓存值。使用键和今天的日期添加一个新值。namespace.partitionBookTitleorderDate
// Get partition
Cache.OrgPartition orgPart = Cache.Org.getPartition('myNs.myPartition');
// Retrieve cache value from the partition
if (orgPart.contains('BookTitle')) {
String cachedTitle = (String)orgPart.get('BookTitle');
}
// Add cache value to the partition
orgPart.put('OrderDate', Date.today());
此示例在分区上调用该方法 一个表达式,而不将分区实例分配给变量。get
// Or use dot notation to call partition methods
String cachedAuthor = (String)Cache.Org.getPartition('myNs.myPartition').get('BookAuthor');
将 Visualforce 全局变量用于平台缓存
您可以从 Visualforce 页面访问存储在会话或组织缓存中的缓存值 替换为全局变量。
可以使用 或 全局变量。包括全局变量的 具有命名空间和分区名称的完全限定键名称。$Cache.Session$Cache.Org
此输出文本组件使用全局变量的 命名空间、分区和键。
<apex:outputText value="{!$Cache.Session.myNamespace.myPartition.key1}"/>
此示例与此类似,但使用全局变量从组织缓存中检索值。$Cache.Org
<apex:outputText value="{!$Cache.Org.myNamespace.myPartition.key1}"/>
注意
这 其余示例显示如何使用全局变量访问会话缓存。等效的组织缓存 示例是相同的,只是您改用全局变量。$Cache.Session$Cache.Org与 Apex 方法不同,您不能 省略要引用的前缀 组织中的默认分区。
myNamespace.myPartition
如果未为组织定义命名空间,则用于引用组织的命名空间。local
<apex:outputText value="{!$Cache.Session.local.myPartition.key1}"/>
缓存的值有时是具有属性或方法的数据结构,如 Apex list 或自定义类。在这种情况下,可以使用点表示法访问 or 表达式中的属性。例如,如果 的值声明为 .$Cache.Session$Cache.OrgList.size()numbersListList
<apex:outputText value="{!$Cache.Session.local.myPartition.numbersList.size}"/>
此示例访问声明为 自定义类。
<apex:outputText value="{!$Cache.Session.local.myPartition.myData.value}"/>
如果使用 ,请限定密钥名称 与实现接口的类和文字字符串,以及命名空间和 分区名称。在此示例中,实现的类称为 。CacheBuilderCacheBuilder_B_CacheBuilderCacheBuilderImpl
<apex:outputText value="{!$Cache.Session.myNamespace.myPartition.CacheBuilderImpl_B_key1}"/>
使用 CacheBuilder 接口安全地缓存值
平台缓存最佳实践是确保您的 Apex 代码处理缓存未命中 通过测试返回 null 的缓存请求。您可以自己编写此代码。或者,您可以 使用界面,使它 易于安全地将值存储和检索到会话或组织缓存中。
Cache.CacheBuilder
与其仅仅声明要在 Apex 类中缓存的内容,不如创建一个内部 实现接口的类。这 接口只有一个方法, 通过对基于方法的参数生成缓存值的逻辑进行编码来重写它。CacheBuilderdoLoad(String var)doLoad(String var)
若要检索已缓存的值,请不要直接调用该方法。相反,它第一次由 Salesforce 间接调用 引用实现 的类。 只要该值存在,后续调用就会从缓存中获取该值。如果值 不存在,则该方法被调用 再次生成值,然后返回它。因此,在使用接口时不会执行方法。由于该方法会检查缓存未命中,因此您不必编写 代码自行检查空值。CacheBuilderdoLoad(String var)CacheBuilderdoLoad(String var)put()CacheBuilderdoLoad(String var)
让我们看一个例子。假设您正在为 Visualforce 编写 Apex 控制器类 页。在 Apex 类中,您经常运行 SOQL 查询,该查询根据 用户 ID。SOQL 查询可能很昂贵,而且 Salesforce 用户记录通常不会更改 很多,所以用户信息是 的一个很好的候选者。CacheBuilder
在控制器类中,创建一个实现接口并重写该方法的内部类。然后将 SOQL 代码添加到方法中,并将用户 ID 作为其 参数。CacheBuilderdoLoad(String var)doLoad(String var)
class UserInfoCache implements Cache.CacheBuilder {
public Object doLoad(String userid) {
User u = (User)[SELECT Id, IsActive, username FROM User WHERE id =: userid];
return u;
}
}
若要从组织缓存中检索用户记录,请执行该方法,并向其传递类和用户 ID。同样,使用 和 从会话或 分区缓存。Org.get(cacheBuilder, key)UserInfoCacheSession.get(cacheBuilder, key)Partition.get(cacheBuilder, key)
User batman = (User) Cache.Org.get(UserInfoCache.class, ‘00541000000ek4c');
运行该方法时,Salesforce 会搜索 使用由字符串 00541000000ek4c 和 UserInfoCache 组成的唯一键的缓存。 如果 Salesforce 找到缓存的值,则返回该值。在此示例中,缓存的值是 与 ID 00541000000ek4c 关联的用户记录。如果 Salesforce 找不到值,则 再次执行 UserInfoCache 的方法(并重新运行 SOQL 查询),缓存用户 记录,然后返回它。get()doLoad(String var)
CacheBuilder 编码要求
在编写实现接口的类时,请遵循这些要求。CacheBuilder
- 该方法必须采用参数,即使您不使用 参数。Salesforce 使用字符串和类名来 为缓存的值生成唯一键。doLoad(String var)String
- 该方法可以返回任何 值,包括 null。如果返回 null 值,则将其直接传递给 CacheBuilder 使用者,而不是缓存。CacheBuilder 使用者应处理 正常使用 null 值。建议使用 null 值来反映临时失败 重新生成缓存键。doLoad(String var)
- 实现的类必须是 非静态,因为 Salesforce 实例化了类的新实例并运行该方法以创建缓存的 价值。CacheBuilderdoLoad(String var)
平台缓存最佳实践
平台缓存可以大大提高应用程序的性能。 但是,请务必遵循这些准则以获得最佳缓存性能。在 通常,缓存几个大项目比缓存许多小项目更有效 分别。还要注意缓存限制,以防止意外缓存 拆迁。
评估性能影响
要测试平台缓存是否提高了应用程序的性能,请计算 使用和不使用缓存时经过的时间。不要依赖 Apex 调试日志时间戳 用于执行时间。请改用该方法。例如,首先调用以获取开始时间。执行 应用程序逻辑,从缓存或其他数据源获取数据。然后 计算经过的时间。System.currentTimeMillis()System.currentTimeMillis()
long startTime = System.currentTimeMillis();
// Your code here
long elapsedTime = System.currentTimeMillis() - startTime;
System.debug(elapsedTime);
正常处理缓存未命中
通过测试返回 null 的缓存请求,确保代码处理缓存未命中。自 帮助调试,添加缓存操作的日志记录信息。
或者,使用检查缓存未命中的接口。Cache.CacheBuilder
public class CacheManager {
private Boolean cacheEnabled;
public void CacheManager() {
cacheEnabled = true;
}
public Boolean toggleEnabled() { // Use for testing misses
cacheEnabled = !cacheEnabled;
return cacheEnabled;
}
public Object get(String key) {
if (!cacheEnabled) return null;
Object value = Cache.Session.get(key);
if (value != null) System.debug(LoggingLevel.DEBUG, 'Hit for key ' + key);
return value;
}
public void put(String key, Object value, Integer ttl) {
if (!cacheEnabled) return;
Cache.Session.put(key, value, ttl);
// for redundancy, save to DB
System.debug(LoggingLevel.DEBUG, 'put() for key ' + key);
}
public Boolean remove(String key) {
if (!cacheEnabled) return false;
Boolean removed = Cache.Session.remove(key);
if (removed) {
System.debug(LoggingLevel.DEBUG, 'Removed key ' + key);
return true;
} else return false;
}
}
组缓存请求
如果可能,请对缓存请求进行分组,但请注意缓存限制。帮助改善 性能,则对键列表执行缓存操作,而不是对单个键执行缓存操作。为 例如,如果您知道调用 Visualforce 页面或执行任务需要哪些键 在 Apex 中,一次检索所有密钥。若要检索多个密钥,请调用初始化方法。get(keys)
缓存较大的项目
缓存几个大项目比单独缓存许多小项目更有效。 缓存许多小项目会降低性能并增加开销,包括总 序列化大小、序列化时间、缓存提交时间和缓存容量使用情况。
不要在一个请求中向平台缓存添加许多小项目。相反,将数据包装在 较大的项目,例如列表。如果列表很大,请考虑将其分解为多个项目。 下面是一个要避免的示例。
// Don't do this!
public class MyController {
public void initCache() {
List<Account> accts = [SELECT Id, Name, Phone, Industry, Description FROM
Account limit 1000];
for (Integer i=0; i<accts.size(); i++) {
Cache.Org.put('acct' + i, accts.get(i));
}
}
}
相反,将数据包装在几个相当大的项目中,而不会超过 单个缓存项的大小。
// Do this instead.
public class MyController {
public void initCache() {
List<Account> accts = [SELECT Id, Name, Phone, Industry, Description FROM
Account limit 1000];
Cache.Org.put('accts', accts);
}
}
缓存较大项的另一个很好的例子是将数据封装在 Apex 类中。为 例如,您可以创建一个包装会话数据的类,并缓存该类的实例 而不是单个数据项。缓存类实例可提高整体性能 序列化大小和性能。
注意缓存限制
将项目添加到缓存时,请注意以下限制。缓存分区大小限制当达到缓存分区限制时,将逐出密钥,直到缓存减少 达到 100% 容量。平台缓存使用最近最少使用 (LRU) 算法进行逐出 缓存中的密钥。本地缓存大小限制
将项目添加到缓存时,请确保不超过本地缓存 请求中的限制。会话缓存的本地缓存限制为 500 KB,并且 1,000 KB 用于组织缓存。如果超出本地缓存限制,则可以逐出项目 在提交请求之前从本地缓存中获取。这种驱逐可能会导致 意外失误和序列化时间长,可能会浪费资源。单个缓存项大小限制单个缓存项的大小限制为 100 KB。如果序列化大小 项目超出此限制,则引发异常。这是一个很好的 练习捕获此异常并减小缓存项的大小。Cache.ItemSizeLimitExceededException
使用“缓存诊断”页(谨慎)
要确定使用了多少缓存,请查看“平台缓存诊断”页面。自 到达“诊断”页面:
- 确保为用户启用了缓存诊断(在“用户详细信息”上) 页面)。
- 在“平台缓存分区”页面上,单击分区名称。
- 单击该分区的“诊断”页面的链接。
“诊断”页面提供有价值的信息,包括容量使用情况、密钥、 以及缓存项的序列化和压缩大小。会话缓存和组织缓存 具有单独的诊断页面。会话缓存诊断是按会话进行的,它们 不要在所有活动会话中提供见解。
注意
生成诊断页面 收集所有与分区相关的信息,这是一项成本高昂的操作。使用它 谨慎。
最大限度减少成本高昂的操作
请考虑以下准则,以最大程度地减少成本高昂的操作。
- 谨慎使用。这两种方法都是 昂贵,因为它们遍历所有与分区相关的信息,寻找或制作 给定分区的计算。Cache.Org.getKeys()Cache.Org.getCapacity()注意Cache.Session使用成本不高。
- 避免调用该方法 其次是方法。如果您打算 若要使用键值,只需调用该方法并确保该值不等于 null。contains(key)get(key)get(key)
- 仅在必要时清除缓存。清除缓存会遍历所有 与分区相关的缓存空间,这很昂贵。清除缓存后,您的 应用程序可能会通过调用数据库查询来重新生成缓存,并且 计算。这种再生可能是复杂而广泛的,并会影响您的 应用程序的性能。