IMemoryCache 保证唯一的新密钥 .NET-Core [英] IMemoryCache Guaranteed Unique new Keys .NET-Core

查看:28
本文介绍了IMemoryCache 保证唯一的新密钥 .NET-Core的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Microsoft.Extensions.Caching.Memory.IMemoryCache 接口/类.

I'm attempting to use the Microsoft.Extensions.Caching.Memory.IMemoryCache interface / class.

我需要向缓存中添加一个新项目,并确保我不会覆盖已保存的其他任何内容.目前,所有密钥都是自动生成和随机化的(不是顺序的).

I need to add a new item to the cache, and make sure I don't override anything else that's already saved. At the moment, all keys are automatically generated and randomized (not sequential).

如何针对当前缓存项测试随机密钥的唯一性?

或者,我怎样才能获得一个有保证的唯一密钥?获得一个自动生成的密钥可以用于以后的检索.

Or, How can I get a guaranteed unique key? It'd be ok getting an auto-generated key that can be used for later retrieval.

https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory 有几个例子,但使用 .TryGetValue(object key, object out value) 为我生成的每个键来测试唯一性似乎有点矫枉过正,当考虑多线程环境时,这可能是一个问题.

https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory has a few examples but using the .TryGetValue(object key, object out value) for each key I generate to test uniqueness seems like overkill, and when considering multi-threaded environments this could be a problem.

博客 https://wildermuth.com/2016/04/14/Using-Cache-in-ASP-NET-Core-1-0-RC1 使用相同的 TryGetValue(key, out value) 模式作为故意的键.

The blog https://wildermuth.com/2016/04/14/Using-Cache-in-ASP-NET-Core-1-0-RC1 uses the same pattern of TryGetValue(key, out value) for deliberate Keys.

我希望不必将这个生成的密钥列表保存在其他地方,即另一个列表分隔列表,因为这会让我回到在列表变老时修剪列表的问题.

I'm hoping NOT to have to keep this list of generated keys somewhere else, i.e. another list separated list, as this would take me back to the issue of trimming the list when it grew old.

作为额外的,在这种特定情况下,我将键作为 url-querystring 参数传递,因此与 url 兼容的字符串将是超级的.提前致谢.

Just as an extra, in this specific case I'm be passing the keys around as url-querystring parameters, so url-compatible strings would be super. Thanks in advance.

推荐答案

正如您已经发现的那样,将 GUID 用于缓存键并不是一个好的解决方案.主要问题是GUID生成后,没有办法可靠地将其重新生成为相同的key,以便从缓存中取出数据.

Using a GUID for a cache key is not a good solution, as you have already discovered. The main problem is that after the GUID is generated, there is no way to reliably regenerate it into the same key in order to get the data out of the cache.

通常,当我创建缓存时,键基于被缓存的实体或缓存它的方法.但也可以基于值的组合来制作缓存,这些值一起使值唯一.

Usually, when I create a cache the keys are based off of the entity being cached or the method that is caching it. But it is also possible to make the cache based on a combination of values that together make the value unique.

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

要从实体中获取键,除了实体的主键之外,我们只需使用一个常量值.

To get the key from an entity, we simply use a constant value in addition to the primary key of the entity.

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() + "_";
}

在这种情况下,我们根据节点所属的父站点地图的唯一键、节点的唯一键、方法或属性名称以及当前是否设置了只读标志来构建键.这些值的每个唯一集合都会产生一个单独的缓存键,从而为每个组合创建一个单独的缓存.

In this case, we are building the key based on the unique key of the parent SiteMap the node belongs to, the unique key of the node, the method or property name, and whether or not the readonly flag is currently set. Each unique set of these values results in a separate cache key, making a separate cache for each combination.

当然,为了使其正常工作,值之间应该有某种安全"分隔符,以防止通过连接不同的值来创建相同的键.例如,"1" + "23""12" + "3" 是相同的字符串,但是您可以通过使用下划线来防止此类冲突,管道字符、逗号或其他一些不会出现在数据中的分隔符来分隔值("1" + "_" + "23"不是"12" + "_" + "3" 相同的字符串).

Of course, for this to work right, there should be some kind of "safe" delimiter between the values to prevent the same key from being created by concatenating different values. For example, "1" + "23" is the same string as "12" + "3", but you can prevent these sort of collisions by using an underscore, pipe character, comma, or some other delimiter that won't be in the data itself to separate the values ("1" + "_" + "23" is not the same string as "12" + "_" + "3").

最重要的是,缓存键必须以某种方式表示缓存中的内容,以便它有用.您的应用程序应了解如何提供构成密钥的数据,以便在需要再次检索相同数据时重新制作.

The bottom line is that the cache key must somehow represent what is in the cache in order for it to be useful. Your application should understand how to provide the data that makes up the key so it can be re-made if the same data needs to be retrieved again.

这篇关于IMemoryCache 保证唯一的新密钥 .NET-Core的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆