Числовая функция в списке redis с использованием lua - PullRequest
0 голосов
/ 22 февраля 2019

Я новичок в Луа и Редис.Я рассматриваю возможность использования Redis для поддержки некоторых запросов в реальном времени.В качестве проверки концепции и проверки работоспособности я суммировал значения в списке.

docker-compose.yml

version: '3.1'

services:
  redis:
    image: redis:4.0.13-alpine
    ports:
      - "6379:6379"

Python-скрипт

import redis
import numpy as np


n = 1000000

redis_host = "localhost"
redis_port = 6379
redis_password = ""

arr = np.random.rand(n)

r = redis.StrictRedis(host=redis_host, port=redis_port, password=redis_password, decode_responses=True)
r.delete('mylist')
r.lpush('mylist', *arr.tolist())
print(np.sum(arr))

lua_sum = """
local result = redis.call('lrange', KEYS[1], 0, -1)
local sum = 0
for i=1, #result, 1 do
    sum = sum + result[i]
end
return tostring(sum)
"""

f = r.register_script(lua_sum)
print(f(keys=['mylist']))

Использование ipython timeitДля версии Redis требуется чуть больше секунды.Я (наивно?) Ожидал, по крайней мере, на порядок меньшую задержку.Есть ли что-то крайне неэффективное в сценарии?Заметьте, я понимаю, что этот конкретный вариант использования может быть обработан предварительной обработкой, но это просто простое начало.

Редактировать В частности, команды timeit:

In [2]: %timeit f(keys=['mylist'])
1 loop, best of 3: 1.31 s per loop

In [3]: %timeit np.sum(arr)
1000 loops, best of 3: 1.04 ms per loop

Ответы [ 2 ]

0 голосов
/ 16 марта 2019

Я думаю, что вы на самом деле ищете что-то вроде redis-benchmark.Он включен в дистрибутив redis.

Из командной строки redis-cli я заполнил пустой случайный экземпляр redis списком, подобным вашему:

127.0.0.1:6379>eval "local result = redis.call('lrange', 'mylist', 0, -1); local sum = 0; for i=1, #result, 1 do sum = sum + result[i]; end; return tostring(sum);" 0

Затем я запустил redis-benchmark:

$ redis-benchmark -n 100000 script load "local result = redis.call('lrange', 'mylist', 0, -1); local sum = 0; for i=1, #result, 1 do sum = sum + result[i]; end; return tostring(sum);"
script load local result = redis.call('lrange', 'mylist', 0, -1); local sum = 0; for i=1, #result, script load local result = redis.call('lrange', 'mylist', 0, -1); local sum = 0; for i=1, #result, script load local result = redis.call('lrange', 'mylist', 0, -1); local sum = 0; for i=1, #result, script load local result = redis.call('lrange', 'mylist', 0, -1); local sum = 0; for i=1, #result, script load local result = redis.call('lrange', 'mylist', 0, -1); local sum = 0; for i=1, #result, ====== script load local result = redis.call('lrange', 'mylist', 0, -1); local sum = 0; for i=1, #result, 1 do sum = sum + result[i]; end; return tostring(sum); ======
  100000 requests completed in 1.20 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

99.99% <= 1 milliseconds
100.00% <= 1 milliseconds
83263.95 requests per second

Как видите, результаты сильно отличаются от того, что вы показываете.100 000 вызовов скрипта были выполнены за 1,2 секунды.

Я не знаю, почему ваши тесты показали значительно худшую производительность, но я могу представить несколько вариантов:

  1. Память / процессорограничения в вашем образе докера
  2. сетевая задержка
  3. накладные расходы из используемой вами библиотеки python-redis

Но, по сути, вам не следует использовать redis для обработкисвязанные скрипты.Поскольку redis является однопоточным, сценарий lua будет блокировать выполнение всех остальных сценариев до тех пор, пока он не завершится.

Я предлагаю вам поэкспериментировать с redis-benchmark, чтобы лучше понять, как работает redis.

0 голосов
/ 23 февраля 2019

Ваш скрипт Lua вызывает LRANGE, чтобы получить 1 миллион номеров от Redis, то есть LRANGE key, 0, -1, что очень неэффективно.Redis должен прочитать 1 миллион номеров из списка и передать эти данные Lua.Это займет много времени.

Кроме того, вы пытаетесь LPUSH 1 миллион номеров для Redis за один вызов, что также является очень плохой идеей, поскольку это может блокировать Redis на длительное время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...