-1

我需要在 ASP.NET Web API 中缓存有关用户角色的信息。我决定使用System.Web.Helpers.WebCache类。角色是纯字符串,大约 40 个字符长。每个用户可能有 1-10 个角色。

我正在考虑两种方法来做到这一点:

  1. 使用WebCache.Set(UserID, List<String>).使用用户 ID 作为键并将角色列表(字符串)存储为值。它很容易检索。
  2. 使用字典,我将使用 userId 作为键,使用角色列表作为值,然后缓存字典。这样我只用一个键进行缓存。当我检索此信息时,我首先检索字典,然后使用用户 ID 获取角色信息。

问题:

  1. 哪种方法更好?我喜欢方法一,因为它易于使用。它有什么缺点吗?
  2. 我计算用于将这些键保存到缓存中的内存使用的方法是将相同数量的数据(存储 10 个字符串类型的角色)添加到记事本中,然后计算记事本的大小(使用 UTF-8 编码)。大小约为500 bytes,磁盘大小为4 KB. 然后如果我有 200 个用户,我将乘以 200 * 500 字节来计算内存使用量。这是正确的(如果近似关闭,我可以)计算方式吗?
4

5 回答 5

0

1. 方案一是可取的。它很简单,似乎只提供优势。

2.您的计算对选项1有意义,但对选项2没有意义。使用散列的AC#字典占用更多内存,对于像这样的原始数据和短数据,散列所占用的数据可能会显着增加。

与可维护性和功能相比,此类应用程序的单个字节的内存存储通常是次要问题,这是因为用户角色通常是具有相当大安全问题的核心功能,并且随着项目的发展,将变得非常重要的是代码是可维护和安全的。

缓存应该专门用作一种优化,因为这与相对较小的用户群(约 200 人)的少量数据有关,最好使这些角色的缓存细化且易于重新获取。根据这个库的官方文档

Microsoft system.web.helpers.webcache

通常,您永远不应指望已缓存的项目在缓存中

因为我假设用户角色定义了一些相当重要的功能,所以最好将这些角色的查询添加到您的 Web API 请求中,而不是在本地存储它们。

但是,如果您一心想要使用此缓存并在它消失时重新获取,那么根据您的问题,选项一将是一个更可取的选择。

这是因为列表占用的内存更少,在这种情况下看起来更直接,我认为使用字典没有任何好处。

当您拥有大型数据集并需要速度时,字典会大放异彩,但对于所有数据都已存储在内存中且数据集相对较小的场景,字典会带来复杂性和更高的内存要求,而其他方面则不多。尽管在大多数现代设备和服务器上的任何一种情况下,内存使用量听起来都可以忽略不计。

鉴于您需要按用户查找角色,字典可能听起来很有吸引力,但 WebCache 类似乎已经提供了这种功能,因此额外的字典失去了吸引力

于 2018-08-30T18:47:21.453 回答
0

我更喜欢保存单个键的方法,而不是将所有用户的角色保存为单个缓存对象。

以下是原因:

1)创建很简单,当用户登录时或在适当的时间,检查缓存并为该用户创建“如果为空”,无需遍历字典对象(或 LINQ)来获取该键物品。

2)当用户注销或在适当的时刻,缓存对象被完全销毁,而不是仅从缓存中删除该特定键。

3)当多个用户试图同时访问对象时,也不需要锁定对象,这种情况就会发生。由于对象是按用户创建的,因此不存在锁定该对象或需要使用同步或互斥锁的风险。

谢谢, 普拉文

于 2018-08-23T16:06:27.023 回答
0

您不需要选项 2,选项 1 就足够了,因为您只需要key,list<string>.

在使用缓存之前一般要考虑几点:-

  • 缓存的数据量是多少。
  • 您在内存/分布式中使用什么缓存模式。
  • 你将如何管理缓存。
  • 如果正在缓存的数据增长超过阈值,那么跌倒机制是什么。

缓存有其优点和缺点,在您的场景中,您已经完成了有效负载分析,所以我认为选项 1 没有任何问题。

于 2018-09-05T12:02:33.237 回答
0

首先确保会有抽象层,如果将来你可以很容易地改变实现。我看不出这两种方法之间有任何显着差异,它们都使用哈希表进行搜索。但是我想第二次使用搜索两次,当它在缓存中搜索字典和在字典中搜索用户时。我另外推荐

  1. 如果用户数量巨大,则不要将角色存储为字符串,而是存储角色 ID。如果有 1000-10000 没有意义去做

  2. 项目清单

    更新用户角色时不要忘记清除缓存记录

于 2018-09-04T12:33:21.253 回答
0

Q1:不知道Cache项的实际使用情况,很难下定论。尽管如此,我认为这一切都归结为这些项目的生活垃圾邮件的设计。如果您想在一段时间内一次性将它们全部淘汰,然后查询一组新数据,则将包含用户和角色的 ConcurrentDictionary 存储到 WebCache 是一种更易于管理的解决方案。

否则,如果您想根据特定事件单独停用每个条目,则方法似乎是一个相当直接的答案。请注意,如果您选择方法二,请使用 ConcurrentDictionary 而不是 Dictionary,因为后者不是线程安全的。

Q2:WebCache 本质上是一个 IEnumerable>,因此除了对象的元数据之外,它还存储了键字符串和每个值的内存位置。另一方面,ConcurrentDictionary/Dictionary 存储键字符串的哈希码和每个值的内存位置。虽然每个键的 byte[] 长度非常小,但其哈希码可能略大于字符串的大小。否则,HashCodes 的大小是非常可预测的并且相当苗条(在我的测试中大约 10 个字节)。每次添加条目时,整个集合的大小都会增加大约 30 个字节。当然,这个数字不包括价值的实际大小,因为它与收藏无关。

您可以使用以下方法计算字符串的大小:

System.Text.Encoding.UTF8.GetByteCount(key);

您可能还会发现编写代码来实现对象的大小很有用:

static long GetSizeOfObject(object obj) 
{
    using (var stream = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, obj);
        return stream.Length;
    }
}
于 2018-09-04T01:33:56.920 回答