Redis
为什么学习Redis。
1.1 现存问题:
1、 传统的数据在请求量过大,数据量过大时,要么直接宕机,要么速度奇慢。
2、 再搭建集群后,Session数据无法共享,并且传统的锁操作也失效了。
3、 传统的关系型数据库无法适应非结构化数据的存储。
1.2 NOSQL
NOSQL : 非关系型数据库,泛指除了关系型数据库之外的数据库;
- Key-Value :Redis
- 面向列存储;
- 文档型:MongoDB,Elasitcsearch
- 图形化:Neo4j
1.3 Redis介绍
- Redis 是基于C语言编写的非关系型数据库,基于内存存储,还支持持久化;
- 还提供了多种存储数据的结构,针对多种编程语言都提供了相应的API操作;
- 提供了主从,哨兵以及集群结构,解决性能瓶颈和单点故障;
二、安装、连接Redis
2.1 docker-compose.yml文件
version: "3.1"
services:
redis:
restart: always
image: 10.0.134.175:5000/redis:5.0.9
container_name: redis
ports:
- 6379:6379
2.2 连接Redis服务
- 使用Redis容器内部的redis-cli客户端去连接Redis服务
- 进入容器内部后,输入:[redis-cli -h 127.0.0.1 -p 6379]()
- 测试set和get命令。
- 使用图形化界面连接;
三、Redis存储数据的结构。
Redis存储数据的结构一共有8中,常用的有5种。
- key-string:存储最简单的数据,一个key对应一个信息。
- key-hash:存储一个对象的信息。
- key-list:存储一个列表,可以实现栈和队列结构。(允许重复,存取有序)
- key-set:存储一个集合,提供并集,交集和差集 的操作。(不允许重复,存取无序)
- key-zset:存储一个集合,实现排行榜,积分榜等操作。(不允许重复,存取有序,根据指定的score)
- HyperLogLog:(了解)
- geo:(了解)
- 位图:(了解)
四、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,field,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结构中从尾部弹栈。
- lrange key start stop:指定key的list结构从start索引位置取值到stop索引位置的全部值,如果获取全部列表数据指定lrange key 0 -1。
4.4set命令
- 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.5Zset命令
- 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]:根据分数从大到小查询指定数据。
- 指定分数的详细信息:
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>
- 测试: - ```java 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>
- 测试: - ```java 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>
- 测试: - ```java 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();
}
}
六、作业。。。
周末任务:
- 屡顺第一周的全部内容,整理笔记.(电子版,纸质).
- 完成web-master的Session共享操作,并保证在部署到服务器后,可以实现在一台服务器上登录,另外一个也有标识信息.