Недавно я работал над функцией парсинга rdb файлов, столкнулся с некоторыми проблемами на пути и решил некоторые проблемы. Конкретная причина для этого будет подробно рассмотрена позже, а на этот раз я в основном хочу рассказать о первой трудности, возникающей при запуске обработки файлов: понимании протокола файлов RDB и о том, как читать двоичные файлы.
RDB-файл
[Чтение исходного кода Redis] постоянство RedisКак упоминалось в статье, устойчивость Redis достигается за счет RDB и AOF. Файл RDB Redis представляет собой файл в двоичном формате.С этой точки зрения Redis представляет собой кэш-базу данных в памяти, которая очень быстро сохраняет данные на жесткий диск или восстанавливает данные. Redis имеет различные типы данных: строка, список, хэш, набор, zset.Размер памяти, занимаемый разными типами данных, разный.При разборе данных, которые могут быть распознаны естественным языком, необходимо использовать разные методы.Некоторый протокол или нужны правила. Это чем-то похоже на типы данных в языках программирования.Разные типы данных занимают разный размер байтов, но все они кодируются в двоичном виде при сохранении на компьютер.Это зависит от того, сколько байтов считывается и как их интерпретировать.
Например, тип объекта redis представлен несколькими определенными символами, 0 представляет собой строку после чтения типа строки, за которой следует длина строки, которая сохраняет размер байтов, которые будут считаны следующим образом. формируют значение полного строкового объекта. для сохраненных"name" => "hoohack"
Строковый объект пар ключ-значение, хранящийся в памяти, может быть представлен следующей схемой:
Конечно, помимо строк, в Redis также есть различные объекты, такие как списки, наборы, хэши и т. д. Для этих типов в файле RDB есть разные определения правил, вам нужно только интерпретировать файл в соответствии с протоколом Формат файла RDB, и вы можете его дополнить.Безошибочно интерпретирует документы в символы, которые могут быть описаны естественным языком.
После тщательного сравнения можно обнаружить, что режим работы компьютера аналогичен режиму работы компьютера.Все данные, хранящиеся в компьютере, являются двоичными.Конкретное значение должно зависеть от того, сколько байтов необходимо и какой тип анализа Значение, проанализированное при чтении разных байтов, отличается, имеет тот же размер байта, но сохраняется в разных типах, если выполняется правильное преобразование, оно также правильное. Например, на языке Сиvoid *
Указатель - 4 байта, и int также 4 байта, определите целое число int, сохраните его вvoid *
Это также не проблема, вам нужно только сделать преобразование типов при чтении.
Таким образом, ключом к интерпретации файла RDB является понимание протокола файла RDB.Поскольку протокол формата файла RDB понятен, данные различных типов данных могут быть проанализированы в соответствии с определенным протоколом. Более подробный протокол файла RDB см. в документе с определением формата файла RDB:RDB file format.
Просмотреть файлы RDB
Очистите базу данных Redis, сохраните пару ключ-значение, а затем используйте команду save для сохранения данных в текущем файле базы данных rdb, получите файл dump.rdb.
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set name hoohack
OK
127.0.0.1:6379> save
OK
кот для просмотра файла:
Видно, что это файл, содержащий искаженные символы, потому что файл сохранен в двоичном формате.Если вы хотите распечатать язык, понятный людям, вы можете просмотреть его с помощью команды od в Linux. Команда od используется для вывода байтов, закодированных в восьмеричном, шестнадцатеричном или других форматах файла.Обычно она используется для вывода символов в файле, которые не могут быть напрямую отображены на терминале.Обратите внимание, что вывод - это байты, а символы между разделителями - это все символы, хранящиеся в одном байте.
выходной файл команды od в восьмеричном, шестнадцатеричном и других форматах
Как видно из руководства пользователя, параметр, который выводит шестнадцатеричный формат, — это x, символ — c, и выводится соответствующее соотношение между символом и шестнадцатеричным:od -A x -t x1c -v dump.rdb
Результат печати следующий:
Как видно из приведенного выше рисунка, файл печати представляет собой несколько шестнадцатеричных чисел, и преобразованный в кодовую таблицу ASCII может снова найти соответствующий символ в кодовой таблице ASCII. Например, первый символ,52=5*16+2*1=82='R'
.
Вот к слову, я лично считаю эту команду od очень полезной.Когда есть сомнения в разборе данных, эта команда используется для устранения возникших проблем. Распечатайте содержимое файла, найдите прочитанные символы, сравните протокол файла RDB, чтобы увидеть, какие данные должны быть проанализированы, затем сравните логику синтаксического анализа в коде, чтобы увидеть, есть ли какие-либо проблемы, а затем исправьте код.
Если вам сложно вводить команды, вы можете загрузить файл и просмотреть его онлайн:www.onlinehexeditor.com
Бинарное сохранение и чтение данных
Мы знаем, что все данные компьютера сохраняются в двоичном формате. Символы, которые мы видим, — это данные, полученные путем чтения двоичного файла, а затем проанализированные. Программа выполняет соответствующие преобразования в соответствии с различными типами данных, а затем отображается то, что мы см. характер. Компьютер допускает различные типы данных, такие как: 32-битные целые числа, 64-битные целые числа, строки, числа с плавающей запятой, логические значения и т. д. Различные типы данных считываются путем чтения байтов разного размера в зависимости от типа. Прочитайте это, это искомые данные.
Первым шагом в анализе данных является чтение данных. В компьютере данные, как мы все знаем, считываются байт за байтом. Поэтому первое, чего нужно добиться, — прочитать файл в байтах.
Языком, используемым для реализации функции разбора файлов RDB, на этот раз является Golang.В API операций с файлами Golang предусмотрена функция чтения байтов.File.ReadAt
.
Прототип функции выглядит следующим образом:
func (f *File) ReadAt(b []byte, off int64) (n int, err error)
Функция начинается с позиции off, на которую указывает указатель File, считывает len(b) байт данных и сохраняет их в b. В соответствии с пониманием API я реализовал функцию чтения данных файла по байтам, Функция получает значение длины, которое представляет собой длину байтов, которые нужно прочитать. Конкретный код реализации выглядит следующим образом:
type Rdb struct {
fp *os.File
... // other field
}
func (r *Rdb) ReadBuf(length int64) ([]byte, error) {
// 初始化一个大小为length的字节数组
buf := make([]byte, length)
// 从curIndex开始读取length个字节
size, err := r.fp.ReadAt(buf[:length], r.curIndex)
checkErr(err)
if size < 0 {
fmt.Fprintf(os.Stderr, "cat: error reading: %s\n", err.Error())
return []byte{}, err
} else {
// 读取成功,更新文件操作的偏移量
r.curIndex += length
return buf, nil
}
}
Преобразование данных в Golang
Функция, реализованная выше, возвращает массив байтов. После того, как функция вернет прочитанные данные, их необходимо преобразовать, если их нужно сохранить в другом типе данных. Golang также предоставляет относительно мощный API. Ниже приведено решение преобразования типа данных, с которым я столкнулся при разборе данных, надеюсь, оно вам поможет. нить
str := string(buf)
целое число, сначала преобразованное в двоичное значение, а затем отформатированное с типом int32
intVal := int(binary.BigEndian.Uint32(buf))
целое число int64, сначала преобразованное в двоичное значение, а затем отформатированное с типом int64
int64Val := int64(int16(binary.LittleEndian.Uint16(valBuf)))
число с плавающей запятой
floatVal, err := strconv.ParseFloat(string(floatBuf), 64)
число с плавающей запятой float64, сначала преобразуйте в двоичное значение, а затем вызовите функцию Float64frombits математической библиотеки, чтобы преобразовать двоичное значение в тип float64.
floatBit := binary.LittleEndian.Uint64(buf)
floatVal := math.Float64frombits(floatBit)
Суммировать
Теоретическое понимание и практическое применение различаются.Хотя всем известно, что данные бинарные, то есть как их разбирать, в реальной реализации все еще много проблем. Благодаря практике работы с бинарными файлами были получены следующие результаты:
1. Получите более глубокое представление о том, как данные хранятся в компьютере. Все представляет собой двоичное содержимое 0 и 1. Это просто зависит от того, как вы хотите его использовать. Соответствующие аналогичные преобразования также могут получить то, что вы хотите.
2. При работе в определенной системе вы должны следовать определенному протоколу, иначе вы получите беспорядочные или искаженные вещи.Например, порядок байтов данных также сделает результаты синтаксического анализа данных несогласованными.
Оригинал статьи, ограниченный стиль написания, недостаток знаний и знаний, если есть неточности в статье, сообщите пожалуйста.
Если эта статья была вам полезна, ставьте лайк, спасибо ^_^
Для более интересного контента, пожалуйста, обратите внимание на личный публичный номер.