简体   繁体   English

如何在Redis缓存中存储列表元素

[英]How to store list element in Redis cache

I have used StackExchange.Redis for c# redis cache. 我已经将StackExchange.Redis用于c#redis缓存。

cache.StringSet("Key1", CustomerObject);

but I want to store data like 但我想存储数据

cache.StringSet("Key1", ListOfCustomer);

so that one key has all Customer List stored and it is easy to search,group,filter customer Data also inside that List 这样一个密钥就可以存储所有客户列表,并且很容易在该列表中搜索,分组,过滤客户数据

Answers are welcome using ServiceStack.Redis or StackExchange.Redis 使用ServiceStack.RedisStackExchange.Redis欢迎使用答案

If you use Stackechange.Redis , you can use the List methods on its API. 如果使用Stackechange.Redis ,则可以在其API上使用List方法。 Here is a naive implementation of IList using a redis list to store the items. 这是IList的一个简单实现,使用redis列表来存储项目。

Hopefully it can help you to understand some of the list API methods: 希望它可以帮助您理解一些列表API方法:

public class RedisList<T> : IList<T>
{
    private static ConnectionMultiplexer _cnn;
    private string key;
    public RedisList(string key)
    {
        this.key = key;
        _cnn = ConnectionMultiplexer.Connect("localhost");
    }
    private IDatabase GetRedisDb()
    {
        return _cnn.GetDatabase();
    }
    private string Serialize(object obj)
    {
        return JsonConvert.SerializeObject(obj);
    }
    private T Deserialize<T>(string serialized)
    {
        return JsonConvert.DeserializeObject<T>(serialized);
    }
    public void Insert(int index, T item)
    {
        var db = GetRedisDb();
        var before = db.ListGetByIndex(key, index);
        db.ListInsertBefore(key, before, Serialize(item));
    }
    public void RemoveAt(int index)
    {
        var db = GetRedisDb();
        var value = db.ListGetByIndex(key, index);
        if (!value.IsNull)
        {
            db.ListRemove(key, value);
        }
    }
    public T this[int index]
    {
        get
        {
            var value = GetRedisDb().ListGetByIndex(key, index);
            return Deserialize<T>(value.ToString());
        }
        set
        {
            Insert(index, value);
        }
    }
    public void Add(T item)
    {
        GetRedisDb().ListRightPush(key, Serialize(item));
    }
    public void Clear()
    {
        GetRedisDb().KeyDelete(key);
    }
    public bool Contains(T item)
    {
        for (int i = 0; i < Count; i++)
        {
            if (GetRedisDb().ListGetByIndex(key, i).ToString().Equals(Serialize(item)))
            {
                return true;
            }
        }
        return false;
    }
    public void CopyTo(T[] array, int arrayIndex)
    {
        GetRedisDb().ListRange(key).CopyTo(array, arrayIndex);
    }
    public int IndexOf(T item)
    {
        for (int i = 0; i < Count; i++)
        {
            if (GetRedisDb().ListGetByIndex(key, i).ToString().Equals(Serialize(item)))
            {
                return i;
            }
        }
        return -1;
    }
    public int Count
    {
        get { return (int)GetRedisDb().ListLength(key); }
    }
    public bool IsReadOnly
    {
        get { return false; }
    }
    public bool Remove(T item)
    {
        return GetRedisDb().ListRemove(key, Serialize(item)) > 0;
    }
    public IEnumerator<T> GetEnumerator()
    {
        for (int i = 0; i < this.Count; i++)
        {
            yield return Deserialize<T>(GetRedisDb().ListGetByIndex(key, i).ToString());
        }
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        for (int i = 0; i < this.Count; i++)
        {
            yield return Deserialize<T>(GetRedisDb().ListGetByIndex(key, i).ToString());
        }
    }
}

Note the use of Newtonsoft.Json for the serialization. 请注意使用Newtonsoft.Json进行序列化。 You will need the following nu-get packages: 您将需要以下nu-get包:

Install-Package Newtonsoft.Json
Install-Package StackExchange.Redis

After reading your question and comments, since you want to access elements by key, I think you're looking for Redis Hashes , which are maps composed of fields associated with values. 在阅读了您的问题和评论后,由于您希望按键访问元素,我认为您正在寻找Redis Hashes ,它是由与值相关联的字段组成的地图。

So you can have a Redis Key for a Hash containing all your Customers, each one being a Value associated to a Field. 因此,您可以拥有包含所有客户的哈希的Redis密钥,每个客户都是与字段关联的值。 You can choose the CustomerId as the Field, so you can then get a customer by its id in O(1). 您可以选择CustomerId作为字段,这样您就可以通过其在O(1)中的ID获取客户。

I think implementing IDictionary is a good way to see it working. 我认为实现IDictionary是一种很好的方式来看它的工作原理。 So a RedisDictionary class similar to the RedisList but using a Redis Hash could be: 所以类似于RedisList但使用Redis Hash的RedisDictionary类可以是:

public class RedisDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
    private static ConnectionMultiplexer _cnn;
    private string _redisKey;
    public RedisDictionary(string redisKey)
    {
        _redisKey = redisKey;
        _cnn = ConnectionMultiplexer.Connect("localhost");
    }
    private IDatabase GetRedisDb()
    {
        return _cnn.GetDatabase();
    }
    private string Serialize(object obj)
    {
        return JsonConvert.SerializeObject(obj);
    }
    private T Deserialize<T>(string serialized)
    {
        return JsonConvert.DeserializeObject<T>(serialized);
    }
    public void Add(TKey key, TValue value)
    {
        GetRedisDb().HashSet(_redisKey, Serialize(key), Serialize(value));
    }
    public bool ContainsKey(TKey key)
    {
        return GetRedisDb().HashExists(_redisKey, Serialize(key));
    }
    public bool Remove(TKey key)
    {
        return GetRedisDb().HashDelete(_redisKey, Serialize(key));
    }
    public bool TryGetValue(TKey key, out TValue value)
    {
        var redisValue = GetRedisDb().HashGet(_redisKey, Serialize(key));
        if (redisValue.IsNull)
        {
            value = default(TValue);
            return false;
        }
        value = Deserialize<TValue>(redisValue.ToString());
        return true;
    }
    public ICollection<TValue> Values
    {
        get { return new Collection<TValue>(GetRedisDb().HashValues(_redisKey).Select(h => Deserialize<TValue>(h.ToString())).ToList()); }
    }
    public ICollection<TKey> Keys
    {
        get { return new Collection<TKey>(GetRedisDb().HashKeys(_redisKey).Select(h => Deserialize<TKey>(h.ToString())).ToList()); }
    }
    public TValue this[TKey key]
    {
        get
        {
            var redisValue = GetRedisDb().HashGet(_redisKey, Serialize(key));
            return redisValue.IsNull ? default(TValue) : Deserialize<TValue>(redisValue.ToString());
        }
        set
        {
            Add(key, value);
        }
    }
    public void Add(KeyValuePair<TKey, TValue> item)
    {
        Add(item.Key, item.Value);
    }
    public void Clear()
    {
        GetRedisDb().KeyDelete(_redisKey);
    }
    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        return GetRedisDb().HashExists(_redisKey, Serialize(item.Key));
    }
    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        GetRedisDb().HashGetAll(_redisKey).CopyTo(array, arrayIndex);
    }
    public int Count
    {
        get { return (int)GetRedisDb().HashLength(_redisKey); }
    }
    public bool IsReadOnly
    {
        get { return false; }
    }
    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        return Remove(item.Key);
    }
    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        var db = GetRedisDb();
        foreach (var hashKey in db.HashKeys(_redisKey))
        {
            var redisValue = db.HashGet(_redisKey, hashKey);
            yield return new KeyValuePair<TKey, TValue>(Deserialize<TKey>(hashKey.ToString()), Deserialize<TValue>(redisValue.ToString()));
        }
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        yield return GetEnumerator();
    }
    public void AddMultiple(IEnumerable<KeyValuePair<TKey, TValue>> items)
    {
        GetRedisDb()
            .HashSet(_redisKey, items.Select(i => new HashEntry(Serialize(i.Key), Serialize(i.Value))).ToArray());
    }
}

And here are some examples to use it: 以下是一些使用它的示例:

// Insert customers to the cache            
var customers = new RedisDictionary<int, Customer>("customers");
customers.Add(100, new Customer() { Id = 100, Name = "John" });
customers.Add(200, new Customer() { Id = 200, Name = "Peter" });

// Or if you have a list of customers retrieved from DB:
IList<Customer> customerListFromDb;
customers.AddMultiple(customerListFromDb.ToDictionary(k => k.Id));

// Query a customer by its id
var customers = new RedisDictionary<int, Customer>("customers");
Customer customer100 = customers[100];

Update (Oct 2015) 更新(2015年10月)

A better implementation of these collections can be found on CachingFramework.Redis library. 可以在CachingFramework.Redis库中找到这些集合的更好实现。

Here is the code. 是代码。

You can use ServiceStack.Redis high-level IRedisTypedClient Typed API for managing rich POCO Types. 您可以使用ServiceStack.Redis高级IRedisTypedClient Typed API来管理丰富的POCO类型。

First get a typed Redis client for Customers with: 首先为客户获取一个类型化的Redis客户端:

var redisCustomers = redis.As<Customer>();

Which will resolve a high-level typed API for managing Customer POCO's that then lets you persist a single Customer with: 这将解析用于管理客户POCO的高级类型API,然后允许您通过以下方式持久保存单个客户:

redisCustomers.SetEntry("Customer1", CustomerObject);

Or a list of Customers with: 或者客户列表:

redisCustomers.Lists["Customers"].AddRange(ListOfCustomer);

StackExchange.Redis has already predefined functions to deal with list and set of values. StackExchange.Redis已经预定义了处理列表和值集的函数。

Get IDatabase object : 获取IDatabase对象:

string cacheConnection = Utils.Sections.Storage.RedisCache.ConnectionString; string cacheConnection = Utils.Sections.Storage.RedisCache.ConnectionString;

IDatabase cache = ConnectionMultiplexer.Connect(cacheConnection).GetDatabase(); IDatabase cache = ConnectionMultiplexer.Connect(cacheConnection).GetDatabase();

methods of list : 列表方法:

cache.ListLeftPushAsync(key, values) -> push one of list of elements cache.ListLeftPushAsync(key,values) - >推送一个元素列表

cache.ListRangeAsync(key, startIndex, endIndex) -> get list of values cache.ListRangeAsync(key,startIndex,endIndex) - >获取值列表

cache.KeyExpire(key, timspan) cache.KeyExpire(key,timspan)

please package StackExchange.Redis for more methods. 请打包StackExchange.Redis以获取更多方法。 You don't need to include any extra nuget package. 您不需要包含任何额外的nuget包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM