Redis
1.1 概念
- 随着互联网的发展, web2.0的兴起, 高并发的纯动态网站(抖音,快手),要是使用传统的关系型数据库,显得有点力不从心,因此,NoSQL应运而生,他就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题
什么是Redis
Redis: 是一款高性能的NOSQL(Not Only SQL)系列的非关系型数据库
Redis是一款用c语言开发的的一个开源的键值对数据库(一共就3万多行代码,厉害!),目前他支持下列的数据类型
- String :相当于String
- Hash : 相当于Map
- list: 相当于 linkedlist
- set: 相当于set
- sortedset(有序集合类型) : 不允许重复,且会排序
大概是下面这样
应用场景
- 缓存
- 聊天室的在线好友列表
- 任务队列 (秒杀,抢购)
- 应用排行榜
- 网站访问统计
- 数据过期处理
- 分布式集群架构中的session分离
NOSQL的优点和缺点
优点
- 成本: 易于部署,基本都是开源软件,不用花钱买
- 查询速度贼快(因为是在内存中)
- 存储的数据形式: key:value格式, 文档形式,图片形式, 图片形式等等. 所以可以存储基础类型以及对象或者是集合等各种格式,而数据库则只支持基础类型
- 拓展性: 关系型数据库有类似join这种多表查询机制的限制导致拓展很难
缺点
- 新技术,所以维护和资料有限
- 不提供对于sql的支持,因此学习不同的NOSQL数据库学习成本高
- 不提供关系型数据库对于事务的处理
和SQL数据库由有什么区别?
对于SQL数据库
- 数据之间常常有联系(数据在一个表中,不同表之间也有关系)
- 数据是保存在硬盘文件里面的
对于非关系型数据库
- 数据之间没有联系
- 数据存储在内存中
非关系型数据有什么用?
- 对于一些经常查询但是却不怎么发生变化的数据,我们可以在服务器本地使用这个数据库,这样可以提升速度
流程如下
1.2 命令操作
redis的数据结构
- redis存储的是: key:value 格式的数据结构,其中key都是字符串,value有5中数据类型
String的命令操作
常用命令如下
- 存储: set key value [EX seconds] [PX milliseconds] [NX|XX]
- 获取: get key
- 删除: del key [key …]
这是所有命令
1 SET key value 设置指定 key 的值
2 GET key 获取指定 key 的值。
3 GETRANGE key start end 返回 key 中字符串值的子字符
4 GETSET key value 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
5 GETBIT key offset 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
6 MGET key1 [key2..] 获取所有(一个或多个)给定 key 的值。
7 SETBIT key offset value 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
8 SETEX key seconds value 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
9 SETNX key value 只有在 key 不存在时设置 key 的值。
10 SETRANGE key offset value 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。
11 STRLEN key 返回 key 所储存的字符串值的长度。
12 MSET key value [key value ...] 同时设置一个或多个 key-value 对。
13 MSETNX key value [key value ...] 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
14 PSETEX key milliseconds value 这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
15 INCR key 将 key 中储存的数字值增一。
16 INCRBY key increment 将 key 所储存的值加上给定的增量值(increment) 。
17 INCRBYFLOAT key increment 将 key 所储存的值加上给定的浮点增量值(increment) 。
18 DECR key 将 key 中储存的数字值减一。
19 DECRBY key decrement key 所储存的值减去给定的减量值(decrement) 。
20 APPEND key value 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾
Hash的命令操作
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。
常用命令如下
-
存储:hset key field value
-
//将下面admin和password存进myhash这个key里面 hset myhash username admin hset myhash password 123456
-
-
获取:
-
hget key field : 获取指定key上面的指定的field
-
hgetall key: 获取指定key所有的field和value
hget myhash username admin hget myhash password 123456 hgetall myhash
-
-
删除:hdel key field [field …]
所有命令
1 HDEL key field2 [field2] 删除一个或多个哈希表字段
2 HEXISTS key field 查看哈希表 key 中,指定的字段是否存在。
3 HGET key field 获取存储在哈希表中指定字段的值/td>
4 HGETALL key 获取在哈希表中指定 key 的所有字段和值
5 HINCRBY key field increment 为哈希表 key 中的指定字段的整数值加上增量 increment 。
6 HINCRBYFLOAT key field increment 为哈希表 key 中的指定字段的浮点数值加上增量 increment 。
7 HKEYS key 获取所有哈希表中的字段
8 HLEN key 获取哈希表中字段的数量
9 HMGET key field1 [field2] 获取所有给定字段的值
10 HMSET key field1 value1 [field2 value2 ] 同时将多个 field-value (域-值)对设置到哈希表 key 中。
11 HSET key field value 将哈希表 key 中的字段 field 的值设为 value 。
12 HSETNX key field value 只有在字段 field 不存在时,设置哈希表字段的值。
13 HVALS key 获取哈希表中所有值
14 HSCAN key cursor [MATCH pattern] [COUNT count] 迭代哈希表中的键值对。
list的命令操作
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
常用的命令如下
- 存储:
- lpush key value [value …] : 从数组的头部添加
- rpush key value [value …] : 从数组的尾部添加
- 获取:
- lrange key start end: 获取该数组范围内的所有数据 (想要获取所有的可以0 -1)
- LLEN key 获取列表长度
- 删除:
- lpop: 从列表头部弹出一个元素,并将元素返回
- rpop: 从列表的尾部弹出一个元素,并将元素返回
下面是所有的命令
1 BLPOP key1 [key2 ] timeout 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
2 BRPOP key1 [key2 ] timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
3 BRPOPLPUSH source destination timeout 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
4 LINDEX key index 通过索引获取列表中的元素
5 LINSERT key BEFORE|AFTER pivot value 在列表的元素前或者后插入元素
6 LLEN key 获取列表长度
7 LPOP key 移出并获取列表的第一个元素
8 LPUSH key value1 [value2] 将一个或多个值插入到列表头部
9 LPUSHX key value 将一个或多个值插入到已存在的列表头部
10 LRANGE key start stop 获取列表指定范围内的元素
11 LREM key count value 移除列表元素
12 LSET key index value 通过索引设置列表元素的值
13 LTRIM key start stop 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
14 RPOP key 移除并获取列表最后一个元素
15 RPOPLPUSH source destination 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
16 RPUSH key value1 [value2] 在列表中添加一个或多个值
17 RPUSHX key value 为已存在的列表添加值
set的命令操作
Redis的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
常用命令
- 存储:
- sadd key value
- 获取:
- smembers key : 获取set集合中的所有元素
- 删除
- srem key value: 删除set集合中的某个元素
所有命令
1 SADD key member1 [member2] 向集合添加一个或多个成员
2 SCARD key 获取集合的成员数
3 SDIFF key1 [key2] 返回给定所有集合的差集
4 SDIFFSTORE destination key1 [key2] 返回给定所有集合的差集并存储在 destination 中
5 SINTER key1 [key2] 返回给定所有集合的交集
6 SINTERSTORE destination key1 [key2] 返回给定所有集合的交集并存储在 destination 中
7 SISMEMBER key member 判断 member 元素是否是集合 key 的成员
8 SMEMBERS key 返回集合中的所有成员
9 SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合
10 SPOP key 移除并返回集合中的一个随机元素
11 SRANDMEMBER key [count] 返回集合中一个或多个随机数
12 SREM key member1 [member2] 移除集合中一个或多个成员
13 SUNION key1 [key2] 返回所有给定集合的并集
14 SUNIONSTORE destination key1 [key2] 所有给定集合的并集存储在 destination 集合中
15 SSCAN key cursor [MATCH pattern] [COUNT count] 迭代集合中的元素
sortedset的命令操作
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
常用命令
- 存储:
- zadd key score value
- 获取
- zrange key start stop [WITHSCORES]
- ZRANK key member 返回有序集合中指定成员的索引
- 删除
- zrem key member [member …]
所有命令
1 ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
2 ZCARD key 获取有序集合的成员数
3 ZCOUNT key min max 计算在有序集合中指定区间分数的成员数
4 ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
5 ZINTERSTORE destination numkeys key [key ...] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中
6 ZLEXCOUNT key min max 在有序集合中计算指定字典区间内成员数量
7 ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合成指定区间内的成员
8 ZRANGEBYLEX key min max [LIMIT offset count] 通过字典区间返回有序集合的成员
9 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 通过分数返回有序集合指定区间内的成员
10 ZRANK key member 返回有序集合中指定成员的索引
11 ZREM key member [member ...] 移除有序集合中的一个或多个成员
12 ZREMRANGEBYLEX key min max 移除有序集合中给定的字典区间的所有成员
13 ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员
14 ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员
15 ZREVRANGE key start stop [WITHSCORES] 返回有序集中指定区间内的成员,通过索引,分数从高到底
16 ZREVRANGEBYSCORE key max min [WITHSCORES] 返回有序集中指定分数区间内的成员,分数从高到低排序
17 ZREVRANK key member 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
18 ZSCORE key member 返回有序集中,成员的分数值
19 ZUNIONSTORE destination numkeys key [key ...] 计算给定的一个或多个有序集的并集,并存储在新的 key 中
20 ZSCAN key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成员和元素分值)
通用命令
- keys* : 查询所有的键
- type key: 获取键对应的value类型
- del key: 删除指定的key
1.3 Redis持久化
我们为了将临时的数据保存,我们需要将数据持久化,保存到硬盘的文件中,这样我们的数据就能够保存
持久化机制
RDB
默认的方式,不需要进行配置,默认就是用这种机制
-
原理:在一定的时间间隔中,检测key的变化,然后持久化数据
-
临时缓存数据保存在
dump.rdb
中 -
对性能的影响比较低
-
配置: 编辑redis.windows.conf文件
# In the example below the behaviour will be to save: # after 900 sec (15 min) if at least 1 key changed # after 300 sec (5 min) if at least 10 keys changed # after 60 sec if at least 10000 keys changed save 900 1 save 300 10 save 60 10000
-
AOF
-
日志记录的方式,可以记录每一条命令操作。可以每一次命令操作后,持久化数据
-
对性能的影响较大
-
配置:编辑
redis.windows.conf
appendonly no(默认关闭) appendonly yes(这是开启)
-
三个相关的配置,三个只能取一个
# appendfsync always (每一次操作都进行持久化) appendfsync everysec (每秒都进行持久化) # appendfsync no (不进行持久化操作)
-
第二章 Jedis
2.1 概念&快速入门
Jedis : 一款Java操作redis数据库的工具
使用步骤
- 下载并导入jedis的jar包
- 创建测试类
- 在测试类中,获取连接池对象,操作,关闭连接池
public class JedisTest {
//快速入门
@Test
public void test01(){
//获取链接
Jedis jedis = new Jedis("localhost",6379);//如果是空参,那么默认会链接本地locahost和默认端口
//操作
jedis.set("name","hhhhhhh");
//关闭链接
jedis.close();
}
}
2.2 操作各种数据类型
我们需要知道的就是,这下面的所有的命令,和redis基本一模一样
操作String
@Test
public void test01(){
//获取链接
Jedis jedis = new Jedis("localhost",6379);
//操作
System.out.println(jedis.get("username"));//your_father
//使用下面这个方法,可以在指定的秒数之后删除这个键值对,用于激活码的有效期等等有时效限制的东西
jedis.setex("activecode",10,"I am your father");//10秒之后删除
//关闭链接
jedis.close();
}
操作hash
@Test
public void test02(){
//获取链接
Jedis jedis = new Jedis("localhost",6379);
//操作
jedis.hset("myHash","user","father");
jedis.hset("myHash","age","22");
jedis.hset("myHash","gender","male");
//获取
System.out.println(jedis.hget("myHash", "user"));//father
System.out.println(jedis.hgetAll("myHash"));//{gender=male, user=father, age=22}
//关闭链接
jedis.close();
}
操作list
@Test
public void test03(){
//获取链接
Jedis jedis = new Jedis("localhost",6379);
//操作
jedis.lpush("myList","a","b","c");
jedis.rpush("myList","a","b","c");
System.out.println(jedis.lrange("myList",0,-1));//[c, b, a, a, b, c]
//关闭链接
jedis.close();
}
操作set&sortedset
@Test
public void test04(){
//获取链接
Jedis jedis = new Jedis("localhost",6379);
//操作
jedis.sadd("mySet","a","b","c");
System.out.println(jedis.smembers("mySet"));//存进了abc,顺序可能是随机的
jedis.zadd("mySortedSet",0.1,"aaa");
jedis.zadd("mySortedSet",0.2,"bbb");
jedis.zadd("mySortedSet",0.2,"ccc");
System.out.println(jedis.zrange("mySortedSet", 0, -1));//[aaa, bbb, ccc]
//关闭链接
jedis.close();
}
2.3 连接池
连接池是jedis自带的,类名叫做JedisPool
使用步骤
- 创建连接池对象
- 调用方法
getResource()
方法获取Jedis链接
@Test
public void test05() {
//创建一个配置对象,来设置连接池的各种参数
JedisPoolConfig jpc = new JedisPoolConfig();
jpc.setMaxTotal(50);
jpc.setMaxIdle(10);
JedisPool pool = new JedisPool(jpc,"localhost",6379);//空参就是使用默认参数
//获取连接池对象
Jedis jedis = pool.getResource();
jedis.set("haha", "aaaa");
System.out.println(jedis.get("haha"));//aaaa
//这里并不是真正的关闭,只是将资源归还给连接池
jedis.close();
}
具体配置信息如图
工具类
有时候,我们想要通过配置文件来加载连接池的配置,那么我们就要自己写一个工具类来实现这个功能
//工具类
package Utils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* 提过获取连接的方法,他的作用就是加载配置文件
*/
public class JedisPoolUtils {
private static JedisPool jedisPool;
//加载配置文件
static {
InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
Properties properties = new Properties();
try {
properties.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//获取到配置,现在我们将这个输入到类中
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.parseInt(properties.getProperty("maxTotal")));
config.setMaxIdle(Integer.parseInt(properties.getProperty("maxIdle")));
//初始化连接池
jedisPool = new JedisPool(config, properties.getProperty("host"), Integer.parseInt(properties.getProperty("port")));
}
public static Jedis getJedis() {
return jedisPool.getResource();
}
}
//测试的方法
@Test
public void test06() {
Jedis jedis = JedisPoolUtils.getJedis();
jedis.set("nimade","hhhh");
System.out.println(jedis.get("nimade"));//hhhh
jedis.close();
}