The introduction of Redis

Redis is an open source (BSD-licensed), in-memory data structure storage system that can be used as database, cache, and messaging middleware MQ. It supports many types of data structures, such as strings, hashes, lists, sets, sorted sets, range queries, bitmaps, Hyperloglogs and Geospatial index radius query. Redis is built with replocation, LUA scripting, LRU eviction, transactions, and different levels of disk persistence, And high availability through Redis Sentinel and Automated Cluster

Redis common type

  • string String
  • hash HashMap
  • list LinkedList
  • set HashSet
  • sorted_set TreeSet

Redis data storage format

  • Redis itself is a Map where all data is stored in the form of ==key:value==
  • == Data type == refers to the type of data stored, that is, the type of the value part, and the key part is always a string

string

  • Stored data: Single data, the simplest data storage type, is also the most common data storage type
  • Format for storing data: One storage space holds one data
  • Store content: Usually a string, which can be used as a numeric operation if it is presented as an integer

Basic operations on string data

  • Add/modify data

    set key value

  • To get the data

    get key

  • Delete the data

    del key

127.0.0.1:6379 >setName maomao OK 127.0.0.1:6379> get name"maomao"127.0.0.1:6379 > del name (integer) 1
127.0.0.1:6379> get name
(nil)

Copy the code
  • Add/modify multiple data

    mset key1 value1 key2 value2 …

  • Get multiple data

    mget key1 key2 …

  • Get the length of the data string (number of strings)

    strlan key

  • Append information to original information (append if original information exists, otherwise == new ==)

    append key value

127.0.0.1:6379> mset k1 a k2 b k3 c
OK
127.0.0.1:6379> mget k1 k2 k3
1) "a"
2) "b"
3) "c"127.0.0.1:6379 >setName maomao OK 127.0.0.1:6379> strlen name (integer) 6
127.0.0.1:6379> append hello world
(integer) 5
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> append name zhu
(integer) 9
127.0.0.1:6379> get name
"maomaozhu"
Copy the code

Extended operations on string data

Data addition and subtraction operations

The business scenario

  • In large-scale enterprise applications, == is a basic operation. Multiple tables are used to store data of the same type, but the corresponding primary key IDS must be consistent and cannot be repeated. The Oracle database has sequence Settings to solve this problem, but the MySQL database does not have a similar mechanism. How can I solve this problem?

The solution

  • Sets numeric data to increment a specified range of values

    incr key

      incrby key increment
      incrbyfloat key increment
    Copy the code
  • Sets numeric data to reduce a specified range of values

    decr key

      decrby key increment
    Copy the code

Redis is inherently single-threaded, so you can solve the distributed ID problem in this way

127.0.0.1:6379 >setNum 0 OK 127.0.0.1:6379> incr numOn the # 1
(integer) 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> get num
"2"127.0.0.1:6379 > decr num# 1
(integer1 127.0.0.1:6379> decr num (integer) 0
127.0.0.1:6379> decr num
(integer) -1
127.0.0.1:6379> get num
"1"127.0.0.1:6379 > incrby num is 10You can set the step size to specify the increment
(integer9 127.0.0.1:6379> incrby num 10 (integer) 19
127.0.0.1:6379> decrby num 9
(integer) 10
127.0.0.1:6379> incrbyfloat num 2.5		# the decimal
"12.5"127.0.0.1:6379 > incrby num is 3.5# incrby can only be an int
(error) ERR value is not an integer or out of range
Copy the code

String as a numeric operation

  • String is stored in Redis. Default == is a string. When incR is added or subtracted, decR will be converted to numeric type for calculation.
  • Redis all operations are == atomic ==, using a single thread to handle all business, commands are executed one by one, so there is no need to worry about concurrency

Data impact.

  • Note: an error will be reported if the original data cannot be converted to a value == or if the redis value == upper limit == is exceeded.

9223372036854775807 (maximum long data in Java, long.max_value)

Redis is used to control the id== of the primary key of the database table and provide a generation policy for the primary key of the database table to ensure the uniqueness of the == primary key of the database table. Applies to all databases and supports database clusters

Data timeliness Settings

The business scenario

  • Casting vote can only be done through wechat, each wechat can only cast 1 vote every 4 hours.
  • E-commerce merchants open the recommendation of popular commodities, and the popular commodities cannot remain in the popular period all the time. The popular period of each commodity lasts for 3 days, and the popular period will be automatically cancelled after 3 days.
  • Hot news will appear on news websites. The biggest characteristic of hot news is timeliness. How to automatically control the timeliness of hot news?

The solution

  • Sets the data to have a specified life cycle

    setex key seconds value

      psetex key milliseconds value
    Copy the code
  • Set up separate data

    setnx key value

127.0.0.1:6379 > setex tel 10'123456789'	# Set a key value to num 10 seconds after expirationOK 127.0.0.1:6379 > TTL tel# Lifecycle
(integer) 6
127.0.0.1:6379> get tel
"123456789"TTL tel (127.0.0.1:6379 >integer) 1
127.0.0.1:6379> get tel
(nil)
127.0.0.1:6379> setnx subject 'redis'	If the key does not exist, create the corresponding key
(integer) 1
127.0.0.1:6379> setnx subject 'mongodb'	# create failed if key exists
(integer) 0
127.0.0.1:6379> get subject
"redis"127.0.0.1:6379 > psetex zhu, 5000'zhuzhu'	# milliseconds
OK
127.0.0.1:6379> ttl zhu
(integer) 1
127.0.0.1:6379> get zhu
(nil)

127.0.0.1:6379> setK1 v1 OK 127.0.0.1:6379> get k1"v1"
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> msetnx k1 v1 k4 v4	# msetnx is an atomic operation that either succeeds or fails together
(integer) 0
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> get k1
"v1"
Copy the code

Redis == Controls the life cycle of data ==, and controls business behaviors by whether data fails, which is applicable to all operations with time-limited control

Some other operations on string data

  • Gets the range of strings

    getrange key start end

  • Replaces the string in the specified range

    setrange key offset value

127.0.0.1:6379 >set name 'hello,maomao'OK 127.0.0.1:6379 > get the name"hello,maomao"
127.0.0.1:6379> getrange name 0 3
"hell"127.0.0.1:6379> getrange name 0-1"hello,maomao"
127.0.0.1:6379> setrange name 2 mmm
(integer) 12
127.0.0.1:6379> get name
"hemmm,maomao"
127.0.0.1:6379> setrange name 0 ilove
(integer) 12 127.0.0.1:6379> Getrange name 0-1"ilove,maomao"
Copy the code
  • First get the set again

    getset key value

127.0.0.1:6379 > getset db redis# Return nil if no value exists(nil) 127.0.0.1:6379 > get db"redis"127.0.0.1:6379 > getset db mongoIf there is a value, get the original value and set the new value
"redis"127.0.0.1:6379 > get db"mongoDB"
Copy the code
  • Store an object
set user:1 {name:maomao,age:18}	# Set a user:1 object value to json character to save an object!The key here is a clever design: user:{id}:{filed} , 127.0.0.1:6379> mset user:1:name maomao user:1:age 18 user:1:gender nV OK 127.0.0.1:6379> mget user:1:name user:1:age user:1:gender 1)"maomao"
2) "18"
3) "nv"
Copy the code

Precautions for string data operations

  • The difference between feedback of unsuccessful data operations and normal data operations
    1. Indicates whether the running result is successful. (Integer) 0 → false Indicates that the running result is failed. (Integer) 1 → true Indicates that the running result is successful
    2. Indicates the running result value (INTEGER) 3 → 3 3 (INTEGER) 1 → 1 1
  • Data not obtained

(nil) equals null

  • Maximum data storage capacity

512MB

  • Maximum range of numerical computation (maximum of longs in Java)

9223372036854775807

Application scenario of string

Control the display of high-frequency access information on the homepage, such as the up master of STATION B, the homepage displays the number of fans, the number of likes and the number of plays

  • Set user information for big V user in Redis, with user primary key and attribute value as key, and set periodic refresh strategy in the background
    • User: id: 110: fans – 2389000
    • User: id: 110: he likes – 9476000
    • User: id: 110: views – 480000000
  • Store up main information in Redis in JSON format and refresh periodically (hash is also possible)

Eg: user: id:110 → {“id”:110,”name”:” fans”:2389000,”likes”:9476000, “views”:480000000}

127.0.0.1:6379> mset user:id:110:likes 9476000 user:id:110:views 480000000OK 127.0.0.1:6379> mget user:id:110:fans user:id:110:likes user:id:110:views 1)"2389000"
2) "9476000"
3) "480000000"127.0.0.1:6379 > incr user: id: 110: fans (integer) 2389001
127.0.0.1:6379> incr user:id:110:views
(integerIncr user:id: 100 :views (integer) 480000002
127.0.0.1:6379> mget user:id:110:fans user:id:110:likes user:id:110:views
1) "2389001"
2) "9476000"
3) "480000002"127.0.0.1:6379 >setUser: id: 120 {id: 120, name: wanglaoju, fans, 2389000, "likes" : 9476000, views: 480000000} OK 127.0.0.1:6379 > get user: id: 120"{id:120,name:wanglaoju,fans:2389000,likes:9476000,views:480000000}"

Copy the code

Key setting conventions

  • Hot data key naming convention in the database

Table name: Primary key name: Primary key Value: Field name ORDER: ID: 294375951: Name EQUIP: ID: 390472345: Type news: ID: 202004150: title

hash

  • New storage requirements: Groups a series of storage data for easy management. Typical applications store object information
  • Required storage structure: One storage space holds multiple key-value pairs of data
  • Hash type: The underlying data store uses the == hash table structure ==

Reference to hash tablesBig man’s article

Hash storage structure optimization

  • If the number of fields is small, the storage structure is optimized to an array-like structure
  • If the number of fields is large, the storage structure uses the HashMap structure

Basic operations on hash data

  • Add/modify data

    hset key field value

  • To get the data

    hget key field

hgetall key

  • Delete the data

    hdel key field1 [field2]

127.0.0.1:6379> hset user name xiaotian
(integer) 1
127.0.0.1:6379> hset user age 20
(integer) 1 127.0.0.1:6379> hset user gender naninteger) 1
127.0.0.1:6379> hgetall user
1) "name"
2) "xiaotian"
3) "age"
4) "20"
5) "gender"
6) "nan"127.0.0.1:6379 > hget user name"xiaotian"127.0.0.1:6379 > hget user gender"nan"

127.0.0.1:6379> hdel user gender
(integer) 1
127.0.0.1:6379> hgetall user
1) "name"
2) "xiaotian"
3) "age"
4) "20"
Copy the code
  • Add/modify multiple data

Hmset key field1 value1 field2 value2…

  • Get multiple data

Hmget key field1 field2…

  • Gets the number of fields in the hash table

hlen key

  • Gets whether the specified field exists in the hash table

hexists key field

127.0.0.1:6379> hmget user name age
1) "xiaotian"
2) "20"

127.0.0.1:6379> hmset user name feifei age 22 weight 46
OK
127.0.0.1:6379> hgetall user
1) "name"
2) "feifei"
3) "age"
4) "22"
5) "weight"
6) "46"127.0.0.1:6379 > hlen user# fetch the number of fields
(integer) 3

127.0.0.1:6379> hexists user age	Check whether the specified field exists
(integer) 1
127.0.0.1:6379> hexists user height
(integer) 0
Copy the code

Hash data extension operation

  • Gets the names or values of all fields in a hash table

hkeys key

hvals key

  • Sets the numeric data of the specified field to increase the value of the specified range

hincrby key field increment

hincrbyfloat key field increment

127.0.0.1:6379 > hkeys user# all field names
1) "name"
2) "age"
3) "weight"127.0.0.1:6379 > hvals userAll field values
1) "feifei"
2) "22"
3) "46"

127.0.0.1:6379> hincrby user age 1
(integer) 23
127.0.0.1:6379> hincrby user weight 10	# specify increment
(integer) 56
127.0.0.1:6379> hincrby user weight -5	# specify decrement
(integer51)Copy the code

Precautions for hash data operations

  • Value == of the hash type can only store string == and cannot store other data types. == does not exist nesting. If the data is not retrieved, the corresponding value is nil.
  • Each hash can store 2^32-1 key-value pairs
  • The hash type is very close to the data storage form of objects, and can be flexibly added and deleted object attributes. However, hash is not designed to store a large number of objects. Do not abuse hash, let alone use it as a list of objects
  • Hgetall operation can == obtain all attributes ==. If there are too many internal fields, the overall data traversal efficiency will be very low, which may become a data access bottleneck

Hash application scenarios

Design and implementation of shopping cart in e-commerce website

Business analysis

  • Analyze only the Redis storage model for the shopping cart
    • Add, browse, change quantity, delete, empty
  • Shopping carts are persistently synchronized across databases
  • Relationship between shopping cart and order
    • Submit shopping cart: Read data to generate order
    • Merchant temporary price adjustment: subject to order level
  • Unlogged user shopping cart information store
    • Cookies are stored

The solution

  • With the customer ID as the key, each customer creates a ==hash storage structure to store the corresponding shopping cart information
  • The product number is stored as ==field== and the purchase quantity as ==value==
  • Add item: Append new field and value
  • Browse: Traverses the hash
  • Change the number of items: Increases/decreases, and sets the value to delete an item: deletes the field
  • Clear: Deletes the key
Id :001 User ID G01 G02 Commodity ID 127.0.0.1:6379> hmset ID :001 G01 100 G02 200 OK 127.0.0.1:6379> hmset ID :002 G02 10 G04 8 G05 100 OK 127.0.0.1:6379> hset ID: 001G03 5 (integer) 1 127.0.0.1:6379> hgetall ID :001 1)"g01"
2) "100"
3) "g02"
4) "200"
5) "g03"
6) "5"
127.0.0.1:6379> hdel id:001 g01
(integer) 1 127.0.0.1:6379> hgetall ID :001 1)"g02"
2) "200"
3) "g03"
4) "5"127.0.0.1:6379> hincrby ID :001 G03 3 (integer) 8 127.0.0.1:6379> hgetall ID :001 1)"g02"
2) "200"
3) "g03"
4) "8"

Copy the code

However, this is not enough at present. At present, the data is only stored in Redis, which does not accelerate the process. The commodity information also needs to be queried twice in the database

The solution

  • The item record in each shopping cart is saved as two fields

  • Field1 is dedicated to saving purchase quantities

    • Naming format: Commodity ID: NUMS

    Save data: values

  • Field2 is dedicated to saving the information displayed in the shopping cart, including text descriptions, picture addresses, owner information, and more

    • Name format: Product ID :info

Save data: JSON

127.0.0.1:6379> hmset id:003 g01:nums 100 g01:info {diannao,8000} OK 127.0.0.1:6379> hgetall ID :003 1)"g01:nums"
2) "100"
3) "g01:info"
4) "{diannao,8000}"127.0.0.1:6379> hmset id: 004g01 :nums 50 g01:info {diannao,8000} OK 127.0.0.1:6379> hgetall ID :004 1)"g01:nums"
2) "50"
3) "g01:info"
4) "{diannao,8000}"

Copy the code

The new problem with this is that g01:info is duplicated, so we use field2 as a separate hash to hold product information

Finally, if field has a value, do not add it. If field has no value, add it

hsetnx key field value

127.0.0.1:6379> hset ID: 004G01 :nums 200 (integer) 0 127.0.0.1:6379> hget ID: 004g01 :nums"200"127.0.0.1:6379> hsetnx ID: 004g01 :nums 400 (integer) 0
127.0.0.1:6379> hsetnx id:004 g05:nums 400
(integer) 1 127.0.0.1:6379> hgetall ID :004 1)"g01:nums"
2) "200"
3) "g01:info"
4) "{diannao,8000}"
5) "g05:nums"
6) "400"
Copy the code

Shopping spree

On the Double 11 event day, iPhone merchants will launch panic buying activities for iPhone12, iPad Pro and MacBook Pro products costing 5,000 yuan, 6,000 yuan and 10,000 yuan, with the upper limit of 100 units for each product

The solution

  • Use the merchant ID as the key
  • Take the id of the participating commodity as field
  • Take the quantity of commodities participating in the snap up as the corresponding value
  • Use a lower value to control the number of products when buying
127.0.0.1:6379> hmset shop:001 iphone12 100 iPad 100 macbook 100 OK 127.0.0.1:6379> hincrby shop:001 iphone12-1 (integer) 99

127.0.0.1:6379> hincrby shop:001 macbook -20
(integer) 80 127.0.0.1:6379> Hgetall Shop :001 1)"iphone12"
2) "99"
3) "ipad"
4) "100"
5) "macbook"
6) "80"
Copy the code