Redis Inside или что хранится в редисе?
Jan 15, 2018 08:48 · 797 words · 4 minute read
На дашбордах в Grafana увидел заметный рост использования памяти Redis’ом (Total memory usage), и мне стало интересно узнать, что же хранится в БД.
Давайте разберемся и проанализируем содержимое redis
двумя способами (для верности)!
На момент анализа БД redis занимала ~720 MB. Посмотреть что именно находится в redis’е можно с помощью утилиты Redis Desktop Manager, но мне также интересно узнать сколько какие ключи занимают в MB и процентном соотношении (данного функционала в RDM нет).
На GitHub нашлось две утилиты, которые могут решить мою проблему. У каждой из них есть свои плюсы/минусы, у них совершенно разный принцип анализа содержимого БД и нет гарантий что результаты их выполнения будут 100% правильными — именно поэтому будем запускать обе утилиты и сравнивать результаты.
Первая называется Redis-audit — она выбирает для анализа часть БД redis, по умолчанию равную 10% от всего объема (эту часть разработчик называет sample и ее можно изменять с помощью опции -s/--sample
). Из выбранного набора (sample) утилита группирует ключи по именам и выводит статистику по группам ключей.
Разработчик не рекомендует запускать данную утилиту на «живой» БД redis
:
DO NOT run this with a lot of keys on a production master database. Keys *
will block for a long time and cause timeouts
Мы прислушаемся к его совету и запустим redis в docker-контейнере на локальном компьютере, предварительно «подсунув» ему файл dump.rdb
c «живой» базы. При старте контейнера redis
восстановит данные из файла в память и ними можно будет работать.
Файл docker-compose.yml
будет выглядеть так:
version: '3.1'
services:
rds:
container_name: rds
image: redis:4.0-alpine
command:
- 'redis-server'
- '--loglevel warning'
- '--databases 2'
- '--maxmemory 800mb'
- '--requirepass password'
volumes:
- ./db:/data
ports:
- "6379:6379"
В папку db, находящуюся в одном каталоге с конфигурационным файлом docker-compose.yml
ложим дамп базы (dump.rdb
) и запускаем контейнер командой:
docker-compose up -d
Устанавливаем утилиту согласно инструкции в Readme.md проекта и запускаем анализатор с помощью команды (в опциях передаем хост / порт / пароль / номер БД / максимальное кол-во ключей в БД):
./redis-audit.rb -h 192.168.0.34 -p 6379 -a password -d 0 -s 2900606
Прогресс и результат выполнения команды в консоли будет выглядеть примерно так (вывод сокращен):
Auditing 192.168.0.34:6379 dbnum:0 sampling 2900606 keys
Getting a list of all 2899366 keys...
Auditing 2899366 keys...
289936 keys sampled - 10% complete - 2017-12-04 14:36:00 +0200
579872 keys sampled - 20% complete - 2017-12-04 14:36:47 +0200
...
2319488 keys sampled - 80% complete - 2017-12-04 14:41:53 +0200
2609424 keys sampled - 90% complete - 2017-12-04 14:42:47 +0200
DB has 2899366 keys
...
==============================================================================
Found 938212 keys containing strings, like:
user_lesson_177790_153, user_lesson_177118_133, user_lesson_167670_42, user_lesson_176796_95, user_lesson_176902_175, user_lesson_153220_19, user_lesson_41101_28, user_lesson_153097_44, user_lesson_110434_153, user_lesson_171883_9
These keys use 0.54% of the total sampled memory (1.79 MB)
100.0% of these keys expire (938212), with maximum ttl of 19 days, 11 hours, 11 minutes, 53 seconds
Average last accessed time: 2 hours, 3 minutes, 47 seconds - (Max: 2 hours, 8 minutes, 12 seconds Min:1 hours, 59 minutes, 23 seconds)
==============================================================================
...
Summary
---------------------------------------------------+--------------+-------------------+---------------------------------------------------
Key | Memory Usage | Expiry Proportion | Last Access Time
---------------------------------------------------+--------------+-------------------+---------------------------------------------------
session_9d3226ff0cc112b6c78299e2a6c9f894 | 90.8% | 100.0% | 1 hours, 59 minutes, 23 seconds
user_175188 | 7.01% | 0.0% | 1 hours, 59 minutes, 23 seconds
ebook-session:9771:lid-108 | 0.78% | 0.0% | 1 hours, 59 minutes, 24 seconds
user_lesson_177790_153 | 0.54% | 100.0% | 1 hours, 59 minutes, 23 seconds
session_6a07a5cbc9baa0edb1fefdbae63a62fe | 0.15% | 100.0% | 1 hours, 59 minutes, 24 seconds
...
ebook:sid-10044:lid-85 | 0.05% | 100.0% | 1 hours, 59 minutes, 23 seconds
global_settings_banner | 0.0% | 0.0% | 2 hours, 5 minutes, 21 seconds
---------------------------------------------------+--------------+-------------------+---------------------------------------------------
Вторая утилита называется redis-rdb-tools и она анализирует непосредственно дамп БД (файл dump.rdb
) и выводит результат в формате *.csv
(еще утилита умеет конвертировать дамп БД в JSON формат и сравнивать два дампа, но этот функционал сейчас нас не интересует).
Устанавливаем утилиту согласно инструкциям в Readme.md и запускаем анализатор командой:
rdb -c memory /home/e.lebed/20171201dump.rdb -f /home/e.lebed/redismemory.csv
После завершения анализа (стоит отметить, что процесс этот небыстрый) в указанном месте (/home/e.lebed/
) появится файл (redismemory.csv
). Содержимое файла выглядит примерно так:
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
0,string,session_60f8b00e9be37602048a11d36b5287b5,504,string,336,336
0,string,session_e9bd5f90b9df52488e3dcd159fb0c526,280,string,150,150
0,string,ebook:sid-14197:lid-39,96,string,8,8
0,string,session_791cd03862862a047a4f6278dcb3fe9f,280,string,152,152
...
Как видим, у нас получились поля Database Number
, Data Type
, Key
, Memory Used in bytes
и т. д. разделенные запятыми. Из данного набора нас интересуют только поля Key
и Memory Used in bytes
— вырезаем их и записываем в другой файл:
cat redismemory.csv | cut -d ',' -f3,4 > redis2fields.txt
В результате получаем файл с таким содержимым:
key,size_in_bytes
session_60f8b00e9be37602048a11d36b5287b5,504
session_e9bd5f90b9df52488e3dcd159fb0c526,280
ebook:sid-14197:lid-39,96
session_791cd03862862a047a4f6278dcb3fe9f,280
...
Далее с помощью утилит grep
и awk
очень легко подсчитать сумму значений во втором столбце (size_in_bytes
) по каждой группе ключей, например:
grep 'user_lesson_*' redis2fields.txt | awk -F ',' 'BEGIN {s = 0} {s += $2;} END {print s}'
93669256
После этого можно внести полученные данные в Excel / Google таблицы, перевести полученные байты в мегабайты и построить диаграмму. Обе утилиты показывают примерно одинаковый результат — больше всего в БД redis
занимают ключи вида session_*
.