Redis
 sql >> Base de Dados >  >> NoSQL >> Redis

Atualizando a lista de Redis da pilha de serviços

Evite listas:


Infelizmente, as listas do Redis não são realmente uma boa escolha nesta situação. Eu tive o mesmo problema quando comecei a usar o Redis, eles parecem a escolha óbvia;). As listas do Redis são úteis se você as estiver usando como um conjunto somente leitura ou se quiser apenas pop e push, mas não para modificar um item no meio da lista.

Você pode "atualizar" itens em uma lista Redis se souber o índice do item, mas é necessário remover e re-insira , e deve ser por índice, cuja determinação é terrivelmente ineficiente. Ele faz isso iterando a coleção, porque não há uma maneira nativa de fazer isso, e isso não é uma boa ideia. Este é um trecho do IndexOf método do RedisClientList<T> .
public int IndexOf(T item)
{
    //TODO: replace with native implementation when exists
    var i = 0;
    foreach (var existingItem in this)
    {
        if (Equals(existingItem, item)) return i;
        i++;
    }
    return -1;
}

Então, para completar seu código, seria:
public void UpdatePizza(Pizza pizza)
{
    using (var redisClient = new RedisClient(Host, Port))
    {
        IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>();
        IRedisList<Pizza> pizzas = redis.Lists["pizzas:live"];
        var toUpdate = pizzas.First(x => x.Id == pizza.Id);
        toUpdate.State = pizza.State;

        // Update by removing & inserting (don't do it!)
        var index = pizzas.IndexOf(toUpdate);
        pizzas.Remove(index);
        pizzas.Insert(index, toUpdate);
    }                   
}

Mas esta não é uma boa maneira de lidar com isso como eu disse. Ele recuperará a lista dos outros objetos pizza e, em seguida, iterará sobre eles até que corresponda ao índice. E duas operações para atualizar! :( Melhor evitar listas nesta situação.

Solução:


Como você está tentando acessar a pizza por seu ID, você pode criar uma chave de pizza exclusiva para cada objeto, isso permitirá que você acesse a pizza diretamente. Então podemos usar:
pizzas:live:{Id}

Exemplos:


Criar uma pizza
using (var redisClient = new RedisClient())
{
    IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>();
    var pizzaKey = string.Format("pizzas:live:{0}", 123);
    var pizza = new Pizza { Id = 123, Type = "Mushroom", State = "Cooking" };
    redis.SetEntry(pizzaKey, pizza);
}

Ganhe uma pizza por ID
using (var redisClient = new RedisClient())
{
    IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>();
    var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
    var pizza = redis.GetValue(pizzaKey);
}

Atualizar uma pizza por ID (Simplesmente um GET e SET)
using (var redisClient = new RedisClient())
{
    IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>();
    var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
    var pizza = redis.GetValue(pizzaKey); // Get
    pizza.State = "Delivery"; // Update
    redis.SetEntry(pizzaKey, pizza); // Save
}

Mover para outra "lista" (talvez:quando uma pizza muda de estado)
using (var redisClient = new RedisClient())
{
    var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
    var deliveredKey = string.Format("pizzas:delivered:{0}", pizza.Id);
    redisClient.RenameKey(pizzaKey, deliveredKey);
}

Excluir uma pizza
using (var redisClient = new RedisClient())
{
    var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
    redisClient.Remove(pizzaKey);
}

Liste todas as pizzas ao vivo
using (var redisClient = new RedisClient())
{
    var livePizzaKeys = redisClient.ScanAllKeys("pizzas:live:*").ToList();
    List<Pizza> livePizzas = redisClient.GetValues<Pizza>(livePizzaKeys);
}

Eu espero que isso ajude.