Redis sharding cluster construction and its principle
- 1. Redis fragmentation cluster
-
- 1.1. Build a shard cluster
- 1.2. Prepare instance and configuration
- 1.3. Startup
- 1.4. Create a cluster
- 1.5. Testing
- 2. Hash slot principle
-
- 2.1. Slot principle
- 2.2. Summary
- 3. Cluster scaling
-
- 3.1. Demand analysis
- 3.2. Create a new redis instance
- 3.3. Add new nodes to redis
- 3.4. Transfer slot
- 4. Failover
-
- 4.1. Automatic Failover
- 4.2. Manual failover
- 5. RedisTemplate access to fragmented cluster
1. Redis Fragmentation Cluster
1.1. Build a shard cluster
Master-slave and sentry can solve the problem of high availability and high concurrent reading. But there are still two unresolved issues:
-
Mass data storage problem
-
The problem of high concurrent writing
Using fragmented clusters can solve the above problems, as shown in the figure:
Sharded cluster features:
-
There are multiple masters in the cluster, and each master saves different data
-
Each master can have multiple slave nodes
-
The master monitors each other’s health status through ping
-
Client requests can access any node in the cluster and will eventually be forwarded to the correct node
Sharded clusters require a large number of nodes. Here we build a minimal sharded cluster, including 3 master nodes, and each master contains a slave node. The structure is as follows:
Here we will open 6 redis instances in the same virtual machine to simulate a fragmented cluster. The information is as follows:
IP | PORT | Role |
---|---|---|
192.168.150.101 | 7001 | master |
192.168.150.101 | 7002 | master |
192.168.150.101 | 7003 | master |
192.168.150.101 | 8001 | slave |
192.168.150.101 | 8002 | slave |
192.168.150.101 | 8003 | slave |
1.2. Prepare instance and configuration
Delete the previous directories 7001, 7002, and 7003, and recreate the directories 7001, 7002, 7003, 8001, 8002, and 8003:
# Enter the /tmp directory cd /tmp # Delete old ones to avoid configuration interference rm -rf 7001 7002 7003 # Create a directory mkdir 7001 7002 7003 8001 8002 8003
Prepare a new redis.conf file under /tmp with the following content:
port 6379 # Enable the cluster function cluster-enabled yes # The name of the configuration file of the cluster, we do not need to create it, it is maintained by redis itself cluster-config-file /tmp/6379/nodes.conf # Timeout for node heartbeat failure cluster-node-timeout 5000 # Persistence file storage directory dir /tmp/6379 # bind address bind 0.0.0.0 # Let redis run in the background daemonize yes # registered instance ip replica-announce-ip 192.168.150.101 # protected mode protected-mode no # number of databases databases 1 # log logfile /tmp/6379/run.log
Copy this file into each directory:
# Enter the /tmp directory cd /tmp # Execute the copy echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf
Modify redis.conf in each directory, and modify 6379 to be consistent with the directory:
# Enter the /tmp directory cd /tmp # Modify the configuration file printf '%s\ ' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf
1.3. Startup
Since the background startup mode has been configured, the service can be started directly:
# Enter the /tmp directory cd /tmp # Start all services with one click printf '%s\ ' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf
View status via ps:
ps -ef | grep redis
Discovery services have been started normally:
If you want to close all processes, you can execute the command:
ps -ef | grep redis | awk '{print $2}' | xargs kill
or (recommended this way):
printf '%s\ ' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-cli -p {} shutdown
1.4. Create a cluster
Although the service is started, each service is currently independent without any association.
We need to execute commands to create a cluster. It is troublesome to create a cluster before Redis5.0. After 5.0, cluster management commands are integrated into redis-cli.
1) Before Redis5.0
Cluster commands before Redis 5.0 were implemented using src/redis-trib.rb under the redis installation package. Because redis-trib.rb is written in ruby language, it needs to install ruby environment.
# install dependencies yum -y install zlib ruby rubygems gem install redis
Then use the command to manage the cluster:
# Enter the src directory of redis cd /tmp/redis-6.2.4/src # Create a cluster ./redis-trib.rb create --replicas 1 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150.101: 8002 192.168.150.101:8003
2) After Redis5.0
We are using Redis6.2.4 version, cluster management and integration into redis-cli, the format is as follows:
redis-cli --cluster create --cluster-replicas 1 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150 .101:8002 192.168.150.101:8003
Command description:
redis-cli --cluster
or./redis-trib.rb
: represents the cluster operation commandcreate
: means to create a cluster--replicas 1
or--cluster-replicas 1
: Specifies that the number of replicas of each master in the cluster is 1, and the total number ofnodes ÷ (replicas + 1)
What you get is the number of masters. Therefore, the first n in the node list is the master, and the other nodes are all slave nodes, which are randomly assigned to different masters.
What it looks like after running:
Enter yes here, and the cluster will start to be created:
You can view the cluster status with the command:
redis-cli -p 7001 cluster nodes
1.5. Test
Try to connect to node 7001 and store a piece of data:
# connection redis-cli -p 7001 # Storing data set num 123 # read data get num # store again set a 1
The result is tragic:
This is because the a key has been set in other nodes
During cluster operation, you need to add the -c
parameter to redis-cli
:
redis-cli -c -p 7001
This time it works:
2. Hash slot principle
2.1. Slot principle
Redis will map each master node to a total of 16384 slots (hash slots) ranging from 0 to 16383, which can be seen when viewing the cluster information:
Data keys are not bound to nodes, but to slots. Redis will calculate the slot value based on the effective part of the key, in two cases:
- The key contains “{}”, and “{}” contains at least 1 character, and the part in “{}” is a valid part
- The key does not contain “{}”, the entire key is a valid part
For example: if the key is num, then calculate according to num, if it is {zqd}num, then calculate according to zqd. The calculation method is to use the CRC16 algorithm to obtain a hash value, and then take the remainder of 16384, and the result obtained is the slot value.
As shown in the figure, when set a 1 is executed on node 7001, a hash operation is performed on a, and the remainder of 16384 is obtained, and the result is 15495, so it needs to be stored in node 103.
After arriving at 7003, when executing get num
, perform a hash operation on num, take the remainder of 16384, and the result is 2765, so you need to switch to 7001 node
2.2. Summary
How does Redis determine which instance a key should be in?
- Allocate 16384 slots to different instances
- Calculate the hash value according to the effective part of the key, and take the remainder of 16384
- The remainder is used as the slot, just find the instance where the slot is located
How to save the same type of data in the same Redis instance?
- This type of data uses the same effective part, for example, keys are all prefixed with {typeId}
3. Cluster scaling
redis-cli –cluster provides many commands to operate the cluster, which can be viewed in the following ways:
For example, the command to add a node:
3.1. Demand analysis
Requirement: Add a new master node to the cluster and store num = 10 in it
- Start a new redis instance with port 7004
- Add 7004 to the previous cluster and act as a master node
- Assign a slot to the 7004 node so that the key num can be stored in the 7004 instance
Two new functions are needed here:
- Add a node to the cluster
- Assign some slots to new slots
3.2. Create a new redis instance
Create a folder:
mkdir 7004
Copy the configuration file:
cp redis.conf /7004
Modify the configuration file:
sed /s/6379/7004/g 7004/redis.conf
start up
redis-server 7004/redis.conf
3.3. Add new nodes to redis
The syntax for adding a node is as follows:
Excuting an order:
redis-cli --cluster add-node 192.168.150.101:7004 192.168.150.101:7001
Check the cluster status with the command:
redis-cli -p 7001 cluster nodes
As shown in the figure, 7004 has joined the cluster and is a master node by default:
However, it can be seen that the number of slots of the 7004 node is 0, so no data can be stored on the 7004
3.4. Transfer slot
We want to store num to node 7004, so we need to see how many slots num has:
As shown above, the slot of num is 2765.
We can transfer the slots of 0~3000 from 7001 to 7004, the command format is as follows:
The specific commands are as follows:
establish connection:
Get the following feedback:
Ask how many slots to move, we plan to be 3000:
Here comes the new problem:
Which node to receive these slots? ?
Obviously it is 7004, so what is the id of node 7004?
Copy this id, and then copy it to the console just now:
Ask here, where did your slot move from?
- all: represents all, that is, each of the three nodes transfers a part
- Specific id: the id of the target node
- done: no more
Here we want to get from 7001, so fill in the id of 7001:
Once filled, click done, and the slot transfer is ready:
Are you sure you want to transfer? Enter yes:
Then, view the results with the command:
can be seen:
The goal is achieved.
4. Failover
The initial state of the cluster is as follows:
Among them, 7001, 7002, and 7003 are masters, and we plan to shut down 7002.
4.1. Automatic failover
What happens when a master in the cluster goes down?
Stop a redis instance directly, such as 7002:
redis-cli -p 7002 shutdown
1) First, the instance loses connection with other instances
2) Then there is a suspected downtime:
3) Finally, it is determined to go offline and automatically promote a slave to the new master:
4) When the 7002 starts up again, it will become a slave node:
4.2. Manual failover
Using the cluster failover command, you can manually shut down a master in the cluster and switch to the slave node that executes the cluster failover command to realize data migration without awareness. The process is as follows:
This failover command can specify three modes:
- Default: The default process, as shown in Figure 1~6 steps
- force: omits the consistency check of offset
- takeover: Execute step 5 directly, ignoring data consistency, master status and other master opinions
Case requirements: Perform manual failover on the slave node 7002 to regain the status of master
Proceed as follows:
1) Use redis-cli to connect to node 7002
2) Execute the cluster failover command
As shown in the picture:
Effect:
5. RedisTemplate access to shard cluster
The underlying layer of RedisTemplate also implements the support of fragmented clusters based on lettuce, and the steps used are basically the same as the sentinel mode:
1) Introduce the starter dependency of redis
2) Configure the shard cluster address
3) Configure read-write separation
Compared with sentinel mode, only the configuration of fragmented clusters is slightly different, as follows:
spring: redis: cluster: nodes: - 192.168.150.101:7001 - 192.168.150.101:7002 - 192.168.150.101:7003 - 192.168.150.101:8001 - 192.168.150.101:8002 - 192.168.150.101:8003