一、 为什么学习Redis
1.1 现存问题:
1.传统的数据在请求量过大,数据量过大时,要么直接宕机,要么速度奇慢。
2.在搭建集群后,Session数据无法共享,并且传统的锁操作也失效了
3.传统的关系型数据库无法适应非结构化数据的存储。
1.2 NOSQL
NOSQL:非关系型数据库,泛指除了关系型数据库之外的数据库。
- Key-Value:Redis
- 面向列存储:Hbase
- 文档型:Mongodb,Elasitcsearch
- 图形化:Neo4j
1.3Redis介绍
Redis是基于C语言编写的非关系型数据库,基于内存存储,还支持持久化,还提供了多种存储数据的结构,针对多种编程语言都提供了相应的API操作,并且还提供了主从,哨兵以及集群结构,解决性能瓶颈和单点故障问题。
二、安装、连接Redis
2.1 docker-compose.yml文件
version: "3.1"
services:
redis:
restart: always
image: 镜像地址
container_name: redis
ports:
- 6379:6379
2.2连接Redis服务
- 使用Redis容器内部的redis-cli客户端去连接Redis服务
— 进入容器内部后,输入 redis-cli -h 127.0.0.1 -p 6379
— 测试set和get命令- 使用图形化界面连接:RedisDesktopManager
三、Redis存储数据的结构。
Redis存储数据的结构一共有8种,常用的有5种
- key-string:存储最简单的数据,一个key对应一个信息
- key-hash:存储一个对象的信息。
- key-list:存储一个列表,可以实现栈和队列结构(允许重复,存取有序)
- key-set:存储一个集合,提供并集,交集和差集 的操作。(不允许重复,存取无序)
- key-zset:存储一个集合,实现排行榜,积分榜等操作。(不允许重复,存取有序,根据指定的score)
四、Redis的操作
4.1 string命令
- set key value:设置key和value
- get key:通过key获取value
- setex key second value:设置key和value的同时指定key的生存时间
- setnx key value:当key不存在时,设置key和value,如果key存在,什么都不做
- incr key:将key对应的value自增1(value必须是数值)
- decr key:将key对应的value自减1(value必须是数值)
4.2 hash命令
- hset key field value:添加key,field,value值
- hmset key field value [field value…]:批量添加key,filed,value值
- hget key field:通过key和field获取value
- hkeys key:通过key获取当前全部的field
- hgetall key:通过key获取当前全部的field和value
- hlen key:通过key获取当前field的数量
- hdel key field[field…]:通过key和field删除当前的value
4.3 list命令
- lpush key value[value…] :从头部插入指定key的list结构中的value数据
- rpush key value [value…]:从尾部插入指定key的list结构中的value数据
- lset key index value:替换指定key的list结构中数据体索引位置的值。
- lpop key:指定key的list结构从头部弹栈
- rpop key:指定key的list结构中从尾部弹栈
- lrang key start stop:指定key的list结构从start索引位置取值到stop索引位置的全部值,如果获取全部列表数据指定lrange key 0 -1。
4.4 set命令
- sadd key member [member …]:向set集合中添加数据。
- smembers key:获取set集合中全部的数据。
- spop key [count]:随机从set集合中移除并获取一个数据,也可以指定count个数。
- srandmember key [count]:随机从set集合中获取一个数据,也可以指定count个数。
- sinter set1 [set2 …]:获取多个set的交集数据。
- sunion set1 [set2 …]:获取多个set的并集数据。
- sdiff set1 [set2 …]:获取set1相对set2的差集数据。
- srem key member [member …]:删除set集合中的指定数据。
- sismember key member:查看当前member是否在set集合中,存在:1,不存在:0
- scard key:返回集合中的个数。
4.5 zset命令
- zadd key score member [score member …]:添加数据到zset集合,同时指定分数和数据。
- zincrby key increment member :修改zset中member对应的分数。
- zrem key member [member …]:删除zset中指定的member
- zscore key member:查询指定member的分数。
- zcard key:查看zset中有多少个数据。
- zcount key min max:查看指定分数范围内的条数。
- zrange key start stop [WITHSCORE]:根据索引的正序查询zset中的数据。
- zrevrange key start stop [WITHSCORE]:根据索引的倒序查询zset中的数据。
- zrangebyscore key min max [WITHSCORE] [limit offer count]:根据分数从小到大查询指定数据。
- zrevrangebyscore key max min [WITHSCORE] [limit offer count]:根据分数从大到小查询指定数据。
- 指定分数的详细信息:
- 默认情况分数有等于效果。
- 添加(数值,代表不等于。
- 最小值和最大值:-inf +inf。
4.6 key操作命令
- select db:切换数据库
- move key db:移动当前库的key到指定库
- keys pattern:查看当前库下的全不key
- expire key second:指定key的生存时间,单位是秒
- pexpire key millionsecond:指定key的生存时间,单位是毫秒
- expireat key timestamp:指定key能存活到哪个时间点,timestamp指定时间点
- pexpireat key million-timestamp :指定key能存活到哪个时间点,million-timestamp指定时间点
- ttl key:查看key的剩余生存时间,单位是秒
- pttl key :查看key的剩余生存时间,单位是毫秒
- persist key:移除key的生存时间
- del key [key…]:删除当前库中的key
4.7 库的操作命令
- flushdb:删除当前库的全部key
- flushall:删除全部库的全部key
- dbsize:查看当前库中key的个数
- lastsave:查看最后一次写操作的时间
- minitor:监控Redis命令的执行时间,发起者,以及具体命令
五、Java连接Redis操作
5.1 基操
- 创建项目
- 导入依赖
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
- 测试
package com.qf.test;
import org.junit.Test;
import redis.clients.jedis.Jedis;
/**
* 基操
*/
public class Demo1 {
@Test
public void test1(){
//1. 连接Redis.
Jedis jedis = new Jedis("10.0.131.232",6379);
//2. 操作.
jedis.set("name","张三");
//3. 释放资源.
jedis.close();
}
@Test
public void test2(){
//1. 连接Redis.
Jedis jedis = new Jedis("10.0.131.232",6379);
//--------------------------------------------
//2. 操作.
String name = jedis.get("name");
System.out.println(name);
//--------------------------------------------
//3. 释放资源.
jedis.close();
}
}
5.2 以byte[]的方式存储对象
- 导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
- 测试
package com.qf.test;
import com.qf.entity.User;
import org.junit.Test;
import org.springframework.util.SerializationUtils;
import redis.clients.jedis.Jedis;
/**
* 存储对象,以byte[]的方式.
*/
public class Demo2 {
@Test
public void test1(){
//1. 连接Redis.
Jedis jedis = new Jedis("10.0.131.232",6379);
//-----------------------------------------
//2. 操作.
//2.1 准备key和value
String key = "user";
User value = new User();
//2.2 将key和value转换成byte[]类型
byte[] byteKey = SerializationUtils.serialize(key);
byte[] byteValue = SerializationUtils.serialize(value);
//2.3 存储到redis
jedis.set(byteKey,byteValue);
//-----------------------------------------
//3. 释放资源.
jedis.close();
}
@Test
public void test2(){
//1. 连接Redis.
Jedis jedis = new Jedis("10.0.131.232",6379);
//-----------------------------------------
//2. 操作.
String key = "user";
//2.1 将key序列化为byte[]
byte[] byteKey = SerializationUtils.serialize(key);
//2.2 从redis获取byte[]数据
byte[] value = jedis.get(byteKey);
//2.3 将value反序列化成user对象
User user = (User) SerializationUtils.deserialize(value);
System.out.println(user);
//-----------------------------------------
//3. 释放资源.
jedis.close();
}
}
5.3 以JSON的方式存储对象
- 导入依赖
<!-- jsonlib,jackson,gson,fastJSON-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
- 测试
package com.qf.test;
import com.alibaba.fastjson.JSON;
import com.qf.entity.User;
import org.junit.Test;
import org.springframework.util.SerializationUtils;
import redis.clients.jedis.Jedis;
/**
* 存储对象,以json的方式.
*/
public class Demo3 {
@Test
public void test1(){
//1. 连接Redis.
Jedis jedis = new Jedis("10.0.131.232",6379);
//-----------------------------------------
//2. 操作.
//2.1 准备key和value
String key = "user";
User value = new User();
//2.2 将value转换成json字符串类型
String jsonValue = JSON.toJSONString(value);
//2.3 存储到Redis
jedis.set(key,jsonValue);
//-----------------------------------------
//3. 释放资源.
jedis.close();
}
@Test
public void test2(){
//1. 连接Redis.
Jedis jedis = new Jedis("10.0.131.232",6379);
//-----------------------------------------
//2. 操作.
//2.1 准备key
String key = "user";
//2.2 从Redis获取Value
String value = jedis.get(key);
//2.3 将Value反序列化一波(业务中大多数情况,不需要.)
User user = JSON.parseObject(value, User.class);
//2.4 输出
System.out.println(value);
System.out.println(user);
//-----------------------------------------
//3. 释放资源.
jedis.close();
}
}
5.4 用连接池操作Redis
package com.qf.test;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* 连接池的方式操作Redis
*/
public class Demo4 {
@Test
public void test1(){
//0. 创建GenericObjectPoolConfig对象,指定连接池信息
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(100);
poolConfig.setMaxIdle(10);
poolConfig.setMinIdle(5);
poolConfig.setMaxWaitMillis(3000);
//1. 创建JedisPool对象.
JedisPool jedisPool = new JedisPool(poolConfig,"10.0.131.232",6379);
//2. 通过pool获取Jedis对象
Jedis jedis = jedisPool.getResource();
//3. 操作.
String value = jedis.get("user");
System.out.println(value);
//4. 还回jedis对象.
jedis.close();
}
}
5.5 管道操作
可以用过管道事先将大量命令全部封装在管道中,一次性将命令全部发送给Redis服务器执行,并获取返回结果。
package com.qf.test;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;
/**
* Redis的管道操作
*/
public class Demo5 {
@Test
public void test1(){
//0. 创建GenericObjectPoolConfig对象,指定连接池信息
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(100);
poolConfig.setMaxIdle(10);
poolConfig.setMinIdle(5);
poolConfig.setMaxWaitMillis(3000);
//1. 创建JedisPool对象.
JedisPool jedisPool = new JedisPool(poolConfig,"10.0.131.232",6379);
//2. 通过pool获取Jedis对象
Jedis jedis = jedisPool.getResource();
//3. 操作.
//3.1 声明管道.
Pipeline pipelined = jedis.pipelined();
for (int i = 0; i <= 99999; i++) {
//3.2 向管道添加牡蛎
pipelined.incr("yyyy");
}
//3.3 将管道的命令全部发送给Redis执行.
pipelined.sync();
//4. 还回jedis对象.
jedis.close();
}
}