Project practice, Redis cluster technology learning

2. Forget nodes

Because the nodes in the cluster constantly exchange node states with each other through the mission message, a robust mechanism is needed to make all nodes in the cluster forget the offline nodes. In other words, let other nodes no longer exchange Gossip messages with the nodes to be offline. Redis provides the cluster forget{downNodeId} command

Make it possible to realize this function.

After receiving the cluster forget{down NodeId} command, the node specified by nodeId will be added to the disable list, and the nodes in the disable list will no longer send the mission message. The validity period of the disable list is 60 seconds. After 60 seconds, the node will participate in the message exchange again. In other words, after the first forget command is issued, we have 60 seconds to let all nodes in the cluster forget the offline nodes.

For online operation, it is not recommended to directly use the cluster forget command to offline nodes. It needs to interact with a large number of node commands. The actual operation is too cumbersome and it is easy to miss the forget node. It is recommended to use redis trib Rbdel node {host: port}{downNodeId} command,

When the offline master node has a slave node, it is necessary to point the slave node to other master nodes, so for the master-slave node

When all nodes are offline, it is recommended to offline the slave node first and then the master node to prevent unnecessary full replication

System. For the offline operation of nodes 6381 and 6384, the commands are as follows:

redis-trib.rb del-node 127.0.0.1:6379

4fa7eac4080f0b667ffeab9b87841da49b84a6e4 # slave node ID

redis-trib.rb del-node 127.0.0.1:6379

40b8d09d44294d2e23c7c768efc8fcd153446746 # master node 6381 id

Confirm the node status after the node goes offline:

127.0.0.1:6379> cluster nodes

6384 and 6381 nodes are no longer included in the cluster node status. So far, we have completed the safe offline of nodes. The new cluster structure is shown in the following figure:

10.5 request routing

At present, we have built the redis cluster and understood the details of communication and scaling, but we have not used the client to operate the cluster. Redis cluster has greatly modified the client communication protocol. In order to maximize performance, it does not use the proxy method, but the client directly connects to the node. Therefore, for applications that want to switch from a single machine to a cluster environment, the client code needs to be modified.

2.Smart client - JedisCluster

(1) Definition of JedisCluster

Jedis provides a Smart client for Redis Cluster. The corresponding class is JedisCluster. Its initialization method

As follows:

public JedisCluster(Set<HostAndPort> jedisClusterNode, int connectionTimeout, int 
 soTimeout, int maxAttempts, final GenericObjectPoolConfig poolConfig) {
 ...
}

It contains five parameters:

·Set < hostandport > jedisclusternode: all Redis Cluster node information (or part of it, because the client can automatically discover it through cluster slots).

·int connectionTimeout: connection timeout.

·int soTimeout: read / write timeout.

·int maxAttempts: number of retries.

·GenericObjectPoolConfig poolConfig: connection pool parameter. JedisCluster will create a connection pool for each node of Redis Cluster.

For example, the following code shows the initialization process of JedisCluster

1. // Initialize all nodes (for example, 6 nodes)
2. Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
3. jedisClusterNode.add(new HostAndPort("10.10.xx.1", 6379));
4. jedisClusterNode.add(new HostAndPort("10.10.xx.2", 6379));
5. jedisClusterNode.add(new HostAndPort("10.10.xx.3", 6379));
6. jedisClusterNode.add(new HostAndPort("10.10.xx.4", 6379));
7. jedisClusterNode.add(new HostAndPort("10.10.xx.5", 6379));
8. jedisClusterNode.add(new HostAndPort("10.10.xx.6", 6379));
9. // Initialize the commnon pool connection pool and set relevant parameters
10. GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
11. // Initialize JedisCluster
12. JedisCluster jedisCluster = new JedisCluster(jedisClusterNode, 1000,
1000, 5, poolConfig);

JedisCluster can call commands, as shown below.

jedisCluster.set("hello", "world");
jedisCluster.get("key");

(2) Multi node commands and operations

Redis Cluster provides distributed features, but some commands or operations, such as keys

Flush all and delete the key of the specified mode. You need to traverse all nodes to complete it. The following code implements the function of deleting the specified mode key from Redis Cluster:

1. // Delete batch data from cluster
2. public void delRedisClusterByPattern(JedisCluster jedisCluster, String patte
rn,
3. int scanCounter) {
4. // Get JedisPool of all nodes
5. Map<String, JedisPool> jedisPoolMap = jedisCluster.getClusterNodes();
6. for (Entry<String, JedisPool> entry : jedisPoolMap.entrySet()) {
7. // Get Jedis connection for each node
8. Jedis jedis = entry.getValue().getResource();
9. // Delete primary node data only
10. if (!isMaster(jedis)) {
11. continue;
12. }
13. // Use Pipeline to delete the data of the specified prefix each time
14. Pipeline pipeline = jedis.pipelined();
15. // Scan data with specified prefix using scan
16. String cursor = "0";
17. // Specify scanning parameters: number of scans per time and pattern
18. ScanParams params = new ScanParams().count(scanCounter).match(patter
n);
19. while (true) {
20. // Perform scan
21. ScanResult<String> scanResult = jedis.scan(cursor, params);
22. // Deleted key list
23. List<String> keyList = scanResult.getResult();
24. if (keyList != null && keyList.size() > 0) {
25. for (String key : keyList) {
26. pipeline.del(key);
27. }
28. // Batch delete
29. pipeline.syncAndReturnAll();
30. }
31. cursor = scanResult.getStringCursor();
32. // If the cursor changes to 0, the scanning is completed
33. if ("0".equals(cursor)) {more IT For certification courses, please visit the United States
break;
35. }
36. }
37. }
38. }
39. // Judge whether the current Redis is a master node
40. private boolean isMaster(Jedis jedis) {
41. String[] data = jedis.info("Replication").split("\r\n");
42. for (String line : data) {
43. if ("role:master".equals(line.trim())) {
44. return true;
45. }
46. }
47. return false;
48. }

It is divided into the following steps:

1) Through jediscluster Getclusternodes() gets the connection pool of all nodes.

2) Use info replication to filter the master nodes in 1).

3) Traverse the master node, use the scan command to find the key of the specified mode, and use the Pipeline mechanism to delete it.

For example, the following operation traverses 1000 keys at a time, and all keys starting with user in Redis Cluster

Delete.

String pattern = "user*";

int scanCounter = 1000;

delRedisClusterByPattern(jedisCluster, pattern, scanCounter);

Therefore, for commands that need to traverse all nodes, such as keys and flush, you can also refer to the above method to realize the corresponding functions.

(3) For more IT certification courses, please visit Meihe learning online ww

In Redis Cluster, mget, mset and other functions cannot be realized due to the distribution of keys to various nodes. However, you can use the CRC16 algorithm to calculate the slot corresponding to the key, and the Smart client saves the corresponding relationship between the slot and the node, archive the keys belonging to the same Redis node, and then perform mget or pipeline operations on the sub key list corresponding to each node.

(4) Methods of using Lua, transaction, etc

Lua and transaction require the key to be operated, which must be on the same node. However, Redis Cluster provides hashtag. If developers really want to use Lua or transaction, they can use a hashtag for the key to be operated, as shown below:

1. // hashtag
2. String hastag = "{user}";
3. // User A's attention table
4. String userAFollowKey = hastag + ":a:follow";
5. // User B's fan list
6. String userBFanKey = hastag + ":b:fans";
7. // Calculate the slot corresponding to hashtag
8. int slot = JedisClusterCRC16.getSlot(hastag);
9. // Gets the JedisPool of the specified slot
10. JedisPool jedisPool = jedisCluster.getConnectionHandler().getJedisPoolFromSl
ot(slot);
11. // Execute transactions on the current node
12. Jedis jedis = null;
13. try {
14. jedis = jedisPool.getResource();
15. // User A's attention table is added to user B, and user B's fan list is added to user A
16. Transaction transaction = jedis.multi();
17. transaction.sadd(userAFollowKey, "user:b");
18. transaction.sadd(userBFanKey, "user:a");
19. transaction.exec();
20. } catch (Exception e) {
21. logger.error(e.getMessage(), e);
22. } finally {
23. if (jedis!= null)
24. jedis.close();
25. }

Add all key s in the transaction to hashtag.

2) Use CRC16 to calculate the slot corresponding to hashtag.

3) Gets the JedisPool of the node connection pool corresponding to the specified slot.

4) Execute transactions on JedisPool.

Added by djr587 on Tue, 15 Feb 2022 10:41:29 +0200