This is the 18th day of my participation in Gwen Challenge

One, foreword

Knowing the history of NoSQL, let’s start with redis.

Redis is well received in the open source middleware field for its excellent performance, perfect documentation, concise source code and rich client library support.

An in-depth understanding of Redis applications and practices has become an essential skill for mid-to-advanced back-end development.

2. Introduction

2.1 What is it?

Redis stands for Remote Dictionary Server. Redis is likened to a Swiss Army knife by many people because of its rich functions.

Check out the official website:

Redis is an open source (BSD licensed), in-memory storage of data structures used as a database, cache, and message broker. Redis provides data structures such as strings, hashes, lists, collections, sorted collections with range queries, bitmaps, super-logs, geospatial indexes, and streams. Redis has built-in replication, Lua scripting, LRU expulsion, transactions, and different levels of disk persistence, and high availability through Redis Sentinel and Redis Cluster automatic partitioning.Copy the code

Well, after looking at this, we know that it can be either a database or cache and message broker middleware. It is also the key-value store database in NoSQL that we talked about earlier.

2.2 the origin of

In 2008, Salvatore Sanfilippo, the founder of An Italian startup called Merzia, noticed the poor performance of MYSQL and decided to implement a database himself. He developed an initial version of Redis in 2009. Within a few years, Redis had a huge user base.

Antirez, the father of Redis, announced his retirement in June 2020, just ten years or so. It is not too much to say that Redis has accelerated the process of the Internet, and the default port of Redis, 6379, is not randomly selected, determined by the position of the “MERZ” on the keyboard of the phone. Annoyed by an Italian advert girl who said a bunch of stupid things on the show, he used her name as a port number, calling her a byword for stupidity.

2.3 What can Redis do

Redis has the following features:

  • 1, fast speed, high performance: based on memory operation
  • 2. Rich data structures: String, list, Hash, set, sortedSet, etc
  • 3. Multi-language support
  • 4, persistence: support data persistence, you can save the data in the memory in the disk, when the restart can be loaded again for use.
  • 5, high availability and distributed: master slave replication and other technologies

What can Redis do based on these features?

1. Cache system

Cache hot content to reduce database stress.

2. Counter

Record the number of likes, comments and clicks on posts.

3. Message queues

When the requirement of message reliability is not high, message queue can be implemented based on REDis.

4. Leaderboards

The ID of the hot list post is put into the list, divided into the overall list and the classification list.

5. Distributed locks

Common in high concurrency environment, through setnx set lock can be used in distributed environment, can also add lock time.

Of course, there may not be so many requirements in practice, but the purpose of learning a technology is to solve problems, so we need to learn more advanced features of Redis, so that we can do some seemingly difficult tasks when Redis comes in handy.

2.4 redis installation

Juejin. Cn/post / 688628…

Three, five basic types

This part is the most important part of Redis, but also the most basic content to get started redis.

Reids has a lot of commands, so let’s review.

3.1 Reids-key Basic command

127.0.0.1:6379> keys * 1) "age" 2) "name" 127.0.0.1:6379> get name" xulei" 127.0.0.1:6379> expire name 3 (integer) 1 127.0.0.1:6379> TTL name # Remaining time (integer) -2 127.0.0.1:6379> get name (nil) 127.0.0.1:6379> exists name (integer) 0 127.0.0.1:6379 > type age stringCopy the code

3.2 the string

3.2.1 Internal Structure

String is the simplest data structure in Redis, with an array of characters inside. All data structures in Redis obtain corresponding value through unique key, and the data type value is the place to distinguish these five basic types.

String is also our most commonly used data structure. As shown in the figure, our common use is to store user information, serialize JSON into string storage, and deserialize it when we take it out.

The String in Redis is a dynamic String, not a traditional String array, that is, it can be dynamically transformed. Its internal structure is similar to Java’s ArrayList, and a pre-allocated memory will be allocated when it is created initially to reduce the frequent allocation of memory. This string is referred to as SDS (Simple Dynamic stirng).

Its internal definition is as follows:

Struct SDSHDR {// Record the number of bytes used in the buF array // is equal to the length of the string held by the SDS int len; // is equal to the length of the string saved by SDS. // A byte array to hold the string char buf[]; }Copy the code

This figure shows an example of SDS

  • The value of the free attribute is 0, indicating that the SDS has no free space to allocate
  • Len means that SDS holds a five-byte string
  • The buf property is an array of type char, with the last byte holding the null character ‘\0’
3.2.2 Space pre-allocation rule and inert space release strategy

The purpose of these two strategies is to make use of unused space, namely the free property value described earlier.

1. Space pre-allocation:

Space preallocation is used to optimize the string growth operation of SDS. When the SDS API modifies an SDS and expands the SDS, the program dynamically modifies the allocated and unallocated space values. Expansion of java-like ArrayList.

The formula is as follows:

  • 1. If len is less than 1MB, then len is equal to the actual length of the string, and free is equal to len
  • When len is greater than or equal to 1MB, the program allocates a fixed 1MB of unused space.
  • 3. Note that the maximum value of a string is 512MB

2, inert space release:

Lazy space free is used to optimize the string shortening operation of SDS, that is, when the number of strings becomes smaller, the excess space is not immediately reclaimed, but is placed in free. This avoids the memory reallocation required to shorten strings.

Of course, SDS also provides the corresponding API, when the real box release, will also release these excess free, to prevent space occupying memory.

3.2.3 Common Operations

Key/value pair:

127.0.0.1:6379> set key1 v1
OK
127.0.0.1:6379> keys *
1) "key1"
2) "age"
127.0.0.1:6379> APPEND key1 hello
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> strlen key1
(integer) 7
Copy the code

Add and subtract operations, you can set the step size

127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views
(integer) 1
127.0.0.1:6379> incrby views 10
(integer) 11
127.0.0.1:6379> decrby views 2
(integer) 9
Copy the code

String range:

127.0.0.1:6379> set key1 "hello,xulei" OK 127.0.0.1:6379> getrange key1 0 4 "Hello" 127.0.0.1:6379> getrange key1 0 -1 # Get all the strings "Hello,xulei"Copy the code

Replacement:

127.0.0.1:6379> set key2 abcd OK 127.0.0.1:6379> get key2 "abcd" 127.0.0.1:6379> setrange key2 1 xx (integer) 4 127.0.0.1:6379 > get key2 axxd ""Copy the code

Setex and setnx:

#setnx (set if not exist) does not exist set 127.0.0.1:6379> setex key3 20 hualin OK 127.0.0.1:6379> Get key3 "hualin" 127.0.0.1:6379> TTL key3 (integer) 5 127.0.0.1:6379> setnx mykey redis # Successful creation (integer) 1 127.0.0.1:6379> keys * 1) "key1" 2) "mykey" 3) "key2" 127.0.0.1:6379> TTL key3 (integer) -2 127.0.0.1:6379> setnx mykey 1 # Create failure if mykey exists (integer) 0 127.0.0.1:6379> get mykey "redis"Copy the code

Batch get and Set:

# mset # mget # msetnx is an atomic operation that either works together, 127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 OK 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> get k2 "v2" 127.0.0.1:6379> Get k3 "v3" 127.0.0.1:6379> mget k1 k2 k3 1) "v1" 2) "v2" 3) "v3" 127.0.0.1:6379> msetnx k1 v1 k4 V4 (integer) 0 127.0.0.1:6379 > get k4 (nil)Copy the code

Object:

Set user:1 {name:zhangson,age:29} # set user:1 {name:zhangson,age:29} # 127.0.0.1:6379> mset user:2:name xulei user:2:age 26 OK ########## # getSet getSet 127.0.0.1:6379> getSet db redis (nil) 127.0.0.1:6379> get db "redis" 127.0.0.1:6379> getSet db mongodb "redis" 127.0.0.1:6379 > get db "mongo"Copy the code

3.3 the List

Redis list is actually a linkedList structure, which is a bidirectional linkedList, corresponding to linkedList in Java language. This structure has Pointers to the head node of the table, Pointers to the tail node of the table, as well as the length of the list and other information. Therefore, it also has the characteristics of linked list, that is, the query is slow, add and delete fast.

Redis’s list structure is often used for asynchronous queues, with one side reading into the queue and the other side dequeuing.

Common commands:

  • lpush/rpush …. Inserts one or more values from the left/right.
  • Lpop/rPOP spits out a value from the left/right.
  • Rpoplpush pops a value from the right side of the list and inserts it to the left
  • lrange
  • Lrange myList 0-1 0 first on the left, -1 first on the right, (0-1 means get all)
  • Lindex retrieves elements by index subscript (left to right)
  • Llen gets the list length
  • Linsert before inserts the insert value after
  • Lrem deletes n values from left (left to right)
  • Lset replaces the list key subscript index with value

Common applications:

127.0.0.1:6379> Lpush list one (INTEGER) 1 127.0.0.1:6379> Lpush list tow (integer) 2 127.0.0.1:6379> Lpush list three (INTEGER) 3 127.0.0.1:6379> lrange list 0-1 1) "three" 2) "tow" 3) "one" 127.0.0.1:6379> lrange list 0 2 1) "three" 2) "Tow" 3) "one" 127.0.0.1:6379> lrange list 0 1) "three" 2) "tow" 127.0.0.1:6379> lrange list 12 1) "tow" 3) "one" 127.0.0.1:6379> lrange list 0 1) "Tow" 2) "one" 127.0.0.1:6379> Rpush list zero (integer) 4 127.0.0.1:6379> lrange list 0-1 # insert header 1) "three" 2) "tow" 3) "one" 4) "zero" ############# 127.0.0.1:6379> lpop list # remove the header element "zero" 127.0.0.1:6379 > lrange list 0 and 1, 1) "tow" 2) "one" # # # # # # # # # # # # # # # # # # # # by the subscript to obtain a value lindex 127.0.0.1:6379 > lrange list 0 -1 1) "tow" 2) "one" 127.0.0.1:6379> Lindex list 1 "one" 127.0.0.1:6379> Lindex list 0 "tow" 127.0.0.1:6379> Lindex list 1 "one" 127.0.0.1:6379> Lindex list 0 "tow" 127.0.0.1:6379> Lindex list 1  2 (nil) ####################### Llen: Return the length of the list 127.0.0.1:6379> llen list (integer) 3 ##################### # lrem removes the specified value and removes the threshold from the header: Uid 127.0.0.1:6379> lrem list 1 1 (integer) 1 127.0.0.1:6379> lrange list 0-2 1) "2" 2) "2" 3) "1" 4) "2" 5) "2" 6) "3" 127.0.0.1:6379> lrem list 2 2 (integer) 2 127.0.0.1:6379> lrange list 0-2 1) "1" 2) "2" 3) "2" 4) "3" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ltrim intercepted a list of elements, element after only short, 1 0 # # ltrim is to empty the whole list of meaning, 127.0.0.1:6379> lrange list2 0-1 1) "hello5" 2) "hello4" 3) "hello3" 4) "hello2" 5) "hello" 127.0.0.1:6379> Ltrim list2 2 3 OK 127.0.0.1:6379> lrange list2 0-1 1) "hello3" 2) "hello2" 127.0.0.1:6379> ################# rpoplpush 127.0.0.1:6379> rpush myList hello1 (integer) 1 127.0.0.1:6379> rpush myList hello2 (integer) 2 127.0.0.1:6379> rpush myList hello3 (INTEGER) 3 127.0.0.1:6379> rpush myList Hello4 (integer) 4 127.0.0.1:6379> Rpush Mylist hello5 (integer) 5 127.0.0.1:6379> rpoplpush myList othorList "hello5" 127.0.0.1:6379> lrange myList 0-1 1) "Hello1" 2) "hello2" 3) "hello3" 4) "hello4" 127.0.0.1:6379 > lrange othorlist 0 and 1, 1) "hello5" # # # # # # # # # # # # # # # # # # lset 127.0.0.1:6379> lset list 0 item # Check whether the list exists, (error) ERR no such key 127.0.0.1:6379> lpush list Value1 (integer) 1 127.0.0.1:6379> lset List 0 item OK 127.0.0.1:6379> lrange list 0 0 1) "item" #################### # linsert inserts specific values 127.0.0.1:6379> lrange before and after List 0-1 1) "intem3" 2) "intem2" 3) "item" 127.0.0.1:6379> linsert list before "item" nimabi (integer) 4 127.0.0.1:6379> lrange list 0-1 1) "intem3" 2) "intem2" 3) "nimabi" 4) "item" 127.0.0.1:6379> linsert list after item Hahahhahah (integer) 5 127.0.0.1:6379> lrange list 0-1 1) "intem3" 2) "intem2" 3) "nimabi" 4) "item" 5) "hahahhahah"Copy the code

3.4 Set (Set)

Redis’s set is the Java equivalent of HashSet. Its internal key-value pairs are unordered and unique. Its internal implementation is equivalent to a special dictionary in which all values are NULL. When the last element in the collection is removed, the data structure is automatically deleted and memory is reclaimed.

Values in a set are not allowed to be repeated and unordered. Can be used to store the user ID that won a prize in an activity, can be deduplicated to ensure that a user does not win twice.

Common commands:

  • Sadd Key value1 value2: Adds one or more member elements to the set key. Existing member elements are ignored.
  • Smembers key: Fetches all the values of the collection.
  • Sismember key Value: checks whether the set key contains the value. If there is 1, 0 is returned if there is no value
  • Scard key value: Returns the number of elements in the collection
  • Srem key value: Deletes an element in the collection
  • Spop key: Spit a value randomly from this set
  • Srandmember key n: Indicates that n values are randomly fetched from the set and will not be deleted from the set
  • Smove source destination Value: Moves a value ina collection from one collection to another
  • Sinter key1 key2: Returns the intersection element of two collections
  • Sunion key1 key2: Returns the union element of two sets
  • Sdiff key1 key2: Returns the difference set element of two sets (in key1, not in key2)

Command application:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # smembers sadd add elements: the set of all the set # sismember: to determine whether there is the element # scard: Get the current element 127.0.0.1:6379> sadd mySet Hello (INTEGER) 1 127.0.0.1:6379> sadd myset xiaolei (integer) 1 127.0.0.1:6379> sadd Myset xulei love Hualin (INTEGER) 3 127.0.0.1:6379> smembers myset 1) "xulei" 2) "Hello" 3) "love" 4) "xiaolei" 5) "Hualin" 127.0.0.1:6379> sismember myset hello (integer) 1 127.0.0.1:6379> scard myset (integer) 5 ######################################## # srem : Remove set element # SRANDMEMBER: Select a random element 127.0.0.1:6379> srem myset Hello (INTEGER) 1 127.0.0.1:6379> SRANDMEMBER mySet "xulei" 127.0.0.1:6379> SRANDMEMBER myset "hualin" 127.0.0.1:6379 > SRANDMEMBER myset "love" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # spop: 127.0.0.1:6379> spop myset "hualin" 127.0.0.1:6379> SMEMBERS myset 1) "love" 2) "xulei" 3) "xiaolei" 127.0.0.1:6379 > spop myset "love" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # to a specified value, 127.0.0.1:6379> sadd mySet Hello (integer) 1 127.0.0.1:6379> sadd MySet world (integer) 1 127.0.0.1:6379> Sadd myset xulei (INTEGER) 1 127.0.0.1:6379> sadd myset2 hualin (integer) 1 127.0.0.1:6379> sadd myset2 xiangni (INTEGER) 1 127.0.0.1:6379> smove myset myset2 xulei (Integer) 1 127.0.0.1:6379> SMEMBERS myset2 1) "xulei" 2) "xiangni" 3) "hualin" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # application: weibo, b station Put all attention in a set in the collection, put its fans are also in a collection. Number set classes: Difference set: SDIFF intersection: SINTER union: SUNION 127.0.0.1:6379> sadd Key1 a (integer) 1 127.0.0.1:6379> sadd Key1 b (integer) 1 127.0.0.1:6379> sadd key1 c (INTEGER) 1 127.0.0.1:6379> sadd key2 C (integer) 1 127.0.0.1:6379> sadd Key2 D (integer) 1 127.0.0.1:6379> sadd key2 e (INTEGER) 1 127.0.0.1:6379> SDIFF key1 key2 1) "b"Copy the code

3.5 ZSet (Ordered List)

Zset adds a value to set, grouping. set k1 v1 zset k1 score1 v1

It is similar to the combination of SortedSet and HashMap. On the one hand, it is a set to ensure the uniqueness of value; on the other hand, it can assign a score to each value, representing the sorting weight of the value. Its internal implementation uses the data structure of jump list.

Application Scenarios:

  • Zset can be used to store the list of fans. The value is the user Id of the fans, and the score is the events concerned, which can be sorted according to the following time.
  • Zset can also be used to store student scores, with value being the student Id and score being the test score.

Speaking:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # ZRANGEBYSCORE sorting min Max ZREVRANGE: from big to small order # zrange: Sort from small to large 127.0.0.1:6379> zadd myset 1 one (integer) 1 127.0.0.1:6379> zadd myset 2 two 3 three (integer) 2 127.0.0.1:6379> Zrange myset 0-1 1) "one" 2) "two" 3) "three" 127.0.0.1:6379> zadd Salary 2500 xiaohon (integer) 1 127.0.0.1:6379> Zadd Salary 9000 zhansan (INTEGER) 1 127.0.0.1:6379> Zadd Salary 200 xulei (integer) 1 127.0.0.1:6379> ZRANGEBYSCORE Salary - INF +inf 1) "xulei" 2) "xiaohon" 3) "zhansan" 127.0.0.1:6379> ZRANGEBYSCORE - INF + INF withscores 1) "Xulei "2) "200" 3) "xiaohon" 4) "2500" 5) "zhansan" 6) "9000" 127.0.0.1:6379> ZRANGEBYSCORE salary - INF 2500 withscores 1) "xulei" 2) "200" 3) "xiaohon" 4) "2500" 127.0.0.1:6379> ZREVRANGE salary 0-1 1) "zhansan" 2) "xiaohon" # # # # # # # # # # # # # # # # # # # # # # # # # # # rem: remove the elements in the rem: remove the elements in the ordered set # zcard: look at the inside of the element tree # zcount: 127.0.0.1:6379> zrange salary 0-1 1) "xulei" 2) "xiaohon" 3) "zhansan" 127.0.0.1:6379> zrem salary xulei (integer) 1 127.0.0.1:6379> zrange salary 0-1 1) "xiaohon" 2) "zhansan" 127.0.0.1:6379> zcard salary (integer) 2 127.0.0.1:6379> zadd myset 1 Hello (integer) 1 127.0.0.1:6379> zadd myset 2 world 3 Xulei (integer) 2 127.0.0.1:6379> zcount myset 1 3 (integer) 3Copy the code

3.6 Hash (Dictionary)

It is equivalent to the Java language HashMap, which is an array + linked list combination.

The hash structure stores multiple key-values and can be used to retrieve individual keys. Essentially, the hash structure is not very different from the string type.

Hash comparison string:

  • 1, if all storage is more structured data, such as user data cache, especially if a data if the field is more, but every time you just need to use one or a few of them use hash is a good choice, because it provides hget and hmget, without having to remove all the data in the code.

  • 2. If the data is so different that all the data needs to be read out and processed, use string

  • 3. Disadvantages of Hash: Higher storage cost than a single string.

Common commands:

  • Hset Key field Value: Assigns value to the field key in the key set
  • Hget Key field Value: The value of the filed property of the key set
  • Hmset key field1 Value Field2 value: batch set value
  • Hmget key field1 Value Field2 value: Obtain the value in batches
  • Hkeys key: Retrieves all fields
  • Hvals key: Retrieves all values

Basic command practice:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # hset: deposit value # hget: # hmset values: save multiple values # hmget: take multiple values # hgetall: get all the key value # hdel: Deleting the specified key 127.0.0.1:6379> hset myhash field1 xulei (integer) 1 127.0.0.1:6379> hget myhash field1 "xulei" 127.0.0.1:6379> Hset myhash field1 xulei (integer) 1 127.0.0.1:6379> hget myhash field1 "xulei" 127.0.0.1:6379> hmset myhash field2 Field3 OK 127.0.0.1:6379> hmget myhash field1 field2 field3 1) "xulei" 2) "2" 3) "3" 127.0.0.1:6379> hgetall myHash 1) Field3 "6) "3" 3" 127.0.0.1:6379> hdel myhash field2 (integer) 1 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # hlen: check the hash table # hexists: the number of fields to determine whether a specified hash is # hkeys: Check all current keys # hvals: Get all values 127.0.0.1:6379> hlen myHash (integer) 2 127.0.0.1:6379> hgetall myHash 1) "field1" 2) "xulei" 3) "field3" 4) "3" 127.0.0.1:6379> hkeys myhash field1 (integer) 1 127.0.0.1:6379> hkeys myhash 1) "field1" 2) "field3" 127.0.0.1:6379 > hvals myhash 1) xulei "2)" 3 "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # hincryby: specify the incremental # hsetnx: 127.0.0.1:6379> hset MyHash field4 4 (integer) 1 127.0.0.1:6379> hincrby MyHash field4 2 (integer) 6 127.0.0.1:6379> hincrby MyHash Field4-4 (integer) 2 127.0.0.1:6379>Copy the code

Four, summary

This article introduces the functions of Redis and the use of five basic types, we also officially opened the door of NoSQL, the follow-up more advanced Redis guide, will be provided in the later stage, like the likes, the original is not easy, your likes will be the best motivation for my creation.

Reference for this article:

  • Redis Deep Adventure
  • Redis Design and Implementation