5 data types of redis:
1.1 string string (can be integer, floating point and string, collectively referred to as element)
1.2 list (implement queue, elements are not unique, first in first out principle)
1.3set set (different elements)
1.4 hash hash value (the key of hash must be unique)
1.5 sort set ordered set
1.String type
1.1 usage scenario:
Scene 1: "so and so variety", start the audition voting. You can only vote through wechat, and each wechat can only vote once every four hours.
Scenario 2: e-commerce merchants open the recommendation of popular goods. Popular goods cannot be in the popular period all the time. The popular period of each kind of goods is maintained for 3 days, and the popular goods will be automatically cancelled after 3 days
Scenario 3: hot news will appear on news websites. The biggest feature of hot news is timeliness. How to automatically control the timeliness of hot news
1.2 feedback on the success of data operation
1.2.1 indicates whether the operation result is successful
(integer)0 – > false failed
(integer)1 – > true successful
1.2.2 indicates the operation result value
(integer)3 – > 3
(integer)1 – > 1
Data not obtained
(nil) is equivalent to null
1.3 string type operation practice
String type is the simplest data type in redis. Its stored value can be string, and its maximum string length can be up to 512M. Based on this type, you can realize the word count of blog, continuously append the log to the specified key, realize a distributed self increment id, and realize the like operation of a blog
incr/incrby
When the stored string is an integer, redis provides a practical command INCR, which is used to increment the current key value and return the incremented value. If num does not exist, it will be created automatically. If it does exist, it will be automatically + 1.
INCR key
127.0.0.1:6379> set num 1
(integer) 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> keys *
1) "num"
127.0.0.1:6379> incr num
127.0.0.1:6379>
INCRBY key increment can specify growth data
127.0.0.1:6379> incrby num 2
(integer) 5
127.0.0.1:6379> incrby num 2
(integer) 7
127.0.0.1:6379> incrby num 2
(integer) 9
127.0.0.1:6379>
decr/decrby
When the stored string is an integer, redis provides a practical command DECR, which is used to decrement the current key value and return the incremented value. If num does not exist, it will be created automatically. If it does exist, it will be automatically - 1.
DECR key is decremented according to the default step size (1 by default)
Decrby key increment decrements according to the specified step size
append
Append a value to the tail. If the key does not exist, create the key. Its value is the written value, which is equivalent to SET key value. The return value is the total length of the appended string.
Syntax: APPEND key value
strlen
String length returns the length of the data. If the key does not exist, it returns 0. Note that if the key value is an empty string, it also returns 0.
Syntax: STRLEN key
127.0.0.1:6379> get test
"123abc"
127.0.0.1:6379> strlen test
(integer) 6
127.0.0.1:6379> strlen tnt
(integer) 0
127.0.0.1:6379> set tnt ""
OK
127.0.0.1:6379> strlen tnt
(integer) 0
127.0.0.1:6379> exists tnt
(integer) 1
127.0.0.1:6379>
mset/mget
Set / get multiple key values at the same time
Syntax: MSET key value [key value...]
MGET key [key ...]
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> mset a 1 b 2 c 3
OK
127.0.0.1:6379> mget a b c
1) "1"
2) "2"
3) "3"
127.0.0.1:6379>
- How to realize the word count of blog? (strlen)
- How to continuously append the audit log to the specified key?(append)
- How do you implement a distributed self increasing id? (incr snowflake algorithm)
- How to implement a blog like operation? (incr,decr)
2.string Application demo
1. Create project
Create a maven parent project, such as 03 SCA redis, and create two sub projects under this project, one is SCA jedis and the other is SCA temporary, for example:
1.2 add project dependencies in SCA jedis
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.6</version> </dependency>
1.3 add project dependencies in SCA template
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.3.2.RELEASE</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
Distributed id
Business description
In a distributed system, when the amount of data will become larger and larger, it is necessary to divide the data into tables. However, after table splitting, the data in each table will increase automatically according to its own rhythm, and there is likely to be id conflict. At this time, a separate mechanism is needed to generate a unique id. the generated id can also be called distributed id. here, we use redis to implement a simple method Of course, there are some third-party systems that can help you generate such IDs and expand your learning
Key code implementation
package com.jt.redis; import redis.clients.jedis.Jedis; import java.time.zone.ZoneOffsetTransitionRule; /** * Requirement: generate an id with increasing distribution * Multiple tables use the id generated in this method as the primary key id value (the database will not be used in the distributed environment) * Self increment strategy in the table -auto_increment) */ public class IdGenerator { //Virtual machine IP address private static final String IP ="192.168.126.129"; //redis port number private static final int port =6379; public static Long getId(){ Jedis jedis = new Jedis(IP,port); //jedis.auth("123456"); / / the database password does not need to be written without a password Long id = jedis.incr("id"); jedis.close();//Close connection return id; } public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(){ @Override public void run() { Long id = IdGenerator.getId(); System.out.println("id = "+id); } }.start(); } } }2.hash hash hash value (the key of hash must be unique)
Confusion of String type storage
If the storage of object class data has frequent update requirements, the operation will be cumbersome, easy to save and troublesome to change.
In order to distinguish it from the address of key value pairs in Redis, the key in hash becomes field, and the key features the key of Redis.
2.1hash type
New storage requirements: organize a series of stored data to facilitate management, and store object information in typical applications
Memory structure required: how many key value pairs of data are stored in a storage space
Hash type: the bottom layer uses hash table structure to realize data storage
2.2cash type data operation precautions
The value under the hash type can only store strings. It is not allowed to store other types of data. There is no nesting. If the data is not obtained, the corresponding value is (nil)
Each hash can store 232-1 key value pairs
Hash type is very close to the data storage form of objects, and object attributes can be added and deleted flexibly. However, hash is not designed to store a large number of objects. Remember not to abuse it, and hash can not be used as an object list
hgetall operation can obtain all attributes. If there are too many internal key s, the overall data traversal efficiency will be very low, which may become a data access bottleneck.
2.3 hash grammar practice
hset/hget
HSET key field value
HGET key field
HMSET key field value [field value...]
HMGET key field [field]
HGETALL key
127.0.0.1:6379> hset user username chenchen
(integer) 1
127.0.0.1:6379> hget user username
"chenchen"
127.0.0.1:6379> hset user username chen
(integer) 0
127.0.0.1:6379> keys user
1) "user"
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
127.0.0.1:6379>
127.0.0.1:6379> hset user age 18
(integer) 1
127.0.0.1:6379> hset user address "xi'an"
(integer) 1
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
3) "age"
4) "18"
3) "address"
4) "xi'an"
127.0.0.1:6379>
The HSET command does not distinguish between insert and update operations. The HSET command returns 1 when performing insert operations and 0 when performing update operations.
hincrby
127.0.0.1:6379> hdecrby article total 1 # Error during execution
127.0.0.1:6379> hincrby article total -1 # There is no hdecrby subtraction command
(integer) 1
127.0.0.1:6379> hget article total # Get value
hmset/hmget
HMSET and HMGET set and get object properties
127.0.0.1:6379> hmset person username tony age 18
OK
127.0.0.1:6379> hmget person age username
1) "18"
2) "tony"
127.0.0.1:6379> hgetall person
1) "username"
2) "tony"
3) "age"
4) "18"
127.0.0.1:6379>
hexists
Does the property exist
127.0.0.1:6379> hexists killer
(error) ERR wrong number of arguments for 'hexists' command
127.0.0.1:6379> hexists killer a
(integer) 0
127.0.0.1:6379> hexists user username
(integer) 1
127.0.0.1:6379> hexists person age
(integer) 1
127.0.0.1:6379>
hdel
127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
127.0.0.1:6379> hgetall person
1) "username"
2) "tony"
3) "age"
4) "18"
127.0.0.1:6379>
hkeys/hvals
Only get the field name HKEYS or field value HVALS
127.0.0.1:6379> hkeys person
1) "username"
2) "age"
127.0.0.1:6379> hvals person
1) "tony"
2) "18"
2.3.8 hlen
Number of elements
127.0.0.1:6379> hlen user
(integer) 1
127.0.0.1:6379> hlen person
(integer) 2
127.0.0.1:6379>
Section interview analysis
- Do I need to write memory to publish a blog? (yes, hmset)
- What would you do to browse blog content? (hmget)
- How to determine whether a blog exists
- How to delete a blog? (hdel)
- How do you store user information after successful login in a distributed system? (hmset)
hash application scenario
Single sign on
Business description
In the distributed system, there will be multiple services. When we log in to one service and then access other services, we don't want to log in again. We usually call it the single sign on system. In this system, an authentication server is provided to complete user identity authentication. In some small and medium-sized distributed systems, we usually use redis Store user authentication information
Key code implementation
package com.jt.redis; import redis.clients.jedis.Jedis; import java.util.Map; import java.util.UUID; /** * SSO(Single sign on system) case demonstration: * 1)Access resources (if you don't log in, you should be prompted to log in first. How to determine whether you log in or not) * 2)Execute login (login is successful and user login information is stored) * 3)Access resources (logged in) * Solution * 1)Scheme 1:SpringSecurity+jwt+oauth2 (large concurrency) * 2)Scheme 2: Spring Security + redis + oauth2 (small and medium-sized concurrent) * */ public class SSODemo02 { /**Login design of Certification Center*/ static String doLogin(String username,String password){ //1. Perform user identity verification if(!"jack".equals(username))//In the future, this jack will come from the database throw new IllegalArgumentException("This user does not exist"); //2. If the user exists and the password is correct, it means that the user is a legal user of the system if(!"123456".equals(password)) throw new IllegalArgumentException("Incorrect password"); //3. Store legal user information in redis Jedis jedis=new Jedis("192.168.126.129", 6379); String token=UUID.randomUUID().toString(); jedis.hset(token,"username",username); jedis.hset(token, "status", "1"); //.... jedis.expire(token, 2); jedis.close(); return token;//token } /**Get resources in resource service*/ static Object doGetResource(String token){ //1. Check whether the user has logged in if(token==null||"".equals(token)) throw new IllegalArgumentException("Please log in first"); Jedis jedis=new Jedis("192.168.126.129", 6379); Map<String,String> map=jedis.hgetAll(token); jedis.close(); //2. If you do not log in, you will be prompted to log in first System.out.println("map="+map); if(map.isEmpty()) throw new RuntimeException("Login timeout or token Invalid, please login again"); //3. If you are logged in, you can access resources System.out.println("Continue accessing resources"); //..... return "the resource of user"; } //Suppose the main method here is the client public static void main(String[] args) throws InterruptedException { String token=null; //First access to resources // doGetResource(token); //Perform login operation (authentication will be implemented in the authentication center in the future) token=doLogin("jack", "123456"); //Second access to resources Thread.sleep(2000); doGetResource(token); } }