目录
[一、 Redis介绍](#一、 Redis介绍)
[1. NoSQL的引言](#1. NoSQL的引言)
[2. 为什么是NoSQL](#2. 为什么是NoSQL)
[3. NoSQL的四大分类](#3. NoSQL的四大分类)
[3.1. 键值(Key-Value)存储数据库](#3.1. 键值(Key-Value)存储数据库)
[3.2 .列存储数据库](#3.2 .列存储数据库)
[3.3 .文档型数据库](#3.3 .文档型数据库)
[3.4 .图形(Graph)数据库](#3.4 .图形(Graph)数据库)
[4. NoSQL应用场景](#4. NoSQL应用场景)
[5. 什么是Redis](#5. 什么是Redis)
[6. Redis特点](#6. Redis特点)
[三、 Redis命令操作](#三、 Redis命令操作)
[1 数据库操作指令](#1 数据库操作指令)
[2 操作key相关指令](#2 操作key相关指令)
[3 String类型](#3 String类型)
[1. 内存存储模型](#1. 内存存储模型)
[2. 常用操作命令](#2. 常用操作命令)
[4 List类型](#4 List类型)
[5 Set类型](#5 Set类型)
[6 ZSet类型](#6 ZSet类型)
[7 hash类型](#7 hash类型)
[1. RDB方式 快照(Snapshot)](#1. RDB方式 快照(Snapshot))
[1.1. 特点](#1.1. 特点)
[2.AOF 只追加日志文件](#2.AOF 只追加日志文件)
[3. 持久化总结](#3. 持久化总结)
[五 使用 Java 客户端操作 Redis](#五 使用 Java 客户端操作 Redis)
[1.下载 Jedis 的 jar 包](#1.下载 Jedis 的 jar 包)
[2.Jedis 操作各种 Redis 数据结构](#2.Jedis 操作各种 Redis 数据结构)
[3. Jedis 连接池:JedisPool](#3. Jedis 连接池:JedisPool)
[4.Jedis 连接池工具类](#4.Jedis 连接池工具类)
一、 Redis介绍
1. NoSQL的引言
NoSQL (Not Only SQL
),意即不仅仅是SQL, 泛指非关系型的数据库。是一项全新的数据库理念,泛指非关系型的数据库。
2. 为什么是NoSQL
随着互联网网站的兴起,传统的关系数据库在应付动态网站,特别是超大规模和高并发的纯动态网站已经显得力不从心,暴露了很多难以克服的问题。如商城网站中对商品数据频繁查询
、对热搜商品的排行统计
、订单超时问题
、以及微信朋友圈(音频,视频)存储等相关使用传统的关系型数据库实现就显得非常复杂,虽然能实现相应功能但是在性能上却不是那么乐观。nosql这个技术门类的出现,更好的解决了这些问题,它告诉了世界不仅仅是sql。
3. NoSQL的四大分类
3.1. 键值(Key-Value)存储数据库
md-end-block
# 1.说明:
- 这一类数据库主要会使用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。
# 2.特点
- Key/value模型对于IT系统来说的优势在于简单、易部署。
- 但是如果DBA只对部分值进行查询或更新的时候,Key/value就显得效率低下了。
# 3.相关产品
- Tokyo Cabinet/Tyrant,
- Redis
- SSDB
- Voldemort
- Oracle BDB
3.2 .列存储数据库
md-end-block
# 1.说明
- 这部分数据库通常是用来应对分布式存储的海量数据。
# 2.特点
- 键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。
# 3.相关产品
- Cassandra、HBase、Riak.
3.3 .文档型数据库
md-end-block
# 1.说明
- 文档型数据库的灵感是来自于Lotus Notes办公软件的,而且它同第一种键值存储相类似该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可 以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高
# 2.特点
- 以文档形式存储
# 3.相关产品
- MongoDB、CouchDB、 MongoDb(4.x). 国内也有文档型数据库SequoiaDB,已经开源。
3.4 .图形(Graph)数据库
md-end-block
# 1.说明
- 图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。
- NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数据接口或者查询API。
# 2.特点
# 3.相关产品
- Neo4J、InfoGrid、 Infinite Graph、
4. NoSQL应用场景
-
缓存(数据查询、短连接、新闻内容、商品内容等等)
-
聊天室的在线好友列表
-
任务队列。(秒杀、 抢购、12306等等)
-
应用排行榜
-
网站访问统计
-
数据过期处理(可以精确到毫秒)
-
分布式集群架构中的 session 分离
5. 什么是Redis
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.
Redis 开源 遵循BSD 基于内存数据存储 被用于作为 数据库 缓存 消息中间件
Redis 是用 C 语言开发的一个开源的高性能键值对(key-value)数据库,官方提供测试数据,50个并发执行100000个请求,读的速度是110000次/s,写的速度是81000次/s,且 Redis 通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止 Redis 支持的键值数据类型如下: 字符串类型 String 哈希类型 Hash 列表类型 List 集合类型 Set 有序集合类型 sortedset
- 总结: redis是一个内存型的数据库
6. Redis特点
-
Redis是一个高性能key/value内存型数据库
-
Redis支持丰富的数据类型
-
Redis支持持久化
-
Redis单线程,单进程
二、Redis安装和设置
1.下载安装
Redis 官网(Linux 版本) Redis 中文官网 Redis (Windows 版本)GitHub 下载
-
解压直接可以使用,找到文件:
-
redis.windows.conf :配置文件
-
redis-cli.exe :Redis 的客户端
-
redis-server.exe :Redis 的服务器端
开启 Redis 时,需要先双击开启服务器端,再开启客户端
-
-
服务器端
- 客户端
- 要先开启服务器端,才能开启客户端
三、 Redis命令操作
1 数据库操作指令
md-end-block
# 1.Redis中库说明
- 使用redis的默认配置器动redis服务后,默认会存在16个库,编号从0-15
- 可以使用select 库的编号 来选择一个redis的库
# 2.Redis中操作库的指令
- 清空当前的库 FLUSHDB
- 清空全部的库 FLUSHALL
2 操作key相关指令
md-end-block
# 1.DEL指令
- 语法 : DEL key [key ...]
- 作用 : 删除给定的一个或多个key 。不存在的key 会被忽略。
- 可用版本: >= 1.0.0
- 返回值: 被删除key 的数量。
# 2.EXISTS指令
- 语法: EXISTS key
- 作用: 检查给定key 是否存在。
- 可用版本: >= 1.0.0
- 返回值: 若key 存在,返回1 ,否则返回0。
# 3.EXPIRE
- 语法: EXPIRE key seconds
- 作用: 为给定key 设置生存时间,当key 过期时(生存时间为0 ),它会被自动删除。
- 可用版本: >= 1.0.0
- 时间复杂度: O(1)
- 返回值:设置成功返回1 。
# 4.KEYS
- 语法 : KEYS pattern
- 作用 : 查找所有符合给定模式pattern 的key 。
- 语法:
KEYS * 匹配数据库中所有key 。
KEYS h?llo 匹配hello ,hallo 和hxllo 等。
KEYS h*llo 匹配hllo 和heeeeello 等。
KEYS h[ae]llo 匹配hello 和hallo ,但不匹配hillo 。特殊符号用 "\" 隔开
-可用版本: >= 1.0.0
-返回值: 符合给定模式的key 列表。
# 5.TTL
- 语法 : TTL key
- 作用 : 以秒为单位,返回给定key 的剩余生存时间(TTL, time to live)。
- 可用版本: >= 1.0.0
- 返回值:
当key 不存在时,返回-2 。
当key 存在但没有设置剩余生存时间时,返回-1 。
否则,以秒为单位,返回key 的剩余生存时间。
- Note : 在Redis 2.8 以前,当key 不存在,或者key 没有设置剩余生存时间时,命令都返回-1 。
# 6.RENAME
- 语法 : RENAME key newkey
- 作用 : 将key 改名为newkey 。当key 和newkey 相同,或者key 不存在时,返回一个错误。当newkey 已经存在时,RENAME 命令将覆盖旧值。
- 可用版本: >= 1.0.0
- 返回值: 改名成功时提示OK ,失败时候返回一个错误。
# 7.TYPE
- 语法 : TYPE key
- 作用 : 返回key 所储存的值的类型。
- 可用版本: >= 1.0.0
- 返回值:
none (key 不存在)
string (字符串)
list (列表)
set (集合)
zset (有序集)
hash (哈希表)
Redis是一个key-value的数据库,key一般是String类型,不过value的类型多种多样:官网也给出了命令解释
Commands | Docshttps://redis.io/commands
3 String类型
1. 内存存储模型
2. 常用操作命令
命令 | 说明 |
---|---|
set | 设置一个key/value |
get | 根据key获得对应的value |
mset | 一次设置多个key value |
mget | 一次获得多个key的value |
getset | 获得原始key的值,同时设置新值 |
strlen | 获得对应key存储value的长度 |
append | 为对应key的value追加内容 |
setex | 设置一个key存活的有效期(秒) |
setnx | 存在不做任何操作,不存在添加 |
msetnx原子操作(只要有一个存在不做任何操作) | 可以同时设置多个key,只有有一个存在都不保存 |
decr | 进行数值类型的-1操作 |
decrby | 根据提供的数据进行减法操作 |
Incr | 进行数值类型的+1操作 |
incrby | 根据提供的数据进行加法操作 |
incrby age 10
setex key time value
4 List类型
list 列表 相当于java中list 集合 特点 :元素有序 且 可以重复
1.内存存储模型
2.常用操作指令
命令 | 说明 |
---|---|
lpush | 将某个值加入到一个key列表头部 |
lpushx | 同lpush,但是必须要保证这个key存在 |
rpush | 将某个值加入到一个key列表末尾 |
rpushx | 同rpush,但是必须要保证这个key存在 |
lpop | 返回和移除列表左边的第一个元素 |
rpop | 返回和移除列表右边的第一个元素 |
lrange | 获取某一个下标区间内的元素,从0开始 |
llen | 获取列表元素个数 |
lset | 设置某一个指定索引的值(索引必须存在) |
lindex | 获取某一个指定索引位置的元素 |
lrem | 删除重复元素 |
ltrim | 保留列表中特定区间内的元素 |
linsert | 在某一个元素之前,之后插入新元素 |
lpush 集合名 元素名
llen 集合名
lrange 集合名 开始索引 结束索引
lindex 集合名 索引
lrem 集合名 删除的个数 元素名
5 Set类型
特点: Set类型 Set集合 元素无序 不可以重复,好友,可能认识的人。
1.内存存储模型
2.常用命令
命令 | 说明 |
---|---|
sadd | 为集合添加元素 |
smembers | 显示集合中所有元素 无序 |
scard | 返回集合中元素的个数 |
spop | 随机返回一个元素 并将元素在集合中删除 |
smove | 从一个集合中向另一个集合移动元素 必须是同一种类型 |
srem | 从集合中删除一个元素 |
sismember | 判断一个集合中是否含有这个元素 |
srandmember | 随机返回元素 |
sdiff | 求差集 |
sinter | 求交集 |
sunion | 求和集 |
sadd 集合名 元素名
smembers 集合名
scard 集合名
sinter 集合1 集合2
6 ZSet类型
特点: 可排序的set集合 排序 不可重复 ,因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。底层的实现是一个跳表(SkipList)加 hash表。
ZSET 官方 可排序SET sortSet
1.内存模型
2.常用命令
命令 | 说明 |
---|---|
zadd | 添加一个有序集合元素 |
zcard | 返回集合的元素个数 |
zrange 升序 zrevrange 降序 | 返回一个范围内的元素 |
zrangebyscore | 按照分数查找一个范围内的元素 |
zrank | 返回排名 |
zrevrank | 倒序排名 |
zscore | 显示某一个元素的分数 |
zrem | 移除某一个元素 |
zincrby | 给某个特定元素加分 |
md-end-block
ZADD KEY_NAME SCORE1 VALUE1.. SCOREN VALUEN
zrange 集合名 开始索引 结束索引
zrange 集合名 开始索引 结束索引
7 hash类型
特点: value 是一个map结构 存在key value key 无序的
1.内存模型
2.常用命令
命令 | 说明 |
---|---|
hset | 设置一个key/value对 |
hget | 获得一个key对应的value |
hgetall | 获得所有的key/value对 |
hdel | 删除某一个key/value对 |
hexists | 判断一个key是否存在 |
hkeys | 获得所有的key |
hvals | 获得所有的value |
hmset | 设置多个key/value |
hmget | 获得多个key的value |
hsetnx | 设置一个不存在的key的值 |
hincrby | 为value进行加法运算 |
hincrbyfloat | 为value加入浮点值 |
hset 集合名 key value
hset 集合 key
四、持久化机制
client redis[内存] -----> 内存数据- 数据持久化-->磁盘
Redis官方提供了两种不同的持久化方法来将数据存储到硬盘里面分别是:
-
RDB 快照(Snapshot)
-
AOF (Append Only File) 只追加日志文件
1. RDB方式 快照(Snapshot)
1.1. 特点
这种方式可以将某一时刻的所有数据都写入硬盘中,当然这也是redis的默认开启持久化方式,保存的文件是以.rdb形式结尾的文件因此这种方式也称之为RDB方式。
1.2.快照生成方式
-
客户端方式: BGSAVE 和 SAVE指令
-
服务器配置自动触发
md-end-block
# 1.客户端方式之BGSAVE
- a.客户端可以使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时,redis会调用fork来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求。
名词解释: fork当一个进程创建子进程的时候,底层的操作系统会创建该进程的一个副本,在类unix系统中创建子进程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后,对被写入的内存的共享才会结束服务`
# 2.客户端方式之SAVE
- b.客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令
- b.客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令
- 注意: SAVE命令并不常用,使用SAVE命令在快照创建完毕之前,redis处于阻塞状态,无法对外服务
md-end-block
# 3.服务器配置方式之满足配置自动触发
- 如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令
- 如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令
-
在一定的间隔中,检测 key 的变化情况,然后持久化数据 编辑 redis.windows.conf 文件(不同版本位置可能不同)
-
save 900 1 :15分钟至少有一个 key 发生改变就持久化一次
-
save 300 10 :5分钟至少有十个 key 发生改变就持久化一次
-
save 60 10000 :1分钟至少有一万个 key 发生改变就持久化一次
-
-
假如更改了上述配置文件(不建议更改) save 900 1 save 300 10 save 10 5
-
需要使用是,就不能按上述方法正常点击 Redis 服务器端运行了:需要重新启动 Redis 服务器,并指定配置文件名称,使用命令行(Windows + R 键输入 cmd,之后打开后输入 cd /d 文件夹路径),客户端依旧双击打开 盘符:\存放目录\redis 版本号>redis-server.exe redis.windows.conf
-
之后在客户端中输入键存入值,就会在 Redis 文件夹目录中产生一个 dump.rdb 文件进行存储数据
2.AOF 只追加日志文件
2.1.特点
-
AOF :日志记录的方式,可以记录每一条命令的操作,可以在每一次命令操作后,持久化数据
- 编辑 redis.windows.conf 文件(不同版本位置可能不同)
-
appendonly no(默认关闭 aof) → appendonly yes(开启 aof)(使用时依旧需要重新启动 Redis 服务器,并指定配置文件名称,使用命令行(Windows + R 键输入 cmd,之后打开后输入 cd /d 文件夹路径),客户端依旧双击打开,进行操作后生成持久化文件:appendonly.aof)(这种操作对性能影响较大)
-
appendfsync always :(默认被注释)每一次操作都进行持久化
-
appendfsync everysec :(默认开启)每隔一秒进行一次持久化
-
appendfsync no :(默认被注释)不进行持久化
-
3. 持久化总结
两种持久化方案既可以同时使用(aof),又可以单独使用,在某种情况下也可以都不使用,具体使用那种持久化方案取决于用户的数据和应用决定。
无论使用AOF还是快照机制持久化,将数据持久化到硬盘都是有必要的,除了持久化外,用户还应该对持久化的文件进行备份(最好备份在多个不同地方)。
五 使用 Java 客户端操作 Redis
Java 客户端 Jedis Jedis :一款 Java 操作 Redis 数据库的工具
1.使用步骤
1.下载 Jedis 的 jar 包
使用 Maven 导入依赖 jar 包(注意版本的对应使用)
md-end-block
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.1</version>
</dependency>
2.使用
在开启 Redis 服务器端和客户端的前提下 Java 操作
md-end-block
@Test
public void test01(){
// 1. 获取连接
Jedis jedis = new Jedis("localhost", 6379);
// 2. 操作
jedis.set("username","zhangsan");
// 3. 关闭连接
jedis.close();
}
2.Jedis 操作各种 Redis 数据结构
-
字符串类型:String
-
set
-
get
-
md-end-block
@Test
public void test02(){
// 1. 获取连接
// 如果使用空参构造,默认值"localhost",6379端口
Jedis jedis = new Jedis();
// 2. 操作
// 存储
jedis.set("username","zhangsan");
// 获取
String username = jedis.get("username");
System.out.println(username);
// 可以使用 setex() 方法存储可以指定过期时间的 key value
jedis.setex("activecode",20,"value"); // 将 activecode:value 键值存入 redis,并且20秒后自动删除该键值对
// 可以存储有时效的激活码,验证码等
// 3. 关闭连接
jedis.close();
}
- 哈希类型 Hash:Map 格式
-
hset
-
hget
-
hgetAll
md-end-block
@Test
public void test03(){
// 1. 获取连接
// 如果使用空参构造,默认值"localhost",6379端口
Jedis jedis = new Jedis();
// 2. 操作
// 存储 Hash
jedis.hset("user","name","lisi");
jedis.hset("user","age","23");
jedis.hset("user","gender","male");
// 获取 Hash
String name=jedis.hget("user","name");
System.out.println(name);
// 获取 Hash 的所有 map 中的数据
Map<String, String> user = jedis.hgetAll("user");
Set<String> keySet = user.keySet();
for (String key :
keySet) {
// 获取 value
String value = user.get(key);
System.out.println(key+":"+value);
}
// 3. 关闭连接
jedis.close();
}
- 列表类型 List :LinkedList 格式,支持重复元素
-
lpush/rpush
-
lpop/rpop
-
lrange start end
md-end-block
@Test
public void test04(){
// 1. 获取连接
// 如果使用空参构造,默认值"localhost",6379端口
Jedis jedis = new Jedis();
// 2. 操作
// List 存储
jedis.lpush("mylist","a","b","c"); // 从左边存
jedis.rpush("mylist","a","b","c"); // 从右边存
// List 范围获取
List<String> mylist = jedis.lrange("mylist", 0, -1);
System.out.println(mylist);
// List 弹出
String element01 = jedis.lpop("mylist"); // c
System.out.println(element01);
String element02 = jedis.rpop("mylist"); // c
System.out.println(element02);
// List 范围获取
List<String> newMylist = jedis.lrange("mylist", 0, -1);
System.out.println(newMylist);
// 3. 关闭连接
jedis.close();
}
- 集合类型 Set :不允许重复元素
- sadd
md-end-block
@Test
public void test05(){
// 1. 获取连接
// 如果使用空参构造,默认值"localhost",6379端口
Jedis jedis = new Jedis();
// 2. 操作
// Set 存储
jedis.sadd("myset","java","php","c++");
// Set 获取
Set<String> myset = jedis.smembers("myset");
System.out.println(myset);
// 3. 关闭连接
jedis.close();
}
- 有序集合类型 sorted set :不允许重复元素,且元素有顺序
- zadd
md-end-block
@Test
public void test06(){
// 1. 获取连接
// 如果使用空参构造,默认值"localhost",6379端口
Jedis jedis = new Jedis();
// 2. 操作
// sorted set 存储
jedis.zadd("mysortedset",85,"张三");
jedis.zadd("mysortedset",70,"李四");
jedis.zadd("mysortedset",90,"王五");
// sorted set 获取
Set<String> mysortedset = jedis.zrange("mysortedset", 0, -1);
System.out.println(mysortedset);
// 3. 关闭连接
jedis.close();
}
3. Jedis 连接池:JedisPool
-
使用:
-
创建 JedisPool 连接池对象
-
调用方法
getResource()
方法获取 Jedis 连接
-
md-end-block
@Test
public void test07(){
// 创建一个配置对象
JedisPoolConfig config = new JedisPoolConfig();
// 设置连接池的最大数目
config.setMaxTotal(50);
//设置空闲时连接池保有最大链接数目
config.setMaxIdle(10);
// 1. 创建 Jedis 连接池对象
JedisPool jedisPool = new JedisPool(config,"localhost",6379);
// 2. 获取连接
Jedis jedis = jedisPool.getResource();
// 3. 使用
jedis.set("key","value");
// 4. 关闭,归还到连接池中
jedis.close();
}
4.Jedis 连接池工具类
- 如果是使用 Maven 框架(如果没有使用 Maven 框架,则直接在 src 目录下创建资源包),则需要在 resources 目录下新建
jedis.properties
资源包,内容如下
md-end-block
host=127.0.0.1
port=6379
maxTotal=50
maxIdle=10
- 工具类
md-end-block
public class JedisPoolUtils {
/**
* JedisPool 工具类
* 加载配置文件,配置连接池的参数
* 提供获取连接的方法
*/
private static JedisPool jedisPool;
static {
// 读取配置文件
InputStream inputStream = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
// 创建 Properties 对象
Properties properties = new Properties();
// 关联文件
try {
properties.load(inputStream);
}catch (IOException e){
e.printStackTrace();
}
// 获取数据,设置 JedisPoolConfig 中
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.parseInt((properties.getProperty("maxTotal"))));
config.setMaxIdle(Integer.parseInt((properties.getProperty("maxIdle"))));
// 初始化 JedisPool
jedisPool = new JedisPool(config, properties.getProperty("host"), Integer.parseInt(properties.getProperty("port")));
}
// 获取连接方法
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
- 测试类
md-end-block
@Test
public void test08(){
// 通过连接池工具类获取
Jedis jedis = JedisPoolUtils.getJedis();
// 使用
jedis.set("key","value");
// 关闭,归还到连接池中
jedis.close();
}
老王讲IT 性感有魅力