Хранение огромного рандомизированного списка похожих предметов в Redis - PullRequest
0 голосов
/ 25 февраля 2011

Redis 2.0.3

Мне нужно хранить огромный список предметов в Redis. Каждый элемент представляет собой короткую строку (менее 256 символов).

Мне нужно сделать две операции над списком:

  • Добавьте много (от нескольких тысяч до миллиона) одинаковых предметов. (Несколько раз в день)

  • Удалить один случайный элемент из списка. Не обязательно иметь "честную" случайность. Подойдет любой «достаточно хороший» подход. (До нескольких сотен раз в секунду)

У меня недостаточно оперативной памяти для хранения всех элементов в списке по одному.

Я думаю, что мне нужно хранить вещи партиями, по имени и счетчику. (Там будет до нескольких тысяч различных предметов, больше как несколько сотен.)

Но я не уверен, как организовать это эффективно.

Есть подсказки?

1 Ответ

0 голосов
/ 25 февраля 2011

Ну, так как никто не может мне помочь, вот «тупое» решение в псевдокоде.

  1. Получить случайный элемент:

    function maybe_get_next_item()
      item_name = SRANDMEMBER "items-set"
      item_key = "items:" + item_name
    
      new_item_count = DECR (item_key)
    
      if new_item_count < 0 then
        LOCK -- As explained in SETNX docs
          new_item_count = GET (item_key) -- More added while we were locking?
          if new_item_count and new_item_count < 0 then
            SREM (item_name) -- No, expire it
          end
        UNLOCK
      end
    
      if new_item_count and new_item_count >= 0 then
        return item_name
      end
    
      return false -- this item not found
    end
    
    function get_next_item()
      item_name = maybe_get_next_item()
      while not item_name and (SCARD "items-set" > 0) do
        item_name = maybe_get_next_item()
      end
      return item_name -- false if all items are expended
    end
    
  2. Вставить новые элементы

    function insert_items(item_name, amount)
      LOCK -- As explained in SETNX docs
        SADD "items-set" (item_name)
        INCRBY ("items:" + item_name) amount
      UNLOCK
    end
    

Пожалуйста, предложите лучшее решение, если оно существует, я все еще ругаю Redis и могу пропустить что-то очевидное.

Я подозреваю, что LOCK / UNLOCK в insert_items() может быть лишним и может быть заменен на MULTI / EXEC, но я думаю, что это необходимо для LOCK / UNLOCK в maybe_get_next_item() для правильной работы (которую я не знаю, как заменить на MULTI / EXEC) ...

...