Redis’ slow query logging feature is used to log command requests that take longer than a given amount of time to execute, which can be used to analyze and optimize query speed. In this article, we will analyze how Redis’ slow query logging feature is implemented.
Redis provides two configuration options for slow logging.
- slowlog-log-slower-than: specifies how many microseconds a command request will be logged if it takes longer than 10,000 microseconds to execute, the default is 10,000 microseconds.
- slowlog-max-len: Specifies the maximum number of slow query logs that the server will keep. When the number of slow query logs stored by Redis reaches the specified value, the server will delete the oldest slow query log before adding a new one.
We can use the CONFIG SET/GET command to set/get the values of these two options. Note that the slow query log is stored in memory and not in a log file , which ensures that the slow query log does not become a bottleneck for speed.
Data Structures
The data structure of slowlog is defined in the redisServer
structure.
|
|
It can be seen that the slowlog is stored inside a doubly linked list to facilitate the insertion of new logs at the head of the table, and will be deleted from the end of the table when the amount of logs reaches the set storage limit.
The data of a slowlog is stored in the structure slowlogEntry
, which holds the parameters of the timeout command, duration, log ID, client and other information.
|
|
The value of a slowlog
linked list is a pointer to the log node slowlogEntry
, which together form the data structure of the slow query log. When a new log needs to be added, the add new node function of the linked list is called and the pointer is added to the linked list header.
And why is redisServer.slowlog_entry_id
the ID of the next log? This is a C syntax issue and the specific code used to set the log ID is as follows.
|
|
This line of code will first assign the value of server.slowlog_entry_id
to se.id
and then add 1 to its own value (I always feel a little awkward writing this)
Adding Logs
During the initialization of the Redis service, the initialization function for the slow query function is also executed, creating an empty doubly linked list.
When the client sends a command to the server, the control flow is handed over to server.c/call
, which calls the command implementation function to execute the command and calculates the time taken to execute the command, which is handed over to the slowlog function.
|
|
As you can see from the summary code above, the specific logic is left to the slowlogPushEntryIfNeeded()
function, which adds a new log when the command times out and removes it if the number of logs reaches the limit.
The logic of slowlog implementation is easy to understand. If the timeout is reached, a new element is added to the head of the linked list, and if the number of logs reaches the upper limit, an element is removed from the end of the linked list, probably due to the single-threaded design of Redis, which avoids concurrency problems.
Reference
https://wingsxdu.com/posts/database/redis/slowlog/