今日内容
- nosql系列产品之 redis(非关系型数据库)
- redis数据结构【重点】
- redis相关命令
- redis持久化机制【面试题】
- jedis【相当于jdbc,远程操作redis数据库】
第一章 NoSQL
1.NoSQL介绍
NoSQL,泛指非关系型的数据库,NoSQL即Not-Only SQL,它可以作为关系型数据库的良好补充。
为什么学习NoSQL?
互联网产品的特点:高并发、高可用、高性能、海量数据
关系型数据库与NoSQL数据库并非对立而是互补的关系,即通常情况下使用关系型数据库,在适合
使用NoSQL的时候使用NoSQL数据库,NoSQL数据库对关系型数据库的不足进行弥补。
2. NoSQL的主流产品
分类 | 特点 | 代表产品 |
键值存储 | 数据一般存在内存中,读写速度快(10w/s),适合作为缓存服务 | redis |
文档型数据库 | 数据结构要求不严格,适合存储结构不确定或者价值较低的数据 | mongdb |
列存储数据库 | 查找速度快,更容易进行分布式扩展,适合作为文件存储服务 | Hbase |
图形数据库 | 使用“图结构”进行存储,适合做社交网络计算等等 | Neo4j |
图形数据库介绍
关系数据库,只需要学习一套SQL规范,就可以操作几乎所有关系数据库
非关系型数据库,每一种产品都是独立的,比如进行学会了redis、mongodb
第二章 Redis
1. Redis介绍
Redis(Remote Dictionary Server)是用C语言开发的一个开源的高性能键值对数据库。它的所有数据都是保存在内存中的,这也就决定了其读写速度之快,是其它硬盘保存数据的系统所无法匹敌的。
官方曾经给出过一组测试数据,50个并发执行100000个请求: 读的速度是110000次/s,写的速度是81000次/s
2. Redis服务器安装和使用
下载
- Reids官网地址:http://redis.io
- 中文网地址:https://www.redis.net.cn/
- GitHub地址:https://github.com/MSOpenTech/redis/tags
安装
windows绿色版,解压即用
目录
文件 | 作用 |
redis.windows.conf | 核心配置文件 |
redis-benchmark.exe | |
redis-check-aof.exe | |
redis-check-dump.exe | |
redis-cli.exe | redis命令行客户端 |
redis-server.exe | 启动redis数据库服务 |
目录或文件 | 作用 |
redis-benchmark | 性能测试工具 |
redis-check-aof | AOF文件修复工具 |
redis-check-dump | RDB文件检查工具(快照持久化文件) |
redis-cli | 命令行客户端 |
redis-server | 启动redis服务器 |
redis.windows.conf | redis核心配置文件 |
启动
windows平台使用
[16552] 15 Sep 17:52:39.930 # Warning: no config file specified, using the default config. In order to specify a config file use D:\develop\Redis-x64-3.0.503\redis-server.exe /path/to/redis.conf
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.0.503 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 16552
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
[16552] 15 Sep 17:52:39.935 # Server started, Redis version 3.0.503
[16552] 15 Sep 17:52:39.935 * DB loaded from disk: 0.000 seconds
[16552] 15 Sep 17:52:39.935 * The server is now ready to accept connections on port 6379
linux平台使用
* 在当前解压后的目录下 cmd进入dos窗口
先启动 redis-server.exe redis.windows.conf
再启动 redis-cli.exe
3. Redis数据结构【重点】
Redis采用的是键值对存储,键的类型只能为字符串,值支持五种数据类型:
- 字符串:String
- 哈希:HashMap
- 双向链表:LinkedList
- 无序集合:HashSet
- 有序集合:LinkedHashSet
4. Redis命令操作
Redis命令是用来操作Redis数据库的, 就相当于操作MySql数据库时的SQL语句。
Redis的命令根据要操作的值的数据结构的不同而不同, 每种数据类型都有自己的操作命令
4.1 String 字符串【重点】
字符串类型是Redis中最为基础的数据存储类型。
在Redis中字符串类型的Value最多可以容纳的数据长度是512m。
* 新增(更新)
set key "value"
注意:value值内容有空格,外面需要加引号
* 查询
get key
* 删除
del key
* 新增并指定存活时间
setex key seconds value
ttl key 查看存活时间
* 根据键判断记录是否存在
exists key
* 主键自增(类似于MySQL中的,auto_increment)
set id 1
incr id
新增(修改)
127.0.0.1:6379> set mystr mryhl
OK
查询
127.0.0.1:6379> get mystr
"mryhl"
删除
127.0.0.1:6379> del mystr1
(integer) 1
新增并指定存活时间
127.0.0.1:6379> setex sms_code 10 234534
OK
查看存活时间
127.0.0.1:6379> ttl sms_code
(integer) 1
127.0.0.1:6379> ttl sms_code
(integer) -2
根据键判断记录是否存在
127.0.0.1:6379> exists sms_code
(integer) 0
127.0.0.1:6379> setex sms_code 10 234534
OK
127.0.0.1:6379> exists sms_code
(integer) 1
自增主键
127.0.0.1:6379> set id 1
OK
127.0.0.1:6379> incr id
(integer) 2
127.0.0.1:6379> incr id
(integer) 3
4.2 Hash 哈希
Hash类型极其类似于java中的Map,值里面可以存放一组组的键值对
该类型非常适合于存储java中对象的信息
* 新增(更新)
hset key hkey hvalue
* 查询
hget key hkey 查询具体元素
hgetall key 查询所有元素
* 删除
hdel key hkey 删除指定元素
del key 删除整个hash
新增、更新
127.0.0.1:6379> hset user_1 id 1
(integer) 1
127.0.0.1:6379> hset user_1 name tom
(integer) 1
127.0.0.1:6379> hset user_1 age 18
(integer) 1
查询
127.0.0.1:6379> hget user_1 name
"tom"
查询所有
127.0.0.1:6379> hgetall user_1
1) "id"
2) "1"
3) "name"
4) "tom"
5) "age"
6) "18"
删除
127.0.0.1:6379> hdel user_1 age
(integer) 1
127.0.0.1:6379> hgetall user_1
1) "id"
2) "1"
3) "name"
4) "tom"
4.3 List 列表
List类型底层是一个双向字符串链表。里面的元素是有序的,可重复的
我们可以从链表的任何一端进行元素的增删
新增:
lpush key value 从左侧顶端添加元素
rpush key value 从右侧顶端添加元素
查询:
lrange key start end
0-1(查询所有)
删除:
1pop key 从左侧弹出一个元素
rpop key 从右侧弹出一个元素
127.0.0.1:6379> lpush mylist a
(integer) 1
127.0.0.1:6379> lpush mylist b
(integer) 2
127.0.0.1:6379> lpush mylist c
(integer) 3
127.0.0.1:6379> rpush mylist d
(integer) 4
查询
127.0.0.1:6379> lrange mylist 0 -1
1) "c"
2) "b"
3) "a"
4) "d"
删除
127.0.0.1:6379> lpop mylist
"c"
127.0.0.1:6379> rpop mylist
"d"
补充:如果插入顺序和查询顺序一致,请使用rpush添加元素
4.4 Set 集合(无序)
Set类型底层是一张hash表。里面的元素是无序的,不可重复的
* 新增
sadd key value
* 查询
smembers key
* 删除
srem key value
新增
127.0.0.1:6379> sadd myset timo
(integer) 1
127.0.0.1:6379> sadd myset jack
(integer) 1
127.0.0.1:6379> sadd myset lucy
(integer) 1
查询
127.0.0.1:6379> smembers myset
1) "jack"
2) "lucy"
3) "timo"
删除
127.0.0.1:6379> srem myset anni
(integer) 0
127.0.0.1:6379> srem myset jack
(integer) 1
127.0.0.1:6379> smembers myset
1) "lucy"
2) "timo"
4.5 ZSet 集合(有序)
Zset,也称sortedSet, 在Set的基础上,加入了有序功能,在添加元素的时候,允许指定一个分数,它会按照这个分数排序
* 新增
zadd key 分值 value
* 查询
zrange key start end [withscores] 升序
zrevrange key start end [withscores] 降序
* 删除
zrem key value
新增
127.0.0.1:6379> zadd myzset 56 tom
(integer) 1
127.0.0.1:6379> zadd myzset 20 haley
(integer) 1
127.0.0.1:6379> zadd myzset 2 jek
(integer) 1
查询
127.0.0.1:6379> zrange myzset 0 -1
1) "jek"
2) "haley"
3) "tom"
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "jek"
2) "2"
3) "haley"
4) "20"
5) "tom"
6) "56"
倒序
127.0.0.1:6379> zrevrange myzset 0 -1 withscores
1) "tom"
2) "56"
3) "haley"
4) "20"
5) "jek"
6) "2"
删除
127.0.0.1:6379> zrem myzset jek
(integer) 1
127.0.0.1:6379> zrevrange myzset 0 -1 withscores
1) "tom"
2) "56"
3) "haley"
4) "20"
4.6 通用命令
* 模糊查询键
keys *
* 删除多个键
del key [key] [key]
* 根据键判断值类型
type key
* 选择数据库
select 库名[0~15]
* 清空当前数据库
flushdb
* 清空所有数据库
flushall
5.Redis持久化【面试题】
Redis的数据都是存在在内存之中的,那么这样一旦出现宕机,势必会导致数据的丢失,这就需要持久化操作,也就是要将redis在内存中的数据写到硬盘上保存。
注意:redis虽然有持久化操作,但是其全部数据依旧都在内存中存在,也就是说硬盘上的只是为了安全和备份。
Redis提供了两种数据持久化的方式,分别是RDB和AOF。
RDB:默认开启,不需要配置
* 手动持久化【了解】
bgsave
* 自动持久化
在redis运行期间,根据指定时间规则,将内存的数据集进行快照拍摄,持久化到硬盘 【dump.rdb】
在redis.windows.conf配置文件中,可以查看(修改)时间规则
save 900 1
save 300 10
save 60 10000
################################ SNAPSHOTTING ################################
#
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# 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
#
# Note: you can disable saving completely by commenting out all "save" lines.
#
# It is also possible to remove all the previously configured save
# points by adding a save directive with a single empty string argument
# like in the following example:
#
# save ""
save 900 1
save 300 10
save 60 10000
AOF:默认关闭,需手动开启
* 在redis运行期间,以日志记录方式监控写操作,持久化到硬盘【appendonly.aof】
* 在redis.windows.conf配置文件中开启
appendonly no --> appendonly yes
* 三种日志监控规则
# appendfsync always 每次(写操作)修改时,进行持久化
appendfsync everysec 每秒,持久化一次
# appendfsync no 在CPU空闲期,进行持久化
RDB和AOF二种持久化机制可以同时存在
在开发中使用哪种机制进行持久化?
* RDB:应用在缓存服务器场景
优点:性能高,降低磁盘IO
缺点:redis容灾后,容易丢失数据
* AOF:应用在数据库服务器场景
优点:不容易丢失数据(日志)
缺点:速度稍慢(能够秒杀mysql等产品的...)
6 应用场景
- 缓存【重点】
- 秒杀
- 微博热搜
- 分布式session
- 数据过期处理
第三章 Jedis【重点】
Redis作为一款优秀的缓存服务器存在,大多数语言都提供了连接Redis的驱动包,在java中,比较出名的是Jedis和Redisson,我们今天以Jedis为例学习,看看如何是用程序操作redis。
1 Jedis使用
常用API
方法 | 解释 |
new Jedis(host, port) | 创建jedis对象,参数host是redis服务器地址,参数port是redis服务端口 |
set(key,value) | 设置字符串类型的数据 |
get(key) | 获得字符串类型的数据 |
hset(key,field,value) | 设置哈希类型的数据 |
hget(key,field) | 获得哈希类型的数据 |
lpush(key,values) | 设置列表类型的数据 |
lpop(key) | 列表左面弹栈 |
rpop(key) | 列表右面弹栈 |
del(key) | 删除指定的key |
快速入门
① 导入相关坐标【已完成】
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
maven官方提供坐标搜索仓库:https://mvnrepository.com/
② 编写代码
public class JedisTest {
@Test
public void test01()throws Exception{
// 1.创建jedis连接对象
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 2.调用set方法
jedis.set("mystr", "传智播客");
// 3.释放资源
jedis.close();
}
@Test
public void test02()throws Exception{
// 1.创建jedis连接对象
Jedis jedis = new Jedis();
// 2.调用get方法
System.out.println(jedis.get("mystr"));
// 3.释放资源
jedis.close();
}
}
2. Jedis连接池
jedis连接资源的创建与销毁是非常消耗性能的,所以我们不希望频繁的创建和销毁它.基于这样的需求,就有了jedisPool技术。
快速入门
public class JedisPoolTest {
@Test
public void test01() throws Exception {
// 1.创建连接池对象
JedisPool jedisPool = new JedisPool("127.0.0.1", 6379);
// 2.从池中获取连接
Jedis jedis = jedisPool.getResource();
// 3.操作api实现CRUD
jedis.setex("sms_code", 300, "996571");
// 4.归还到连接池
jedis.close(); // 底层使用了动态代理,进行增强
}
@Test
public void test02() throws Exception {
// 指定连接池配置参数
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(50); // 最大连接数
config.setMinIdle(10); // 空闲期,保留连接数
config.setMaxWaitMillis(3000);// 等待时间
// 1.创建连接池对象
JedisPool jedisPool = new JedisPool(config, "127.0.0.1", 6379);
// 2.从池中获取连接
Jedis jedis = jedisPool.getResource();
// 3.操作api实现CRUD
System.out.println(jedis.get("sms_code"));
// 4.归还到连接池
jedis.close(); // 底层使用了动态代理,进行增强
}
}
连接池工具栏
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;
import java.util.ResourceBundle;
/*
* jedis工具类
* */
public class JedisUtils {
private static JedisPool jedisPool;
private static String host;
private static Integer port;
private static Integer maxTotal;
private static Integer maxIdle;
// 初始化连接池
static {
try {
ResourceBundle jedis = ResourceBundle.getBundle("jedis");
// 读取配置文件给变量赋值
// 获取类加载读取 jedis.properties 获取io流
InputStream is = JedisUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
// 创建properties对象 加载io流
Properties properties = new Properties();
properties.load(is);
// 给变量赋值
host = properties.getProperty("jedis.host");
port = Integer.parseInt(properties.getProperty("jedis.port"));
maxTotal = Integer.parseInt(properties.getProperty("jedis.maxTotal"));
maxIdle = Integer.parseInt(properties.getProperty("jedis.maxIdle"));
// 创建连接池配置对象
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxTotal);
jedisPoolConfig.setMaxIdle(maxIdle);
// 创建连接池对象
jedisPool = new JedisPool(jedisPoolConfig, host, port);
} catch (IOException e) {
e.printStackTrace();
}
}
// 提供获取jedis连接的方法
public static Jedis getJedis() {
return jedisPool.getResource();
}
}
3. 注意事项
在启动项目时,或访问需求是,控制台报错了,连接reids超时,基本只有一个原因,redis没启动成功