Redis
 sql >> Baza danych >  >> NoSQL >> Redis

Kluczowy projekt Redis do aplikacji magazynowych w czasie rzeczywistym

Moja sugestia to przechowywanie wartości min/maks/suma dla wszystkich interwałów, którymi jesteś zainteresowany i aktualizowanie ich o aktualne z każdym przychodzącym punktem danych. Aby uniknąć opóźnień w sieci podczas odczytywania poprzednich danych do porównania, możesz to zrobić w całości wewnątrz serwera Redis za pomocą skryptów Lua.

Jeden klucz na punkt danych (lub, co gorsza, na pole punktu danych) zużywa zbyt dużo pamięci. Aby uzyskać najlepsze wyniki, powinieneś pogrupować je w małe listy/hasze (zobacz http://redis.io/topics/memory-optimization). Redis umożliwia tylko jeden poziom zagnieżdżania w swoich strukturach danych:jeśli dane mają wiele pól i chcesz przechowywać więcej niż jeden element na klucz, musisz jakoś samodzielnie je zakodować. Na szczęście standardowe środowisko Redis Lua zawiera obsługę msgpack, która jest bardzo wydajnym binarnym formatem podobnym do JSON. Wpisy JSON w twoim przykładzie zakodowane za pomocą msgpack "tak jak jest" będą miały długość 52-53 bajtów. Sugeruję grupowanie według czasu, aby mieć 100-1000 wpisów na klucz. Załóżmy, że interwał jednominutowy spełnia to wymaganie. Wtedy schemat kluczy wyglądałby tak:

YYmmddHHMMSS — hash z tid do punktów danych zakodowanych w msgpack na daną minutę.5m:YYmmddHHMM , 1h:YYmmddHH , 1d:YYmmdd — skróty danych okna zawierające min , max , sum pola.

Spójrzmy na przykładowy skrypt Lua, który zaakceptuje jeden punkt danych i w razie potrzeby zaktualizuje wszystkie klucze. Ze względu na sposób, w jaki działa skrypt Redis, musimy jawnie przekazać nazwy wszystkich kluczy, do których skrypt będzie miał dostęp, tj. Dane na żywo i wszystkie trzy klawisze okna. Redis Lua ma również dostępną bibliotekę parsującą JSON, więc dla uproszczenia załóżmy, że po prostu przekazujemy ją do słownika JSON. Oznacza to, że musimy analizować dane dwukrotnie:po stronie aplikacji i po stronie Redis, ale ich wpływ na wydajność nie jest jasny.

local function update_window(winkey, price, amount)
    local windata = redis.call('HGETALL', winkey)
    if price > tonumber(windata.max or 0) then
        redis.call('HSET', winkey, 'max', price)
    end
    if price < tonumber(windata.min or 1e12) then
        redis.call('HSET', winkey, 'min', price)
    end
    redis.call('HSET', winkey, 'sum', (windata.sum or 0) + amount)
end

local currkey, fiveminkey, hourkey, daykey = unpack(KEYS)
local data = cjson.decode(ARGV[1])
local packed = cmsgpack.pack(data)
local tid = data.tid
redis.call('HSET', currkey, tid, packed)
local price = tonumber(data.price)
local amount = tonumber(data.amount)
update_window(fiveminkey, price, amount)
update_window(hourkey, price, amount)
update_window(daykey, price, amount)

Ta konfiguracja może wykonywać tysiące aktualizacji na sekundę, nie obciążając zbytnio pamięci, a dane okien mogą być natychmiast pobierane.

AKTUALIZACJA:Jeśli chodzi o pamięć, 50-60 bajtów na punkt to nadal dużo, jeśli chcesz przechowywać więcej, kilka milionów. Myślę, że przy tego rodzaju danych można uzyskać zaledwie 2-3 bajty na punkt, używając niestandardowego formatu binarnego, kodowania delta i późniejszej kompresji fragmentów za pomocą czegoś takiego jak Snappy. To zależy od Twoich wymagań, czy warto to robić.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Odwrócona paginacja za pomocą posortowanego zestawu Redis

  2. Udostępniać sesje z redis i paszportem na subdomenie?

  3. Jak złapać redis.serializer.SerializationException

  4. Jak bezpiecznie połączyć się z Heroku Redis za pomocą wiersza poleceń?

  5. Chcesz używać Redis jako magazynu statystyk zdarzeń