directory

Redis single point, REDis master/slave, REDis Sentinel, REDis cluster configuration setup and use
Redis installation and configuration 1.1 Redis single point 1.1.2 Operating Redis in command Window 1.1.3 Operating Redis with Jedis Client 1.1.4 Operating Redis with Spring-Redis 1.1.5 Operating Redis with Lettuce 1.2 Redis Primary/Secondary 1.3 Sentinel 1.3.2 Sentinel Configuration 1.3.3 Start Sentinel, Use Jedis connection sentry to operate Redis 1.3.4 Programming & Running 1.3.5 Simulating primary Node outage 1.4 Redis Cluster 1.4.1 Configuring the Redis Cluster 1.4.2 Starting the Redis cluster 1.4.3 Connect to redis Cluster 1.5 summary using JedisCopy the code

Redis single point, Redis master-slave, Redis Sentinel, REDis cluster configuration and use Redis is one of the most widely used middleware by Internet companies today, we open GitHub search redis, edge can be seen, the introduction of the project is like this:

Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, HyperLogLogs, Bitmaps.

The in-memory database supports in-memory database support. Strings, Lists, sets, Hashes, Hyperloglogs, bitmaps that is high performance, support many data types. This article assumes that you already know the basics of Redis and goes on to discuss redis single point, high availability, clustering.

1. Redis installation and configuration

To install Redis, go to the redis website, redis.io.

  1. Download an installation package of the latest version, such as redis-version.tar.gz
  2. Unpack thetar zxvf redis-version.tar.gz
  3. Execute make (this command may cause error, such as GCC, one by one)

On a MAC, installing Redis is as simple as brew Install Redis.

Once redis is installed, let’s not rush to use it, but do some configuration. To open the redis.conf file, we focus on the following configuration:

Daemonize yes # daemonize yes #Copy the code

Redis 1.1 single point

With Redis installed, let’s run it. The command to start redis is:

redishome/bin/redis-server path/to/redis.config

Assuming we have not configured the background run (i.e., daemonize no), we should see the following startup log:

93825:C 20 Jan 2019 11:43:22.640 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 93825:C 20 Jan 2019 11:43:22.640 # Redis version=5.0.3, bits=64, commit=00000000, Modified =0, PID =93825, 43825 :S 20 Jan 2019 11:43:22.641 * Increased the number of instances when the software was loaded Maximum number of open files to 10032 (it was originally set to 256). _._ _.- '' __ "- (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-... - ` __... -.``-._|'` _.-'| Port: 6380 | `-._ `._ / _.-' | PID: 93825 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _. - '| ` - _ ` - _ ` - __. -' _. - '_. -' | | ` - _ ` - _ _. - '_. -' | ` - _ ` - _ ` - __. - '_. -' _. - '` - _ ` -. __. -' _. - '` -) _ _) -' ` - __. - 'Copy the code

Whether or not the background is configured, after the successful startup, we can open a new command line window to try to operate.

1.1.2 Operating Redis in the Command Window

Use Telnet localhost 6379 to connect to Redis, or you can use the code directly to connect to the test. After connecting, you can see the following information:

Connected to localhost.
Escape character is '^]'.
Copy the code

Let’s try a few commands:

Set Hello world set key-value get Hello Obtain the key value expire hello 10 Set TTL hello Check the expiration time del hello Delete the keyCopy the code

This gives us a taste of Redis, which is pretty simple. Just now we are using the command line to operate Redis, let’s use code to operate Redis, in Java as an example, we use an open source Java-Redis client.

1.1.3 Using jedis client to operate Redis

Open GitHub, search redis, enter the project home page, we can see how to use:

  1. Join jedis dependencies

    Redis. Clients Jedis 3.0.0 jar compile

  2. Write the following code

    Jedis jedis = new Jedis(“localhost”,6379);

    jedis.set(“hello”, “world”);

    String value = jedis.get(“hello”);

    System.out.println(value); // get world

    jedis.del(“hello”);

    System.out.println(jedis.get(“hello”)); // get null

1.1.4 Using spring-Redis operations

The above example of jedis manipulating redis is simple, and you can use Spring-Redis in addition to jedis. Complete the following steps

  1. Configure redis

  2. Write the code

    public class Example {

    // inject the actual template
    @Autowired
    private RedisTemplate<String, String> template;
    
    // inject the template as ListOperations
    // can also inject as Value, Set, ZSet, and HashOperations
    @Resource(name="redisTemplate")
    private ListOperations<String, String> listOps;
    
    public void addLink(String userId, URL url) {
        listOps.leftPush(userId, url.toExternalForm());
        // or use template directly
        redisTemplate.boundListOps(userId).leftPush(url.toExternalForm());
    }
    Copy the code

    }

1.1.5 Using the oracle Operation Redis

Lettuce is a Netty – based non-blocking Redis client. Java8 and responsive support. The official website is author. IO /. Lettuce can also be used with spring. Using oracle you need to add the following Maven dependencies:

< the dependency > < groupId > IO. Lettuce < / groupId > < artifactId > lettuce - core < / artifactId > < version > 5.1.5. RELEASE < / version > </dependency>Copy the code

The basic get,set example code is as follows:

public class LettuceTest {

    public static void main(String[] args) {
        RedisURI uri = new RedisURI();
        uri.setHost("myredishost");
        uri.setPort(6379);
        uri.setDatabase(0);
        RedisClient redisClient = RedisClient.create(uri);
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        RedisCommands<String, String> syncCommands = connection.sync();

        syncCommands.set("testKey", "Hello, Redis!");
        System.out.println(syncCommands.get("testKey"));
        
        connection.close();
        redisClient.shutdown();
    }
}
Copy the code

1.2 redis master-slave

Above we started a Redis and operated on it. Of course, this is just an experiment. Suppose we use a Redis in our production environment. What if Redis fails? If you wait until O&M restarts Redis and recovers the data, it may take a long time. Then during this time, our service is unavailable, which should not be tolerated. If we do master/slave, and the master library dies, the operation and maintenance let the slave library take over, then the service can continue to run, just as the so-called prepared.

Redis master/slave configuration is very simple, and the process is as follows (master/slave configuration on one computer in the ps demo case) :

  1. Copy two Redis profiles (to start two Redis, you only need one redis application, two different Redis profiles)

    mkdir redis-master-slave cp path/to/redis/conf/redis.conf path/to/redis-master-slave master.conf cp path/to/redis/conf/redis.conf path/to/redis-master-slave slave.conf

  2. Modify the configuration

    master.conf

    port 6379

    master.conf

    Port 6380 slaveof 127.0.0.1 6379

  3. Start the two Redis separately

    redis-server path/to/redis-master-slave/master.conf redis-server path/to/redis-master-slave/slave.conf

After startup, open two command-line Windows, execute Telnet localhost 6379 Telnet localhost 6380 and then execute info command in both Windows, as you can see

# Replication
role:master

# Replication
role:slave
master_host:127.0.0.1
master_port:6379
Copy the code

The master/slave configuration is ok.

After the set is executed in the master window, the GET is executed in the slave window. If the get is displayed, the master and slave synchronization is successful.

If we execute a set in the slave window, we will get an error:

-READONLY You can't write against a read only replica.
Copy the code

The slave node is read-only.

1.3 the guard sentinel

Above we introduced master slave, slave library as a “puppet”, can “come in”, “take over” when needed. We configure the master and slave to be “prepared”. After the master Redis is down, we can switch to the slave redis immediately. It may only take a few minutes, but it still needs manual operation. Let’s say the main redis dies at 23pm. Ten minutes later, you get a call and your boss tells you to fix it. You get out of bed and do it. If you shut down and someone else knows the server password, wouldn’t the system be down all night? It’s terrible.

That’s where the Redis Sentinel comes in. Sentinel is used to monitor the health of primary and secondary nodes. When the client connects to the primary and secondary redis, it first connects to Sentinel. Sentinel tells the client what the primary REDis address is. Then the client connects to Redis and performs subsequent operations. When the primary node fails, the client fails to connect to the node and reports an error. The client re-queries sentinel for the address of the primary master. Then the client gets [newly elected primary redis] and can operate happily again.

1.3.2 Sentinel Configuration

To illustrate the usefulness of Sentinel, let’s do an experiment. Configure 3 Redis (1 master, 2 slave) and 1 sentry. The steps are as follows:

mkdir redis-sentinel
cd redis-sentinel
cp redis/path/conf/redis.conf path/to/redis-sentinel/redis01.conf
cp redis/path/conf/redis.conf path/to/redis-sentinel/redis02.conf
cp redis/path/conf/redis.conf path/to/redis-sentinel/redis03.conf
touch sentinel.conf
Copy the code

We created 3 Redis profiles and 1 Sentry profile. We set redis01 to master and redis02 and redis03 to slave.

Conf port 63791 vim redis02.conf port 63792 slaveof 127.0.0.1 63791 vim redis03.conf port 63793 slaveof 127.0.0.1 63791 vim sentinel.conf daemonize yes port 26379 Sentinel monitor myMaster 127.0.0.1 63793 1 #Copy the code

The sentinel/sentinel/sentinel/sentinel/sentinel/sentinel/sentinel/sentinel/sentinel/sentinel/sentinel

127.0.0.1 63793 IP address of the primary node. Port 1 (1) indicates the number of votes cast for the primary node. 1 indicates that a sentinel agrees to upgrade to masterCopy the code

1.3.3 Start sentry, connect Sentry with Jedis to operate Redis

Above we have configured redis master slave, 1 master slave, 2 slave, and 1 sentry. Let’s start Redis and sentry separately

redis-server path/to/redis-sentinel/redis01.conf
redis-server path/to/redis-sentinel/redis02.conf
redis-server path/to/redis-sentinel/redis03.conf

redis-server path/to/redis-sentinel/sentinel.conf --sentinel
Copy the code

After startup, you can connect to each of the three Redis and run info to view primary and secondary information.

1.3.4 Programming & Running

Now use the program to connect the sentry and operate redis.

public static void main(String[] args) throws Exception{ Set<String> hosts = new HashSet<>(); Hosts. The add (127.0.0.1: "26379"); / / hosts. The add (127.0.0.1: "36379"); JedisSentinelPool pool = new JedisSentinelPool("mymaster",hosts); Jedis jedis = null; for(int i=0 ; i<20; i++){ Thread.sleep(2000); try{ jedis = pool.getResource(); String v = randomString(); jedis.set("hello",v); System.out.println(v+"-->"+jedis.get("hello").equals(v)); }catch (Exception e){ System.out.println(" [ exception happened]" + e); }}}Copy the code

The program is very simple, loop 20 times, connect sentry, set random string to redis, get result. Print information and catch exceptions.

1.3.5 Simulate the primary node Breakdown

Run the above program (note that you can experiment with this effect by lengthening the sleep time or increasing the for loop, in case the program stops early and you can’t see the overall effect), and then turn off the main Redis to simulate the redis failure. Now the primary redis is redis01 and the port is 63791

redis-cli -p 63791 shutdown
Copy the code

If sentinel is not set to run in the background, you can see the log of the master switch in the command line window.

# # Sentinel ID is fd0634dc9876ec60da65db5ff1e50ebbeefdf5ce + monitor master mymaster 127.0.0.1 63791 quorum * 1 + slave Slave 127.0.0.1:63792 127.0.0.1 63792 @ myMaster 127.0.0.1 63791 * +slave slave 127.0.0.1:63793 127.0.0.1 63793 @ 127.0.0.1 63791 # +sdown master mymaster 127.0.0.1 63791 # +odown master mymaster 127.0.0.1 63791 #quorum 1/1 # +new-epoch 1 # +try-failover master myMaster 127.0.0.1 63791 # +vote-for-leader Fd0634dc9876ec60da65db5ff1e50ebbeefdf5ce 1 # + elected leader master mymaster 127.0.0.1 63791 # +failover-state-select-slave master mymaster 127.0.0.1 63791 # +selected-slave slave 127.0.0.1:63793 127.0.0.1 6379@ Mymaster 127.0.0.1 63791 * + fail-state-send-slaveof -noone slave 127.0.0.1:63793 127.0.0.1 63793 @mymaster 127.0.0.1 63791 * + fail-state-wait-promotion slave 127.0.0.1:63793 127.0.0.1 63793 @mymaster 127.0.0.1 63791 # + Promoted -slave slave 127.0.0.1:63793 127.0.0.1 63793 @myMaster 127.0.0.1 63791 # + Fail-state-reconf - Slaves Master Mymaster 127.0.0.1 63791 * +slave-reconf-sent slave 127.0.0.1:63792 127.0.0.1 63792 @mymaster 127.0.0.1 63791 * +slave-reconf-inprog slave 127.0.0.1:63792 127.0.0.1 63792@mymaster 127.0.0.1 63791 * +slave-reconf-done slave 127.0.0.1:63792 127.0.0.1 63792 @mymaster 127.0.0.1 63791 # +failover-end master mymaster 127.0.0.1 63791 # +switch-master mymaster 127.0.0.1 63791 127.0.0.1 63793 * +slave slave 127.0.0.1:63792 127.0.0.1 63792 @mymaster 127.0.0.1 63793 * +slave slave 127.0.0.1:63791 127.0.0.1 63791 @mymaster 127.0.0.1 63793 # +sdown slave 127.0.0.1:63791 127.0.0.1 63791 @mymaster 127.0.0.1 63793 # -sdown slave 127.0.0.1:63791 127.0.0.1 63791 @mymaster 127.0.0.1 63793 * +convert-to-slave slave 127.0.0.1:63791 127.0.0.1 63791 @mymaster 127.0.0.1 63793Copy the code

There are a lot of logs above, look carefully, you can see the following lines of the main:

In the initial case, # +monitor master mymaster 127.0.0.1 63791 quorum 1 * +slave slave 127.0.0.1:63792 127.0.0.1 63792 @mymaster 127.0.0.1 63791 * +slave slave 127.0.0.1:63793 127.0.0.1 63793 @myMaster 127.0.0.1 63791 Redis03 # +switch-master mymaster 127.0.0.1 63791 127.0.0.1 63793Copy the code

The log is somewhat obscure, but the code looks like this:

14:45:20. 675. [the main] INFO redis. Clients. Jedis. JedisSentinelPool - Trying to find the master from the available Sentinels... 14:45:25. 731. [the main] the DEBUG redis. Clients. Jedis. JedisSentinelPool - Connecting to Sentinel 192.168.1.106:26379 14:45:25. 770. [the main] the DEBUG redis. Clients. Jedis. JedisSentinelPool - Found redis master at 127.0.0.1:63792 14:45:25. 771 [the main] INFO redis. Clients. Jedis. JedisSentinelPool - redis master running at 127.0.0.1:63792, starting Sentinel listeners... 14:45:25. 871. [the main] INFO redis. Clients. Jedis. JedisSentinelPool - Created JedisPool to master the at 127.0.0.1:63792 ejahaeegig-->true deeeadejjf-->true [ exception happened]redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool [ exception happened]........ [ exception happened]........ [ exception happened]........ [ exception happened]........ [ exception happened]........ [ exception happened]........ [ exception happened]........ [ exception happened]........ [ exception happened]........ 14:46:02. 737 [MasterListener mymaster - [192.168.1.106:26379]] the DEBUG redis. Clients. Jedis. JedisSentinelPool - Sentinel 192.168.1.106:26379 published: Mymaster 127.0.0.1 63792 127.0.0.1 63793.14:46:02.738 [MasterListener- myMaster -[192.168.1.106:26379]] INFO Redis. Clients. Jedis. JedisSentinelPool - Created JedisPool to master the at 127.0.0.1:63793 haiihiihbb - > true ifgebdcicd-->true aajhbjagag-->true Process finished with exit code 0Copy the code

And it turns out that

Start normal operation of Redis and set up twice. JedisConnectionException: Could not get a resource from the pool JedisConnectionException: Could not get a resource from the pool The main redis is selected, the program runs normally, and finally ends. We see that the last run set value is aajHBjagag, we can connect to any of the remaining 2 Redis, get Hello, the result must be the same.

1.4 redis cluster

In the previous chapter, we studied redis single point, Redis master and slave respectively, and added the highly available Sentinel sentinel mode. All we have done is to ensure data backup and high availability, so far our application has been writing data to one Redis, and the other Redis are just backups. In actual scenarios, a single Redis node may not meet the requirements because:

  • A single Redis has limited concurrency
  • A single Redis receives all the data and eventually returns too much memory, which results in a large RDB file. Synchronizing data from a large RDB file is slow.

So all we need is a Redis cluster which is a Redis cluster.

A Redis cluster is an assembly that provides data sharing between nodes of multiple Redis.

Redis clusters do not support commands that handle multiple keys, as this requires moving data between different nodes, which does not achieve Redis performance and can lead to unexpected errors under high loads.

Redis clusters provide a degree of availability through partitioning, continuing to process commands in the real world if a node goes down or becomes unreachable. Advantages of Redis clustering:

  • Automatically split data to different nodes.
  • Can continue processing commands if part of the cluster fails or is unreachable.

In order to configure a Redis cluster, we need at least 6 Redis. Why at least 6 Redis? We can find the following sentence in the official Redis documentation:

Note that the minimal cluster that works as expected requires to contain at least three master nodes. 
Copy the code

Because the smallest redis cluster requires at least 3 master nodes, since there are 3 master nodes, and a master node with at least one slave node, there must be at least 6 Redis. For me, however, it was copying six Redis profiles. The redis cluster construction of this experiment is still simulated on a computer.

1.4.1 Configuring the Redis Cluster

As mentioned above, configuring a REDis cluster requires at least six Redis nodes. Therefore, the following nodes need to be prepared and configured:

Slave: redis01 Slave: redis02 slaveof redis01 Slave: redis03 Slave: redis04 slaveof redis03 slave: Redis05 From redis06 slaveof redis05 mkdir redis-cluster CD redis-cluster mkdir redis01 to redis06 6 folders cp redis.conf to redis06 redis01 ... Redis06 Modify the master/slave relationship for three groups of portsCopy the code

1.4.2 Starting the Redis Cluster

After the above configuration is complete, start each of the six Redis instances. If the configuration is correct, the startup succeeds. Then run the following command to create the cluster:

Redis-5.0.3 / SRC /redis-cli --cluster create 127.0.0.1:6371 127.0.0.1:6372 127.0.0.1:6373 127.0.0.1:6374 127.0.0.1:6375 127.0.0.1:6376-1 - cluster - replicasCopy the code

Note that I used IP :port instead of domain:port because I encountered an error with localhost:6371 or something like this:

ERR Invalid node address specified: localhost:6371
Copy the code

After the command is successfully executed, connect to a Redis and run cluster info to see information similar to the following:

cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:1515
cluster_stats_messages_pong_sent:1506
cluster_stats_messages_sent:3021
cluster_stats_messages_ping_received:1501
cluster_stats_messages_pong_received:1515
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:3021
Copy the code

We can see cluster_state: OK, Cluster_SLOts_OK :16384,cluster_size:3.

1.4.3 Connecting the Redis Cluster using Jedis

Above we have configured a Redis cluster with 6 Redis nodes, 3 master and 3 slave. Let’s use Jedis to connect to the Redis cluster. The code is as follows:

public static void main(String[] args) { Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>(); //Jedis Cluster will attempt to discover ClusterNodes automatically jedisClusterNodes. Add (new HostAndPort("127.0.0.1", 6371)); JedisClusterNodes. Add (new HostAndPort (6372) "127.0.0.1,"); JedisClusterNodes. Add (new HostAndPort (6373) "127.0.0.1,"); JedisClusterNodes. Add (new HostAndPort (6374) "127.0.0.1,"); JedisClusterNodes. Add (new HostAndPort (6375) "127.0.0.1,"); JedisClusterNodes. Add (new HostAndPort (6376) "127.0.0.1,"); JedisCluster jc = new JedisCluster(jedisClusterNodes); jc.set("foo", "bar"); String value = jc.get("foo"); System.out.println(" ===> " + value); }Copy the code

Above we set the message set foo bar, but do not know which redis is set to. Please consider that we are in cluster mode, so the data is scattered into different slots. Redis cluster has 16384 hash slots, and each key is verified by CRC16 and the module of 16384 is taken to decide which slot to place. Each node in the cluster is responsible for a portion of the hash slot. For example, if the current cluster has three nodes, then:

  • Node A contains hash slots 0 to 5500.
  • Node B contains hash slots 5501 through 11000.
  • Node C contains hash slots 11001 through 16384.

You still don’t know which redis set Foo bar is on. Try connecting to any Redis and find out.

conclusion

So far, we understand and practice the installation of Redis, Redis single point, Redis master-slave, Redis Sentinel, Redis cluster. Let’s sort out the differences and relationships between redis master and slave, Redis sentry and RedIS machine.

Redis master-slave: This is a backup relationship. When we operate the master database, data is synchronized to the slave database. If the main library machine is down, the secondary library can be accessed. It’s like when you lose your drive D, but you have a backup on your portable hard drive. Redis Sentry: The Sentry guarantees HA and automatic failover in special cases. The Sentry keeps an eye on your “Redis master/slave cluster” and tells you who the new boss is if the master library dies. Redis clustering: Clustering guarantees high concurrency, because there are more brothers to help with it. At the same time, clustering will lead to data dispersion. The whole Redis cluster will be divided into a pile of data slots, that is, different keys will be placed in different slots.

Master/slave guarantees data backup, sentry guarantees HA (failover), and cluster guarantees high concurrency.

All hands to do will be familiar.