2015-08-12 23 views
10

Użyłem StackExchange.Redis dla cache cache # redis.Jak zapisać element listy w pamięci podręcznej Redis

cache.StringSet("Key1", CustomerObject); 

ale chcę, aby przechowywać dane jak

cache.StringSet("Key1", ListOfCustomer); 

tak, że jeden klucz ma wszystko Lista klientów przechowywane i łatwo jest wyszukiwania, grupy, filtrowanie danych klienta również wewnątrz tej listy

odpowiedzi są mile widziane przy użyciu ServiceStack.Redis lub StackExchange.Redis

Odpowiedz

5

Możesz użyć ServiceStack.Redis wysokiego poziomu IRedisTypedClient Typed API do zarządzania bogatymi typami POCO.

najpierw uzyskać wpisane klienta Redis dla Klientów z:

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

Które rozwiązania wysoki poziom wpisany API do zarządzania klienta POCO, że następnie pozwala utrzymywać pojedynczą Klientowi:

redisCustomers.SetEntry("Customer1", CustomerObject); 

Albo listę klientów z:

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

Należy pamiętać o ServiceStack.Redis [ograniczenia bezpłatnego użytku] (https://servicestack.net/download#free-quotas) – thepirat000

+0

@ thepirat000 jak używać listy używając 'ServiceStack.Redis'? – Neo

+1

W zależności od tego, jak chcesz uzyskać dostęp do listy. Czy zawsze pobierzesz całą listę z Redis, czy też chcesz indywidualnie zajmować się przedmiotami? – thepirat000

23

Jeśli używasz Stackechange.Redis, możesz użyć metod list na swoim interfejsie API. Oto naiwna implementacja ILista przy użyciu listy redis do przechowywania przedmiotów.

Mam nadzieję, że to może pomóc zrozumieć niektóre z metod lista 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()); 
     } 
    } 
} 

Zauważ użycie Newtonsoft.Json dla serializacji. Potrzebne będą następujące nu-get pakiety:

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

Po przeczytaniu pytania i komentarze, ponieważ chcesz uzyskać dostęp do elementów przez klucz, myślę, że szukasz Redis Hashes mapy, które są złożone z pól związanych z wartościami.

Dzięki temu możesz mieć klucz Redis dla skrótu zawierającego wszystkich klientów, z których każdy jest wartością powiązaną z polem. Możesz wybrać CustomerId jako Field, dzięki czemu możesz uzyskać klienta według jego id w O (1).

Myślę, że implementacja IDictionary to dobry sposób na sprawdzenie działania. Więc RedisDictionary klasa podobna do RedisList ale stosując Redis Hash mogą być:

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

A oto kilka przykładów użycia:

// 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]; 

Aktualizacja (październik 2015)

lepszą implementację tych kolekcji można znaleźć w bibliotece CachingFramework.Redis.

Here to kod.

+0

bardzo dziękuję za przykładowy przykład z wartościami listy klientów za pomocą jednego klawisza? – Neo

+0

Dziękuję bardzo podobnie jak moje wymaganie jest przechowywanie wartości klienta w jednej liście klientów i mogę uzyskać wartości z listy, przekazując nazwę klienta również – Neo

+0

, aby uzyskać wszystkie elementy klienta za pomocą 'customers.AddMultiple (customerListFromDb.ToDictionary (k => k .ID)); ' – Neo

Powiązane problemy