Redis Inside или что хранится в редисе?

Jan 15, 2018 08:48 · 797 words · 4 minute read redis

На дашбордах в 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_*.

tweet Share