Five data type usage scenarios
Type string
Redis provides native commands
** Typical example 1: ** Number of items in stock, number of items viewed, number of likes for questions or replies, etc
incr key
decr key
incrby key increment
decrby key decrement
Copy the code
** Typical example 2: ** Storage of aging information
The Redis data store has the automatic invalidation capability, and the key-value stored can set the expiration time.
For example, a user needs to obtain a login verification code to log in to an App. The verification code is valid within 30 seconds. You can use string to store the verification code and set the expiration time to 30 seconds.
keys = redisCli.get(key); if(keys ! = null) { return false; } else { sendMsg(); redisCli.set(keys, value, expireTime); }Copy the code
List the type
A list is a linked list of strings sorted by insertion order, with new elements inserted at the head and tail
Message queue implementation (generally not used) mainstream: Kafka, RocketMQ, RabbitMQ
Typical example 1: The latest product to hit the shelves
Display the latest TOP 100 products and store the TOP products.
// Add new goods to the list ret = R.push ("new:goods", goodsId) // Keep 100 bits ret = R.trim ("new:goods", 0, Newest_goods_list = r.range ("new:goods", 0, 99)Copy the code
The set type
Set stores an unordered collection with the function of deduplication. Set is used when you need to store a list of items that cannot be duplicated. At the same time, set also provides the intersection, union, difference set.
After obtaining products similar to two users, user analysis can be carried out by determining the categories of similar products. Similar application scenarios include following friends together in social situations, similar interests and so on to make portraits of people.
// userid is the userid, // sadd "user:userId" goodID sadd "user:1001" 1 sadd "user:1001" 2 sadd "user:1002" 1 sadd "user:1002" 3 Sinter "user:1001" "user:1002" // Result is 1Copy the code
Hash type
When Redis stores objects (for example, user information), it needs to serialize the objects and then store them.
{" name ":" isisiwish ", "phone" : "1008611", "sex", "male"}Copy the code
There are many similar scenarios, such as order data, product data, basic merchant information and so on.
The usage scenario of Redis sorted set is similar to that of SET, except that set is unordered. However, sorted set can sort stored data by providing a score parameter, which is automatically sorted and inserted in order. The sorted set data structure can be selected if a business needs an ordered and non-repetitive list of collections.
SDS
Redis string implementation. In versions 3.2 and later, SDS has a variety of structures (SDS.h) :
- sdshdr5
- sdshdr8
- sdshdr16
- sdshdr32
- sdshdr64
Used to store strings of different lengths representing:
2^5=32byte 2^8=256byte 2^16=65536byte=64KB 2^32byte=4GB
Redis uses SDS to implement strings for:
C itself has no string type (it can only be implemented with the character array char[]).
- To use a character array, you must first allocate enough space to the target variable, otherwise it may overflow.
- To get the length of a character, you must traverse the character array in O(n) time.
- C string length changes reallocate memory to the character array.
- The end of the string is marked by the first ‘\0’ encountered from the beginning to the end of the string. Therefore, you cannot save binary (bytes) contents such as pictures, audio, video, and compressed files. Binary is not safe.
The characteristics of the SDS
- Don’t worry about memory overflow, SDS will be expanded if needed.
- The time to get the string length is O(1) because len is defined.
- Multiple memory reallocation is prevented through “space preallocation” (sdsMakeRoomFor) and “lazy space release”.
- The end indicator is the len attribute (which also ends in ‘\0’ because it allows you to manipulate string functions using the C library), which can contain ‘\0’.
Persistence mechanism
Persistence Overview
Redis is an in-memory database. Data is stored in the memory. To avoid permanent data loss caused by process exit, you need to periodically save Redis data in some form (data or commands) from the memory to hard disks. The next time Redis restarts, data is recovered using persistent files.
Redis persistence is divided into RDB persistence, which saves the current data to disk, and AOF persistence, which saves each write command to disk (similar to MySQL’s Binlog). AOF is the current mainstream persistence method because of its better real-time performance, that is, less data is lost when the process exits unexpectedly.
RDB persistence
RDB persistent execution process:
The Reids data in memory is periodically dumped to the RDB file on the disk, and a snapshot of the data set in memory is written to the disk at a specified interval. The actual operation process is fork a sub-process, and the data set is written to a temporary file first. After the data is written to a temporary file, the original file is replaced and stored in binary compression.
Advantages of RDB
- RDB file compact, small size, fast network transmission, suitable for full copy
- The recovery speed is much faster than AOF, and the impact on performance is relatively small
RDB shortcomings
- The data snapshot persistence mode cannot implement real-time persistence
AOF persistence
AOF persistence logs every write command executed by Redis to a separate log file (sort of like MySQL’s binlog); When Redis restarts, the command in the AOF file is executed again to recover the data. Compared with RDB, AOF has better real-time performance, so it has become the mainstream persistence scheme.
AOF execution process:
Command append:
Append the Redis write command to buffer aof_buf and write the command to the file. This prevents the write command from being directly written to the disk every time. As a result, the DISK I/O becomes the bottleneck of Redis load.
The file synchronization policy for the AOF cache is controlled by the appendfsync parameter:
- Always: immediately after writing the aof_buf command, the fsync operation is invoked to synchronize the command to the AOF file. After fsync is complete, the thread returns. 1. Disk I/O becomes a performance bottleneck. 2. Using a SOLID-state drive drastically reduces life span.
- No: after the command is written into aof_buf, the system calls the write operation and does not perform fsync for the AOF file. The operating system is responsible for the synchronization, and the synchronization period is usually 30 seconds. There will be a lot of data and data security cannot be guaranteed.
- Everysec: after writing aof_buf, the system calls write operation, and the thread returns after write. The fsync file synchronization operation is called once per second by a dedicated thread. The default value is recommended.
AOF advantages
- Supports second-level persistence and good compatibility
- The appen-only mode provides high write performance and is suitable for emergency recovery in case of catastrophic misdeletion
AOF shortcomings
- For the same file, the AOF file must be larger than the RDB snapshot. After the AOF function is enabled, the write QPS is affected. Compared with the RDB, the write QPS decreases
AOF common configurations:
- Appendonly No: Whether to enable AOF
- Appendfilename “appendonly.aof” : aof filename
- Dir./ : Directory where RDB files and AOF files reside
- Appendfsync Everysec: Fsync persistence policy
- No-appendfsync-on-rewrite no: Whether to disable fsync during AOF rewriting; If this option is enabled, the load on the CPU and hard disk (especially the hard disk) during file rewriting can be reduced, but the data during AOF rewriting may be lost. There is a balance between load and security
- Auto-aof-rewrite-percentage 100: specifies one of the triggering conditions for file rewriting
- Auto-aof -rewrite-min-size 64MB: one of the file rewrite trigger commits
- Aof-load-truncated yes: If the end of aOF file is damaged, whether the AOF file is still loaded when Redis starts
Strategy choice
In actual production environments, there are various persistence policies based on data volume, data security requirements of applications, and budget constraints. For example, do not use any persistence at all, use either RDB or AOF, or enable both RDB and AOF persistence. In addition, the choice of persistence must be considered in conjunction with the master-slave policy of Redis, because master-slave replication and persistence also have the function of data backup, and the master and slave can choose the persistence scheme independently.
A master-slave mode
An overview of the
Master-slave replication refers to the replication of data from one Redis server to another Redis server. The former is called the master node and the latter is called the slave node. The replication of data is one-way and can only go from the master node to the slave node. And is 1: n.
role
- Data redundancy: Master/slave replication implements hot backup of data and is a data redundancy method other than persistence.
- Fault recovery: When the primary node fails, the secondary node provides services for fast fault recovery, but in fact, it is a kind of service redundancy.
- Load balancing: On the basis of master/slave replication and read/write separation, the master node provides the write service, and the slave node provides the read service (that is, the application connects to the master node when writing Redis data, and the application connects to the slave node when reading Redis data) to share server load. Especially in the scenario of less write and more read, the concurrency of the Redis server can be greatly increased by sharing the read load with multiple slave nodes.
- High availability cornerstone: In addition to the above, master-slave replication is the foundation upon which sentry and clustering can be implemented, hence master-slave replication is the foundation of High availability in Redis.
Implementation principle of master-slave replication
I. Connection establishment stage
- Step 1: The master node information is saved on the slave node. Two fields, masterHost and MasterPort, are internally maintained on the slave node server to store the IP address and port information of the master node.
- Step 2: Establish a socket connection. Call replication timing function replicationCron() on the secondary node once every second. If a primary node is available for connection, a socket connection is created based on the IP address and port of the primary node.
- Step 3: Send the ping command. After the secondary node becomes the client of the primary node, send the ping command for the first request. The purpose is to check whether the socket connection is available and whether the primary node can process the request.
- Step 4: Authentication. Authentication from the slave node is done by sending the auth command to the master node, whose parameter is the value of masterauth in the configuration file. If the password status on the master node is the same as that on the slave node masterauth (consistent means both exist and the password is the same, or neither exists), the authentication succeeds and the replication continues. If no, disconnect the socket from the secondary node and reconnect the socket.
- Step 5: Send the port information of the secondary node. After authentication, the slave node sends the listening port number (6380 in the previous example) to the master node. The master node saves this information to the Slave_listening_port field of the slave node. This port information has no other function than to be displayed when info Replication is being performed on the primary node.
2. Data synchronization stage
The data synchronization phase is the core phase of the master/slave replication. The data synchronization phase can be divided into full replication and partial replication based on the status of the master/slave nodes
Full copy process
- The secondary node sends a request for full replication to the primary node when it detects that partial replication cannot be performed. Or the secondary node sends a partial replication request, but the primary node determines that the full replication cannot be performed.
- When the master node receives the full copy command, it executes bgSave, generates an RDB file in the background, and uses a buffer (called the copy buffer) to record all write commands executed from now on.
- After the bgSave execution of the master node is complete, the RDB file is sent to the slave node. The slave node first cleans its own old data, then loads the received RDB file to update the database state to the database state when the master node executes the BGSave.
- The master node sends all the write commands in the replication buffer described above to the slave node, which executes these write commands to update the database state to the latest state of the master node.
- If AOF is enabled on the slave node, bgreWriteAOF is triggered to ensure that the AOF file is updated to the latest state on the master node.
Impact of full replication
- The primary node forks the RDB persistence using the BGSave command, which is very CPU intensive, memory intensive (page table replication), and disk IO.
- The master node sends RDB files to the slave nodes over the network, which consumes a lot of bandwidth of both the master and slave nodes.
- The process of emptying old data from the node and loading new RDB files is blocked and cannot respond to client commands. There is also an additional cost if bgrewriteaof is executed from the node.
Partial replication process
- The master node and the slave node maintain a replication offset, which represents the number of bytes passed from the master node to the slave node. When the master node propagates N bytes of data to the slave node each time, the offset of the master node increases by N. Each time the slave node receives N bytes of data from the master node, the offset from the node is increased by N.
- The replication backlog buffer is a fixed-length, first-in, first-out (FIFO) queue maintained by the primary node, with a default size of 1MB; Created when the master node has a slave node, it backs up the data that the master node recently sent to the slave node.
- Master-slave node copy for the first time, the master node will own runid (redis – cli info server | grep run_id) sent to the slave node, from the node to the runid saved; When disconnecting and reconnecting, the slave node sends this RUNID to the master node. The master node determines whether partial replication can be performed based on the RUNID: If the rUNID saved by the slave node is the same as the current RUNID of the master node, it indicates that the master node and the slave node have been synchronized before, and the master node will continue to try partial replication (whether partial replication can be achieved depends on offset and replication backlog buffer). If the RUNID saved by the secondary node is different from the current RUNID of the primary node, it indicates that the Redis node synchronized by the secondary node before the disconnection is not the current primary node and can only be fully replicated.
psync
The psync command is executed to determine how the primary and secondary nodes determine whether to use full or partial replication
- How does the secondary node invoke the psync command based on the current status
- The primary node determines whether to perform full or partial replication based on the psync command received and the current server status
Advantages of master-slave mode
- The Master/Slave role is convenient for horizontal expansion, and the QPS is increased.
- Reduce the Master read pressure and transfer it to the Slave node.
- The primary node is down, and the secondary node as a backup of the primary node can continue to provide service overhead at any time.
Disadvantages of master-slave mode
- If the reliability is not very good, the master node fails to provide write service.
- [Fixed] There is no pressure to solve the primary node write.
- Data redundancy (for high concurrency, high availability, and high performance, redundancy is generally allowed);
- Once the master node is down and promoted from the master node to the master node, the address of the master node of the application party needs to be modified, and all the slave nodes need to be ordered to copy the new master node. The whole process needs manual intervention.
- The write capability of the primary node is limited by the stand-alone node.
- The storage capacity of the primary node is limited by the single node.
Selection and optimization techniques of master-slave replication in various scenarios:
** First create copy: **
In this case, full replication is inevitable. However, note the following: If the primary node has a large amount of data, avoid traffic peak hours to avoid congestion. If multiple secondary nodes need to replicate the primary node, stagger the secondary nodes to avoid excessive bandwidth usage on the primary node. In addition, if there are too many slave nodes, the topological structure of the master-slave replication can be adjusted from one master with multiple slave nodes to a tree structure (the middle node is both the slave node of its master node and the master node of its slave node). However, the use of tree structure should be cautious — the reduction of direct slave nodes of the master node reduces the burden of the master node, but the delay of multi-layer slave nodes increases, the data consistency deteriorates, and the structure is complex, and the maintenance is quite difficult.
Restart the active node:
- ** Active node down: ** Runid changes after the active node is down and restarted. Therefore, partial replication cannot be performed. Only full replication can be performed. In fact, in the event that the master node goes down, failover should be performed by upgrading one of the slave nodes to the master and replicating the other slave nodes from the new master. Failover should be as automatic as possible, and sentinels, described later in this article, can do it automatically.
- ** Safe restart: ** In some scenarios, you may want to restart the primary node, for example, the memory fragmentation rate of the primary node is too high, or you may want to adjust some parameters that can only be adjusted at startup. If the master node is restarted by normal means, the RUNID changes, which may lead to unnecessary full replication. To solve this problem, Redis provides debug Reload restart mode: after the restart, the rUNId and offset of the primary node are not affected, avoiding full replication.
- ** Secondary node restart: ** When the secondary node is down and restarted, the runid of its saved primary node is lost, so partial replication cannot be performed even if slaveof is executed again.
- ** Network interruption: **① Network problem time is very short, only caused a short packet loss, master and slave nodes did not determine timeout (did not trigger the Repl-timeout). In this case, you only need to use the REPLCONF ACK to replace the lost data. ② The network problem takes a long time, the master and slave nodes judge timeout (trigger the Repl-timeout), and the lost data is too much, beyond the replication backlog buffer can store the range. In this case, only full replication can be performed on the primary and secondary nodes instead of partial replication. In order to avoid this situation, the size of the replication backlog buffer should be adjusted according to the actual situation. In addition, timely detection and repair of network outages can also reduce full replication.
Configure primary/secondary replication
Configurations related to both master and slave nodes:
- Slaveof: Redis works on startup. The Redis server with this configuration enabled becomes a slave node after being started. This comment is commented out by default, that is, Redis servers are all master nodes by default
- Repl-timeout 60: determines the connection timeout between the primary and secondary nodes in each phase
Configurations related to the active node:
- Repl-diskless-sync no: controls whether the primary node uses diskless replication (diskless replication) during the full replication phase. Diskless replication refers to full replication in which the master node writes data directly into the socket of the slave node rather than into the RDB file. Disks are not involved in the whole process. Diskless replication is more advantageous when disk I/O is slow and network speed is fast. Note that as of Redis3.0, Diskless replication is experimental and is turned off by default
- Repl-diskless-sync-delay 5: This parameter applies to the full replication phase. When the primary node uses diskless replication, this parameter determines the pause time (unit: second) before sending data from the primary node to the secondary node. This parameter is valid only when diskless replication is enabled. The default value is 5s. The pause time is set based on the following considerations: a. Once the data transmission to the slave socket starts, the newly connected slave can only start the new data transmission until the current data transmission ends. B. Multiple secondary nodes have a high probability to establish a primary/secondary replication within a short period of time
- Client-output-buffer-limit slave 256MB 64MB 60: indicates the size of the buffer on the master node in the full replication phase
- Repl -disable-tcp-nodelay no: indicates the delay of command propagation
- Masterauth: Relates to authentication during the connection establishment phase
- Repl-ping-slave-period 10: indicates the timeout judgment of the master and slave nodes during command transmission
- Repl-backlog -size 1mb: specifies the size of the replication backlog buffer
- Repl – backlogs – TTL 3600: Replicates the length of time the backlog buffer remains when the master node has no slave nodes, so that full replication can be performed when the disconnected slave node is reconnected (default: 3600s). If set to 0, the replication backlog buffer is never released.
- Min-rabes-to-write 3 and Min-Rabes-max-lag 10: specify the minimum number of slave nodes and the corresponding maximum delay of the master node
Secondary node configuration:
- Slave-serve-stale-data yes: specifies whether the slave node responds to client commands when data is stale
- Slave-read-only yes: Indicates whether the slave node is read-only. The default is read-only. Data on the primary and secondary nodes may be inconsistent if the write operation is enabled on the secondary node. Therefore, do not modify this configuration
Single machine memory size limit:
- ** Cut off the primary node: ** When the primary node is down, a common Dr Policy is to promote one secondary node to the primary node and mount other secondary nodes to the new primary node. In this case, only full replication can be performed on these secondary nodes. If the Redis single machine memory reaches 10GB, the synchronization time of a slave node is in the order of minutes. If there are more slave nodes, the recovery speed will be slower. If the read load is high and the secondary node cannot provide services during this period, the system is under great pressure.
- Expansion from the secondary library: **** If the number of visits increases suddenly, the secondary node is required to share the read load. If the amount of data is too large, the synchronization from the secondary node is too slow to cope with the sudden increase of visits.
- Buffer overflow: **** When the primary and secondary databases are cut and expanded, the secondary nodes can be synchronized normally (albeit slowly). However, if the amount of data is too large, the replication buffer of the primary node overflows in the full replication phase, resulting in replication interruption. Full replication → Replication interruption due to overflow of the replication buffer → Reconnection → Full replication → Replication interruption due to overflow of the replication buffer…… The loop.
- Timeout: **** If the amount of data is too large, the primary node fork+ Saves the RDB file during the full replication phase, and the secondary node cannot receive data for a long time, triggering a timeout. Data synchronization between the primary and secondary nodes may also fall into full replication → Replication interruption due to timeout → reconnection → Full replication → Replication interruption due to timeout…… The loop.
- Memory limits ** : ** In addition to the absolute amount of memory on the primary node, the percentage of memory used by the primary node should not be too large: it is best to use only 50-65% of the memory, leaving 30-45% for bgsave commands, replication buffers, etc.
The guard mode
Sentinel mode implements automated fault recovery based on master-slave replication.Copy the code
Sentinel mode consists of two parts, sentinel node and data node:
- Sentinel node: Sentinel node is a special Redis node that does not store data.
- Data node: Both primary and secondary nodes are data nodes.
Redis Sentinel is a distributed system mode that monitors the primary and secondary Redis servers and provides automatic failover when the primary server goes offline.
Three features of sentinel mode
- Monitoring: Sentinel constantly checks whether your primary and secondary servers are working properly.
- Alerts: Sentinel can send notifications to administrators or other applications via the API when a monitored Redis server has a problem.
- Automatic failover: Sentinel starts an automatic failover operation when a primary server fails.
- Configure the provider: When the client initializes, it connects to the sentinel to get the primary node address of the current Redis service.
Sentry mode principle
Three scheduled Tasks
- Every 1 second each Sentinel performs a PING (monitor) on other Sentinel and Redis nodes. This is a heartbeat check and is the basis for determining failure.
- Every 2 seconds, each Sentinel exchanges information (Publish/Subscribe) through the channel of the Master node.
- Every 10 seconds, each Sentinel will execute the INFO command for the Master and Slave. This task mainly achieves two objectives: to discover the Slave node; Confirm the master/slave relationship.
Subjective offline
In the scheduled task of heartbeat detection, if other nodes do not reply for a certain period of time, the sentinel node will subjectively take them offline
Objective offline
Is-is master-down-by-addr queries other sentinel nodes about the status of the primary node. If the number of sentinels on the primary node goes offline reaches a certain value, the primary node goes offline objectively
Elect leader sentry nodes
When the master node is judged to be offline objectively, each sentinel node will negotiate to elect a leader sentinel node, and the leader node will failover it.
failover
- Select a new master node from among nodes: First filter out unhealthy slave nodes; Then select the slave node with the highest priority (specified by slave-priority). If the priorities cannot be distinguished, the secondary node with the largest replication offset is selected. If it still cannot be distinguished, the slave node with the smallest RUNId is selected.
- Update the master/slave status: Run the slaveof no one command to make the slave node become the master node. And using the slaveof command to make other nodes its slave nodes.
- The offline primary node is set as the secondary node of the new primary node. When the original primary node comes online again, it becomes the secondary node of the new primary node.
Advantages of Sentinel mode
- The Sentinel mode is based on the master-slave mode, and has all the advantages of the master-slave mode.
- The master and slave can be switched automatically, making the system more robust and more available.
- Sentinel constantly checks to see if your primary and secondary servers are working properly. Sentinel can send notifications to administrators or other applications via the API when a monitored Redis server has a problem.
Disadvantages of Sentinel mode
- The primary/secondary switchover takes time and results in data loss.
- There is still no solution to the primary node write pressure;
- The write capacity and storage capacity of the primary node are limited by the single-node system.
- Dynamic capacity expansion is difficult and complex, but online capacity expansion becomes complicated when the cluster capacity reaches the upper limit.
Configuration and practice suggestions
configuration
- ** Sentinel Monitor {masterName} {masterIp} {masterPort} {quorum} : ** Sentinel monitor {masterName} {masterIp} {quorum} : ** Sentinel monitor {masterName} {masterPort} {quorum} : MasterName specifies the name of the master node, masterIp and masterPort specify the address of the master node, and quorum is the threshold for the number of sentinels to determine the objective offline of the master node: When the number of sentinels to determine the offline of the master node reaches quorum, the master node is objectively offline. The recommended value is half the number of sentinels plus one.
- **sentinel down-after-milliseconds {masterName} {time} : The sentry uses the ping command to ping other nodes and then takes them offline if they fail to respond to down-after-milliseconds. This configuration is valid for subjective offline decisions of master, slave, and sentinel nodes. The default value for down-after-milliseconds is 30,000 (30s). The value can be adjusted based on different network environments and application requirements. A larger value indicates that the subjective offline judgment is more lenient, which reduces the possibility of misjudgment. However, it takes longer to discover and failover faults, and the client waits longer.
- ** Sentinel parallel-syncs {masterName} {number} : ** Sentinel parallel-syncs is related to replication of slave nodes after a failover: it specifies the number of slave nodes to initiate a replication operation to a new master node at a time. For example, after the primary node is switched over, three secondary nodes need to initiate replication to the new primary node. If parallel-syncs=1, the slave nodes are replicated one by one; If parallel-syncs=3, then the three slave nodes start replication together. The larger the parallel-syncs value is, the faster the secondary node completes the replication, but the greater the network load and disk load of the primary node.
- ** Sentinel failover – timeout {masterName} {time} : ** Sentinel failover-timeout is used to determine the timeout of the entire failover phase. For example, if the time for the primary node to be promoted to the secondary node exceeds timeout, the sentinel failover-timeout parameter is used to determine the timeout of the entire failover phase. Or the time (excluding data replication time) for the secondary node to initiate replication to the new master node exceeds timeout, the failover timeout fails. The default value of failover-timeout is 180000, that is, 180s. If you time out, the value will be twice as high the next time.
practice
- There should be more than one sentinel node. On the one hand, the redundancy of sentry nodes is increased to avoid sentry itself becoming the bottleneck of high availability. On the other hand, reduce the misjudgment of the offline. In addition, these different sentinel nodes should be deployed on different physical machines.
- The number of sentries should be an odd number to facilitate sentries to make “decisions” through voting: leader election decisions, objective offline decisions, etc.
- The configuration of each sentinel node should be consistent, including hardware and parameters, etc. In addition, all nodes should use NTP or similar services to ensure accurate and consistent time.
- Sentry’s configuration provider and notification client functions require client support to implement, as mentioned above in Jedis; If the developer is using a library that does not provide support, you may need to implement it yourself.
- When nodes in a sentry system are deployed in Docker (or any other software that may perform port mapping), special care should be taken that port mapping may cause the Sentry system to fail to function properly because the sentry’s work is based on communicating with other nodes, and Docker’s port mapping may cause the sentry to fail to connect to other nodes.