浏览示例应用程序并发现缓存诊断

学习目标

完成本单元后,您将能够:

  • 解释用于存储和刷新缓存数据的模式。
  • 确定用于缓存值的数据结构。
  • 诊断您的缓存使用情况。

示例应用程序演练

让我们看一个示例应用程序,该应用程序演示如何使用组织缓存来存储和检索货币汇率。汇率在一天内波动,因此该示例应用程序不会返回实时汇率。该应用程序只提供汇率的每日快照。因为我们对准确的实时价值不感兴趣,而只对日常价值感兴趣,因此缓存货币汇率是一个不错的选择。当重复检索汇率时,从缓存中获取汇率会节省大量时间并提高应用程序的性能。

示例应用程序概述

我们将我们的汇率样本申请基于Visualforce页面和Apex控制器,该控制器包含获取汇率的逻辑。第一次访问此页面时,速率是通过对外部Web服务的API调用获得的。只要费率低于一天,此页面的后续执行将从缓存中返回费率。对于每种汇率,此页面显示基础货币,转换的目标货币和转换率。出于说明目的,返回一小组货币。

Visualforce页面显示货币汇率

此示例是Visualforce页面的标记。此页面与ExchangeRates Apex控制器。

<apex:page controller="ExchangeRates" action="{!init}">
    
   <apex:pageBlock title="Rates">
      <apex:pageBlockTable value="{!Rates}" var="rate">
         <apex:column value="{!rate.Base_Currency__c}"/>
         <apex:column value="{!rate.To_Currency__c}"/>
         <apex:column value="{!rate.Rate__c }"/>
      </apex:pageBlockTable>
   </apex:pageBlock>
   
</apex:page>

样品Apex控制器

我们的样品Apex控制器可以完成繁重的工作。它获取汇率,将它们存储在Salesforce和缓存中,并从缓存中检索汇率。以下是样本控制器执行的操作细分,后跟源代码。

第一次运行样本时,会发生以下操作。

  • 汇率是从对外部端点的API调用获得的。
  • 从API调用返回的结果(以JSON格式)将被解析并保存在Salesforce中的Exchange_Rate__c sObjects中。
  • 该 getCachedRates() method将Exchange_Rate__c sObjects数组存储在org缓存中。

在随后的样本执行中:

  • 该示例检查存储数据的新鲜程度。为此,它执行SOQL查询以获取第一个返回的Exchange_Rate__c记录的createdDate值。
  • 如果日期早于一天,则从API调用获得汇率,与第一次执行时一样。
  • 如果日期早于一天,则费率将从组织缓存中获取。如果存在高速缓存未命中,则从Exchange_Rate__c sObject查询速率并将其存储在组织高速缓存中。
注意

注意

Apex控制器使用一个名为的辅助Apex类 RateLib,这里没有显示。此帮助程序类包含用于对传输速率服务进行传出API调用,从API调用解析JSON结果以及存储Exchange_Rate__c记录的方法。

public class ExchangeRates {
    private String currencies = 'EUR,GBP,CAD,PLN,INR,AUD,SGD,CHF,MYR,JPY,CNY';
    public String getCurrencies() { return currencies;}
    public Exchange_Rate__c[] rates {get; set;}
    //                                                                          
    // Checks if the data is old and gets new data from an external web service 
    // through a callout. Calls getCachedRates() to manage the cache.           
    // 
    public void init() {
        // Let's query the latest data from Salesforce
        Exchange_Rate__c[] latestRecords = ([SELECT CreatedDate FROM Exchange_Rate__c 
                        WHERE Base_Currency__c =:RateLib.baseCurrencies 
                              AND forList__c = true 
                        ORDER BY CreatedDate DESC
                        LIMIT 1]);
        
        // If what we have in Salesforce is old, get fresh data from the API
        if ( latestRecords == null  
            || latestRecords.size() == 0 
            || latestRecords[0].CreatedDate.date() < Datetime.now().date()) {
            // Do API request and parse value out
            String tempString = RateLib.getLoadRate(currencies);
            Map<String, String> apiStrings = RateLib.getParseValues(
                tempString, currencies);
            
            // Let's store the data in Salesforce
            RateLib.saveRates(apiStrings);
            // Remove the cache key so it gets refreshed in getCachedRates()
            Cache.Org.remove('Rates');
        }
        // Call method to manage the cache
        rates = getCachedRates();
    }
    //                                                                          
    // Main method for managing the org cache.                                  
    // - Returns exchange rates (Rates key) from the org cache.                 
    // - Checks for a cache miss.                                               
    // - If there is a cache miss, returns exchange rates from Salesforce       
    //    through a SOQL query, and updates the cached value.                   
    //
    public Exchange_Rate__c[] getCachedRates() {
        // Get the cached value for key named Rates
        Exchange_Rate__c[] rates = (Exchange_Rate__c[])Cache.Org.get(
            RateLib.cacheName+'Rates');
        
        // Is it a cache miss? 
        if(rates == null) {
            // There was a cache miss so get the data via SOQL
            rates = [SELECT Id, Base_Currency__c, To_Currency__c, Rate__c 
                        FROM Exchange_Rate__c 
                        WHERE Base_Currency__c =:RateLib.baseCurrencies 
                              AND forList__c = true
                              AND CreatedDate = TODAY];
            // Reload the cache
            Cache.Org.put(RateLib.cacheName+'Rates', rates);
        }
        return rates;
    }
}

要下载Exchange Rate示例的来源并在Developer org中使用它,请参阅参考资料部分。

缓存管理的最佳实践

缓存存储的模式

该 ExchangeRatesApex类包含封装初始化和刷新缓存的逻辑的方法。如果数据陈旧或未找到,则在里面()method通过API调用检索新的汇率,然后将它们存储在Salesforce中。该getCachedRates()方法在内部管理缓存。如果未找到缓存值,则此方法从Salesforce检索一组速率并将其存储在缓存中。

由于我们的应用程序使用外部数据,因此它通过API调用从Web服务获取数据。它还将数据存储为Salesforce记录,作为刷新缓存的备份。不使用外部数据的应用程序使用SOQL检索Salesforce记录并对其进行缓存。在这种情况下,缓存管理过程更简单,缓存方法实现更短。例如,如果您的应用只使用SOQL中的本地数据,则不需要在里面() 方法,但只有 getCachedRates() 方法。

我们建议您在一种方法中包含用于管理缓存的所有逻辑。这样,缓存仅在应用程序的一个位置进行操作。高速缓存的集中管理减少了访问无效高速缓存(高速缓存未命中)或意外覆盖高速缓存值的错误的可能性。

决定缓存什么

此示例将一个sObjects数组存储在缓存中。这种方法是存储数据结构的最佳选择吗?你做出的每一个选择都有权衡。存储较小的数据片段(如字段值而不是整个sObject)可以减少缓存使用量。但是,如果在每个键中存储的数据较少,则可能需要复杂的逻辑来重建数据和sObject,这需要更多的处理时间。并且存储在一个键中的sObject数组使用的缓存空间少于存储在各个键中的各个sObject的总大小。由于序列化和缓存提交时间的开销,缓存较小的项而不是项列表会降低缓存性能。例如,

Cache.Org.put('Rates', rates);

您可以将各个费率存储为具有自己的缓存键的字段,如下所示。

Cache.Org.put('DollarToEuroRate', rateEUR);
Cache.Org.put('DollarToChineseYuan', rateCNY);
Cache.Org.put('DollarToJapaneseYen', rateJPY);
// etc.

决定缓存哪种数据结构取决于您的应用程序对数据的处理方式。例如,如果应用程序转换相同基础货币的货币,则至少存储每种目标货币的汇率。您可以将每种货币汇率存储为单个键。但是为了更容易在Visualforce页面上显示费率,请将数据缓存为sObject列表。sObjects可以增加存储空间,因为它们包含系统字段,例如创建的日期,但它们减少了逻辑处理时间并提高了应用程序和缓存性能。请记住,在使用缓存时,主要目标是减少应用程序的执行时间。

诊断缓存使用情况

所以,你已经完成了所有这些工作来实现Platform Cache。你怎么知道你是否正在充分利用缓存?有几种方法可以检查性能数据。一种方法是在Setup中查看诊断信息(仅在Salesforce Classic中可用)。

在访问诊断页面之前,请为您的用户启用缓存诊断权限。

  1. 从“设置”中,输入users“ 快速查找”框,然后选择“ 用户”
  2. 单击您的用户名,然后单击“ 编辑”
  3. 选择“ 缓存诊断”,然后单击“ 保存”

接下来,访问分区中特定缓存类型的诊断页面。

  1. 从“设置”中,输入cache“ 快速查找”框,然后选择“ 平台缓存”
  2. 单击要检查其诊断信息的分区。
  3. 在会话缓存或组织缓存下,单击“ 诊断”

如果单击“组织缓存”的“ 诊断”,则会在新选项卡中打开“组织缓存诊断”页面。此页面显示两个图表。第一个图表(组织缓存容量和使用情况)显示您的缓存使用限制。在我们的例子中,我们低于极限0.02%。第二个图表(按内容贡献)是一个圆环图,按键显示缓存分布。

注意

注意

因为我们的示例使用org缓存,所以我们只检查诊断页面中的org缓存。还为使用会话高速缓存的应用程序的会话高速缓存提供了类似的诊断页面。

下图显示了包含四个缓存键的内容分发图表。其中一个缓存键Rate用于我们的汇率样本。该 价格键更采用了比空间的一半。

组织缓存的诊断页面

在图表之后,列出了缓存键的详细信息。此列表提供与密钥对应的每个缓存值的大小以及访问缓存的次数。您可以从此列表中手动删除缓存,作为调用该缓存的替代方法去掉()Apex中的方法。“ 删除”按钮允许管理员在不修改任何代码的情况下管理缓存。

该DollarToEuroRate键使用比少得多的空间 价格的关键。这是可以预料的,因为 DollarToEuroRate只存储一个值,而 Rates存储一组sObjects。

使用诊断页面上的信息确定是否调整缓存使用情况。例如,如果缓存值具有较低的访问计数,表明它很少使用,请考虑它是否真的需要,特别是如果它很大。或者,如果您接近缓存使用限制,请重新考虑缓存内容。您可能希望删除不必要的缓存值或购买更多缓存容量。

恭喜!您已经学习了如何使用Platform Cache来缓存应用程序的数据以便快速检索。您还了解了缓存最佳实践以及如何诊断缓存使用情况。您现在已准备好加入花栗鼠的冒险并缓存宝贵的资源!