簡體   English   中英

IMemoryCache保證獨特的新密鑰.NET-Core

[英]IMemoryCache Guaranteed Unique new Keys .NET-Core

我正在嘗試使用Microsoft.Extensions.Caching.Memory.IMemoryCache接口/類。

我需要在緩存中添加一個新項目,並確保我不會覆蓋已保存的任何其他內容。 目前,所有密鑰都是自動生成和隨機化的(不是順序的)。

如何針對當前緩存項測試隨機密鑰的唯一性?

或者,我如何獲得有保證的唯一密鑰? 獲得一個可以用於以后檢索的自動生成密鑰是可以的。

https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory有一些例子,但我為生成的每個鍵使用.TryGetValue(對象鍵,對象輸出值)來測試唯一性似乎過度殺傷,在考慮多線程環境時,這可能是一個問題。

博客https://wildermuth.com/2016/04/14/Using-Cache-in-ASP-NET-Core-1-0-RC1對故意密鑰使用相同的TryGetValue模式(密鑰,輸出值)。

我希望不要在其他地方保留這個生成的密鑰列表,即另一個列表分隔列表,因為這會讓我回到修復列表的問題。

作為一個額外的,在這個特定的情況下,我將傳遞鍵作為url-querystring參數,所以url兼容的字符串將是超級的。 提前致謝。

正如您已經發現的那樣,使用GUID作為緩存密鑰並不是一個好的解決方案。 主要問題是在生成GUID之后,無法將其可靠地重新生成到同一個密鑰中,以便將數據從緩存中取出。


通常,當我創建緩存時,密鑰基於正在緩存的實體或緩存它的方法。 但是,也可以基於值的組合來創建緩存,這些值一起使值唯一。

使用實體的示例

public class Employee
{
    int Id { get; set; }
    string Name { get; set; }
}

要從實體獲取密鑰,除了實體的主鍵之外,我們只使用常量值。

private const string KEY_PREFIX = "Employee_";
private object syncLock = new object();

// innerEmployeeRetriever and cache are populated through the constructor
public Employee GetEmployee(int id)
{
    string key = KEY_PREFIX + id.ToString();

    // Get the employee from the cache
    var employee = cache[key];
    if (employee == null)
    {
        lock (syncLock)
        {
            // Double-check that another thread didn't beat us
            // to populating the cache
            var employee = cache[key];
            if (employee == null)
            {
                employee = innerEmployeeRetriever.GetEmployee(id);
                cache[key] = employee;
            }
        }
    }
    return employee;
}

示例使用方法名稱

private object syncLock = new object();

// innerEmployeeRetriever and cache are populated through the constructor
public Employee GetEmployeeList()
{
    string key = "GetEmployeeList";

    // Get the employee from the cache
    var employees = cache[key];
    if (employees == null)
    {
        lock (syncLock)
        {
            // Double-check that another thread didn't beat us
            // to populating the cache
            var employees = cache[key];
            if (employees == null)
            {
                employees = innerEmployeeRetriever.GetEmployeeList();
                cache[key] = employees;
            }
        }
    }
    return employees;
}

使用值組合的示例

您還可以從幾個不同的值構建密鑰,這些值組合使實體成為唯一的。 如果您沒有要使用的主鍵,或者您要分別緩存多個不同的上下文,這將非常有用。 此示例取自MvcSiteMapProvider

protected string GetCacheKey(string memberName)
{
    // NOTE: We must include IsReadOnly in the request cache key 
    // because we may have a different 
    // result when the sitemap is being constructed than when 
    // it is being read by the presentation layer.
    return "__MVCSITEMAPNODE_" + this.SiteMap.CacheKey + "_" + this.Key 
        + "_" + memberName + "_" + this.IsReadOnly.ToString() + "_";
}

在這種情況下,我們基於節點所屬的父SiteMap的唯一鍵,節點的唯一鍵,方法或屬性名稱以及當前是否設置只讀標志來構建密鑰。 這些值的每個唯一集合都會生成一個單獨的緩存鍵,為每個組合創建一個單獨的緩存。

當然,為了正常工作,值之間應該存在某種“安全”分隔符,以防止通過連接不同的值來創建相同的密鑰。 例如, "1" + "23""12" + "3" "1" + "23"是相同的字符串,但是您可以通過使用下划線,豎線字符,逗號或其他一些不會出現的分隔符來防止這種類型的沖突。在數據本身中分隔值( "1" + "_" + "23" 不是"12" + "_" + "3"相同的字符串)。


底線是,緩存鍵必須以某種方式代表是在高速緩存中,以便它是有用的。 您的應用程序應該了解如何提供構成密鑰的數據,以便在需要再次檢索相同數據時可以重新生成密鑰。

感謝加強Guid獨特性的評論:

我在subejct上搜索了一下,發現Eric Lippert的一篇帖子澄清了我的擔憂: https ://ericlippert.com/2012/05/07/guid-guide-part-three/

  • GUID保證是唯一的,但不保證是隨機的。 不要將它們用作隨機數。

  • 隨機數的GUID不是加密強度隨機數。

  • GUID只有在每個人合作時才是唯一的; 如果有人想重新使用先前生成的GUID,從而人為地創建碰撞,則無法阻止它們。 GUID不是安全機制。

由於我正在創建自己的密鑰,如果我停止刪除字符,我可以信任它們。

你總是可以使用GUID作為唯一鍵,雖然理論上它們當然不是唯一的,因為它們的空間有限,但實際上它們可能不會比隕石摧毀地球的機會少。 因此使用它們相當安全。

另一個問題是為什么你想使用隨機id作為鍵? 當然有一些情況,但通常數據有一些你可以使用的鍵。 例如,如果您在博客引擎中有用戶和帖子,您可以隨時使用$"user_{user.key}"$"post_{post.key}"或類似方法來獲取您的唯一密鑰。 您可以使用完整的類名作為替代。 如果db中的項具有唯一鍵,則此方法將起作用。 由於你沒有完全描述你的情況,很難判斷它是否可能,但我寧願在使用GUID之前嘗試找到“自然鍵”。

PS小心在URL中以這種方式使用GUID。 它可能是也可能不是安全問題。 即如果你將所有用戶的所有數據都放在緩存中並允許通過URL訪問它,那么任何人都可以“猜測”guid並訪問它們不應該訪問的內容。 這並不容易,但可能這樣做,因為你自己寫的時候不能保證它們在加密方面是隨機的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM