Redis gets started quickly and applied, just read this article

1 Introduction

Redis is an open source, memory-based, persistent, high-performance, key-value based Nosql database, used as a database, cache, message broker, and streaming media engine.

Application scenario: As a kv database, its storage value is not as good as that of its counterpart MongoDB. As a message queue, it is not as good as Kafka. Its job is still as a cache, and its "caching" nature is far greater than its "data storage" nature.

Default port: 6379

2. Data type

Redis is based on kv storage, its key type can only be String type, including empty string is also a qualified key, and Value value type can be various.

Key value selection principle: the key value does not need to be too long, too long will consume memory, and the calculation cost of finding such a key value in the data is high; the key value should not be too short, otherwise the readability will be poor.

The latest officially announced supported value types are as follows. In addition to the five basic data types we are familiar with, there are also a bunch of unfamiliar data types. If you are interested, you can learn about them through the official website. In this article, we will focus on five commonly used data structures, String , List , Hash , Set and Zset (ie Sorted sets). For the specific description of each data structure, see the " CRUD operation " module.
insert image description here

3. Cluster Architecture

There are three ways to build a Redis cluster, which feels similar to MongoDB.

1. Master-slave mode (master/slave)
A master can have multiple slaves, and the slaves synchronize the data of the master node. By default, the master node can read and write, and the slave node can only read and write operations are prohibited.

Disadvantage: After the master node hangs up, redis cannot provide external writing services, because the remaining slaves cannot become masters.

2. Sentinel sentinel mode
The Chinese meaning of sentinel is sentinel and guard, and it is an independent process. That is to say, since in the master-slave mode, when the master node hangs up, the slave node cannot actively elect a master node, then I will arrange one or more sentinels to do this. When the sentinel finds that the master node is hung up, Sentinel will re-elect a master from the slave.

The sentinel mode can basically meet the needs of general production and has high availability. However, when the amount of data is too large to be stored in one server, the master-slave mode or sentinel mode cannot meet the demand. At this time, the stored data needs to be fragmented and stored in multiple Redis instances.

3. Cluster mode (fragmentation + copy mode)
The emergence of cluster mode is to solve the problem of limited capacity of single-machine Redis, and distribute Redis data to multiple machines according to certain rules to implement redis distributed storage, that is to say, each Different content is stored on the redis node.

Each node (master) can introduce multiple slaves to ensure the high availability of the cluster, so if two replicas and three fragments are configured, six Redis instances are required.
Because Redis data is allocated to different machines in the cluster according to certain rules, when the amount of data increases, it is very convenient to add new machines for expansion.
This mode is suitable for caching requirements with a huge amount of data. When the amount of data is not very large, use Sentinel.

Redis-Cluster adopts a non-central structure. The client is directly connected to the redis node without an intermediate proxy layer. The client does not need to connect to all nodes in the cluster, but can connect to any available node in the cluster.

The Redis cluster has the following important features:
(1). The sharding feature of the Redis cluster is that the space is split into 16384 slots, a certain node is responsible for some of the slots, and the remainder of the key pair 16384 is allocated to different slots. solt.
(2) The Redis cluster provides a certain degree of availability, and can continue to process commands when a certain node is down (there is no slave under it, or all slaves are down) or it is unreachable.
(3) There is no central node or proxy node in the Redis cluster. One of the most important design goals of the cluster is to achieve linear scalability.

4. Redis client shell command

4.1. Script commands

First introduce two script commands: redis-server and redis-cli

1. The redis-server command is used to start the redis service

#启动redis
redis-server redis.conf
#查看版本
redis-server -v

2. The redis-cli command is used to connect to the redis server and enter the command line mode

#连接 (-p指定端口,-a指定密码,-c 集群模式)
redis-cli -h 172.28.226.5 -p 6379 -a $password -c

#注意:在Redis6.0之前的版本中,如上面指定的是默认用户default的密码,redis以前的版本也只支持单用户访问,也就是没有用户名这个概念。

4.2. Basic command line commands

Redis provides a very rich command, the following only introduces the commonly used commands, other commands you can check https://redis.io/commands/, search for more detailed usage of each command. In addition, you can also view the usage of the command through "help command".
insert image description here

1. Operation and maintenance commands

#测试连接是否可用,返回pang则表示连接可用
redis> PING
"PONG"

#查看redis统计信息
redis> info

#列出所有连接
redis> client list

#杀死某个连接
redis> client kill 127.0.0.1:43501

2. Basic operation commands

dbsize        #显示数据库中所有key的数量
keys *        #显示所有的key
exists mykey  #判断该键是否存在,存在返回1,不存在返回0
flushdb       #清空数据库
del mykey     #删除该键值
type key      #查看key的值类型
help command  #帮助命令,查看命令的用法,如help get

4.3. CRUD operations

  1. Sting

    String type, the simplest and most commonly used value type. On the command line, both key and value can be without quotes.

    #设值,取值,删值基本操作,name就是我们设置的key值,注意以下所有命令command后紧跟的字符串都是key值。
    set name shengr
    get name
    del name
    
    #对已经存在的key设置过期时间,单位秒
    expire name 60
    
  2. List

    The list type is analogous to the array in java, ArrayList.

    The elements in the list are of string type, and the order of the elements is the same as the order of insertion. The addition and deletion speed of the head and tail of the list is fast, and the addition and deletion speed of the middle is slow. Adding and deleting elements is normal during normal use, and elements in the list can appear repeatedly; the index of the list, from left to right, starts from 0; from right to left, from -1 start.

    # lpush 元素依次压入列表头部,一次可以压入一个或多个元素
    lpush words a b c d  	
    # rpush 元素依次插入到列表末位
    rpush words e f g
    # lrange 获取下标从start到end的元素,下标从0开始并且包含end处的值。另外,下标可以是负数,表示倒数第几个值,-1即表示最后一位。
    lrange words 0 -1 
    # lpop 从列表首位移除一个值
    lpop words 
    # rpop 从列表末尾移除一个值
    rpop words 
    
    # 获取List长度
    llen words
    # 通过下标获取值
    lindex words 1
    # 通过下标设置
    lset words 0 a
    
  3. Hash

    The hash type is analogous to the HashMap in java, so a key corresponds to a map type value (a set of kv pairs).

    Hash is a map key-value pair composed of field and associated value, and field and value are both string types.

    # hset 依次设置map中键值对,一次可以设置一个或多个
    hset user name shengr age 12 city sz
    # hget 获取map中某个field上的值
    hget user name
    # hgetAll 获取map中的所有field值
    hgetall user
    #hdel 删除map中的一个或多个指定fileld,不存在的字段忽略
    hdel user age city
    
    # hexists 判断字段是否存在,存在返回1,不存在返回0
    hexists user age
    # hkeys 获取map上的所有field:
    hkeys user
    # hvals 获取map上的所有value:
    hvals user
    # hlen 获取map中field个数:
    hlen user
    
  4. Set

    The collection type is similar to the HashSet in java, with unique members and unordered elements, and the elements are of string type.

    # sadd 往集合中加入元素,重复的元素无法插入
    sadd chars a b b c 
    # smembers 取出所有元素
    smembers chars 
    # srem 从集合中删除元素
    srem chars a 
    # scard 获取集合中元素个数
    scard chars
    
  5. Set

    An ordered collection type, analogous to the TreeSet in java, with unique and ordered members, and the elements are of string type, each element is associated with a floating-point score Score, and the collection is arranged in ascending order of the score elements (scores can be the same or negative).

    # zadd 往集合中加入带分值的元素
    zadd letters 1 a 3.1 b 4 c
    # zrange 根据下标获取集合中的元素,正序
    zrange letters 0 -1
    # zrem 从集合中删除元素
    zrem letters a
    # zcard 返回元素个数
    zcard letters
    # zscore 返回某个元素的分值
    zscore letters b
    # zincrby 给某个元素的分值加上一个值,减去一个值使用负数即可
    zincrby letters 2 b
    

5. JAVA client of Redis

5.1. Three common Java clients

Jedis

The old-fashioned redis client is easy to use and provides comprehensive support for Redis commands, which is what we will focus on below. The methods in Jedis call the underlying Redis API, that is, the Java methods in Jedis are basically consistent with the Redis API. If you understand the Redis API, you can use Jedis more skillfully. Official address: https://github.com/redis/jedis

Note: jedis uses blocking I/O, and its method calls are synchronous, not asynchronous. Jedis client instances are not thread-safe, so Jedis needs to be used through a connection pool.

Lettuce

English literal translation is "lettuce", an advanced Java Redis client for thread-safe synchronous, asynchronous and reactive use. Support for clusters, sentinels, pipelining and codecs. Official website address: https://lettuce.io/

Redisson

On the basis of Redis, the Java in-memory data grid function (In-Memory Data Grid) is implemented. It is an advanced distributed coordination Redis client that provides a series of distributed Java objects. Jedis and Lettuce clients focus more on CRUD (addition, deletion, modification, query) operations on the Reids database, while Redisson API focuses on distributed development. Official website address: https://redisson.org/
insert image description here

5.2. Jedis client detailed explanation

Introduction to Jedis client access mode :

The Jedis client supports stand-alone mode, sharding mode, and cluster mode access modes at the same time. Data access in stand-alone mode is realized by building Jedis class objects , and data access in sharding mode is realized by building ShardedJedis class objects . It is realized by building JedisCluster class objects. Data access in cluster mode. Among them, ShardedJedis is a data distribution scheme implemented by the client before Redis had no cluster function. Now we can use JedisCluster instead.

5.2.1. Stand-alone mode data access

1. Create a Jedis connection object

Construct the Jedis class object through ip and port. If redis is configured with a password, you need to use the auth method for authentication.

Jedis jedis = new Jedis("172.28.226.5",6379);
jedis.auth("$pwd");

2.String type

//1,设置k-v值
jedis.set("name","shengr");
//2,获取k对应v值
String username=jedis.get("name");
System.out.println(username);
//3,设置值的同时指定过期时间,方法为setex,第二参数指定过期时间,单位秒
jedis.setex("flag",30,"1");
//4,删除key
jedis.del("flag");
//5,关闭连接
jedis.close();

3. List type

//lpush 元素依次插入到列表首位
jedis.lpush("words","a","b");
//rpush 元素依次插入到列表末位
jedis.rpush("words","c","d","e");
//lrange 获取下标从start到end的元素,下标从0开始并且包含end处的值。另外,下标可以是负数,表示倒数第几个值,-1即表示最后一位。
List<String> words = jedis.lrange("words", 0, -1);
System.out.println(words);
//lpop 从列表首位弹出一个值
String word1 = jedis.lpop("words");
//rpop 从列表末位弹出一个值
String word2 = jedis.rpop("words");
System.out.println(word1+"--"+word2);

4. Hash type

A key corresponds to a set of field-value values

//设值
jedis.hset("user","name","shengr");
jedis.hset("user","age","12");
jedis.hset("user","city","sz");
//获取单个值
String name=jedis.hget("user","name");
System.out.println(name);
//遍历所有值
Map<String,String> user = jedis.hgetAll("user");
for (String key : user.keySet()) {
    
    
String value = user.get(key);
System.out.println(key+":"+value);
}
//删除key中的一个或多个指定fileld,不存在的字段忽略
jedis.hdel("user","city","sex");

5. Set type

The elements in the collection are unique, adding duplicate elements is invalid

//设值
jedis.sadd("distinctWords","a","b","a");
//获取所有值
Set<String> distinctWords = jedis.smembers("distinctWords");
System.out.println(distinctWords);

6. Zset type

Ordered Set type, the ranking score is specified by score, and the elements are sorted according to this score from small to large

jedis.zadd("sortedset",3,"ding");
jedis.zadd("sortedset",5,"seng");
jedis.zadd("sortedset",4,"ming");
Set<String> sortedset = jedis.zrange("sortedset", 0, -1);
System.out.println(sortedset);

The complete running code is as follows:

public class JedisTest {
     
     
   private static Jedis jedis;
   //通过静态代码块进行初始化值
   static {
     
     
       jedis = new Jedis("172.28.226.5",6379);
       jedis.auth("$pwd");
   }

   //1,String类型
   public static void op01(){
     
     
       //1,设置k-v值
       jedis.set("name","shengr");
       //2,获取k对应v值
       String username=jedis.get("name");
       System.out.println(username);
       //3,设置值的同时指定过期时间,方法为setex,第二参数指定过期时间,单位秒
       jedis.setex("flag",30,"1");
       //4,删除key
       jedis.del("flag");
       //5,关闭连接
       jedis.close();
   }
   //2,List类型
   public static void op02(){
     
     
       //lpush 元素依次插入到列表首位
       jedis.lpush("words","a","b");
       //rpush 元素依次插入到列表末位
       jedis.rpush("words","c","d","e");
       //lrange 获取下标从start到end的元素,下标从0开始并且包含end处的值。另外,下标可以是负数,表示倒数第几个值,-1即表示最后一位。
       List<String> words = jedis.lrange("words", 0, -1);
       System.out.println(words);
       //lpop 从列表首位弹出一个值
       String word1 = jedis.lpop("words");
       //rpop 从列表末位弹出一个值
       String word2 = jedis.rpop("words");
       System.out.println(word1+"--"+word2);
   }

   //3,Hash类型,同一个key对应一组k-v值
   public static void op03(){
     
     
       //设值
       jedis.hset("user","name","shengr");
       jedis.hset("user","age","12");
       jedis.hset("user","city","sz");
       //获取单个值
       String name=jedis.hget("user","name");
       System.out.println(name);
       //遍历所有值
       Map<String,String> user = jedis.hgetAll("user");
       for (String key : user.keySet()) {
     
     
           String value = user.get(key);
           System.out.println(key+":"+value);
       }
       //删除key中的一个或多个指定fileld,不存在的字段忽略
       jedis.hdel("user","city","sex");
   }

   //4-1,Set类型:集合中元素唯一
   public static void op04(){
     
     
       jedis.sadd("distinctWords","a","b","a");
       Set<String> distinctWords = jedis.smembers("distinctWords");
       System.out.println(distinctWords);

   }
   //4-2,有序Set类型: score指定排名分值,元素按照此分值从小到大排序
   public static void op05(){
     
     
       jedis.zadd("sortedset",3,"ding");
       jedis.zadd("sortedset",5,"seng");
       jedis.zadd("sortedset",4,"ming");
       Set<String> sortedset = jedis.zrange("sortedset", 0, -1);
       System.out.println(sortedset);
   }

   public static void main(String[] args) {
     
     
       op01();
       op02();
       op03();
       op04();
       op05();
   }
}

5.2.2. Cluster mode data access

For cluster mode access, what we need to build is the JedisCluster object, not the Jedis object. Although the object has been changed, the method of accessing the above data types is exactly the same as that of the Jedis object. We only need to focus on how to create a JedisCluster connection object here.

1. Jedis connection pool

The connection pool of jedis is called JedisPool. After the connection pool is created, we can obtain connections from the connection pool. The client uses the TCP protocol to connect to Redis. The direct connection method needs to establish a TCP connection every time, and the connection pool method can be pre-installed. The Jedis connection is initialized, so you only need to borrow from the Jedis connection pool each time, and the borrowing and returning operations are performed locally, with only a small amount of concurrent synchronization overhead, which is far less than the overhead of creating a new TCP connection.

Connection pool configuration properties (set properties through the JedisPoolConfig object):

  • maxTotal

    Connection pool capacity, that is, the maximum number of connections available.

  • maxIdle

    The maximum number of idle connections, the default value is 8.

  • maxWaitMillis

    The maximum time to wait for an available connection, in milliseconds, the default value is -1, which means never timeout.

  • testOnReturn

    Boolean value, when this property is true, before calling the borrowObject method to obtain a connection from the connection pool, the validateObject method will be called for validation. If the verification fails, the connection will be removed from the connection pool and destroyed. At the same time, it will try to borrow a new connection object.

  • testOnBorrow

    Boolean value, when this property is true, when the returnObject method is called to return the connection to the connection pool, the validateObject method will be called to verify the current connection, and if the verification fails, the connection will be destroyed.

2. Create a JedisCluster connection object

insert image description here

Created by the construction method, the standard construction method parameters containing all parameters are as follows:

  • HostAndPort

    HostAndPort represents the ip and port information of a single node in the cluster, and multiple nodes in the cluster can be placed in the Set collection.

  • connectionTimeout

    Connection timeout, in milliseconds

  • soTimeout

    Timeout for reading and writing data, in milliseconds

  • maxAttempts

    Maximum number of reconnections

  • password

    password

  • jectPoolConfig

    JedisPoolConfig object that encapsulates connection pool properties

    The complete running code is as follows:

    public class JedisClusterTest {
           
           
       public static JedisCluster getJedisCluster() {
           
           
    
           //1设置集群节点的ip和端口信息,集群有多个节点需要添加多个
           Set<HostAndPort> hostAndPorts = new HashSet<HostAndPort>();
           HostAndPort hostAndPort = new HostAndPort("172.28.226.5",6379);
           hostAndPorts.add(hostAndPort);
           //2设置密码
           String password = "$pwd";
           //3连接超时时间
           int connectTimeout = 5000;
           //4读写超时时间
           int soTimeout = 5000;
           //5最大重连次数
           int maxAttempts = 3;
           //6连接池参数
           JedisPoolConfig jedisPoolConfig = getJedisPoolConfig();
    
           JedisCluster jedisCluster = new JedisCluster(hostAndPorts, connectTimeout, soTimeout, maxAttempts, password, jedisPoolConfig);
           //注意:JedisCluster最好设置成单例,且一般不需要执行close操作,而是由连接池管理。
           return jedisCluster;
       }
       private static JedisPoolConfig getJedisPoolConfig() {
           
           
           //1,pool容量,即最大连接数
           int maxTotal = 1024;
           //2,pool最大空闲连接数,默认值是8
           int maxIdle = 200;
           //3,等待可用连接的最大时间,单位是毫秒,默认值为-1,表示永不超时。
           int maxWaitMillis = 10000;
           //4,在返回一个连接对象时,是否进行有效性检查
           boolean testOnReturn = true;
           //5,借用一个连接对象时,是否进行有效性检查
           boolean testOnBorrow = true;
    
           JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
           jedisPoolConfig.setMaxTotal(maxTotal);
           jedisPoolConfig.setMaxIdle(maxIdle);
           jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
           jedisPoolConfig.setTestOnReturn(testOnReturn);
           jedisPoolConfig.setTestOnBorrow(testOnBorrow);
    
           return jedisPoolConfig;
       }
       public static void main(String[] args) {
           
           
           JedisCluster jc=getJedisCluster();
           jc.set("myname","shengr");
           System.out.println(jc.get("myname"));
       }
    }
    

5.2.3. Redis common exceptions

Exception in thread "main" redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 14315 172.24.226.7:6379
	at redis.clients.jedis.Protocol.processError(Protocol.java:115)
	at redis.clients.jedis.Protocol.process(Protocol.java:161)
	at redis.clients.jedis.Protocol.read(Protocol.java:215)
	at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340)
	at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:239)
	at redis.clients.jedis.Jedis.set(Jedis.java:121)
	at redisClient.JedisTest.op01(JedisTest.java:24)
	at redisClient.JedisTest.main(JedisTest.java:52)

Cause of the problem : MOVED indicates that it is currently in Redis cluster mode. You are using Jedis class object access in cluster mode, and the data access method in Jedis class object stand-alone mode.

Solution : Just change the connection object from Jedis to JedisCluster.

insert image description here

Guess you like

Origin blog.csdn.net/qq_36756227/article/details/129764672