1. NoSQL的概叙
1.1 什么是NoSQL?
1. NoSQL = Not Only SQL
2. 非关系型的数据库
1.2 为什么需要NoSQL?
1. High Performance - 高并发读写
2. Huge Storage - 海量数据的高效率存储和访问
3. High Scalability && High Availability - 高可扩展性和高可实用性
1.3 NoSQL数据库的四大分类
1. 键值(key-value)存储
例如:Redis 优势:快速查询 劣势:存储的数据缺少结构化
2. 列存储
例如:HBase 优势:查找速度比较快,扩展性比较强。 劣势:功能相对于局限
3. 文档数据库
例如:MongoDB 优势:数据结构要求不是特别的严格 劣势:查询性能不是特别高,缺少统一查找的语法
4. 图形数据库
例如:InfoGrid 主要应用于社交网络上面 优势:利用图结构相关的算法 劣势:需要对整个图做计算才能得出结果,
不容易做分布式的方案。
1.4 NoSQL的特点
1. 易扩展:数据之间没有关系,容易扩展
2. 灵活的数据模型: 对于大数据量和高性能的读写
3. 大数据量,高性能
4. 高可用
2. Redis的概叙
2.1 高性能键值对数据库,支持的键值数据类型:
1. 字符串类型(String)
2. 列表类型(list)
3. 有序集合类型(sorted set)
4. 散列类型(Hash)
5. 集合类型(sets)
Redis读的速度11W/秒,写的速度81000/秒。
2.2 Redis的应用场景
1. 缓存(比如数据的查询,比如新闻商品的内容)
2. 任务队列(秒杀抢购等等)
3. 网站访问的统计
4. 数据过期处理(可以精确到毫秒)
5. 应用排行榜
6. 分布式集群架构中的session分离
3. Redis的安装和使用
4. Jedis的入门
Jedis是Redis官方首选的Java客户端开发包。
导入jedis的jar包 和 连接池jar包 , 然后连接redis的服务器。使用cmd: redis-server.exe redis.windows.conf
远程连接:redis-cli.exe -h 127.0.0.1 -p 6379
写两个简单的demo
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisDemo1 {
@Test
/**
* 单实例的测试
*/
public void test(){
//1.设置IP地址和端口
Jedis jedis = new Jedis("127.0.0.1",6379);
//2.保存数据
jedis.set("falg", "hubbert");
//3.获取数据
String value = jedis.get("falg");
System.out.println(value);
//4.释放资源
jedis.close();
}
@Test
/*
*使用连接池的方式来连接
*/
public void testPool(){
//1.获得连接池的配置对象;
JedisPoolConfig config = new JedisPoolConfig();
//2.设置最大连接数
config.setMaxTotal(30);
//3.设置最大空闲连接数
config.setMaxIdle(30);
//4.获得连接池
JedisPool jedisPool = new JedisPool(config,"127.0.0.1",6379);
//5.获得核心对象
Jedis jedis = null;
try{
//获得连接池获得连接
jedis = jedisPool.getResource();
jedis.set("name", "hubbert");
String value = jedis.get("name");
System.out.println(value);
}catch(Exception e){
e.printStackTrace();
}finally{
if(jedis!=null){
jedis.close();
}
if(jedisPool != null ){
jedisPool.close();
}
}
}
}
5. Redis的数据类型
key定义的注意点:
1. 不要定义过长: 最好不要超过1024个字节,这不仅会消耗内存,还会降低查找的效率
2. 统一的命名规范
5.1 存储String
二进制安全的,存入和获取的数据相同。
value最多容纳数据的长度512M。
5.1.2 存储String常用命令:
1. 赋值
set key value
2. 删除
del key
nil 代表数值不存在。
3. 取值
get key
getset key value : 先获取key的值,再重新设置value。
如图所示:
4. 数值增减
incr key 将指定key的value值递增1
decr key 将指定key的value值减1
当值不为数字,则会报错。
5. 扩展命令
incrby key increment(对key的值增加指定的increment数字)
decrby key decrement(对key的值减少指定的decrement数字)
append key value(对key的值直接像加字符串一样加上value的值:例如:3 ,append 5之后为 : 35)
5.2存储Hash
5.2.1 存储Hash常用命令
![](https://i-blog.csdnimg.cn/blog_migrate/98e0f0cfb9f6c4aea2042481692ced84.png)
![](https://i-blog.csdnimg.cn/blog_migrate/689c183891152b68c0c6ac75205c5b8a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a44742d3d7cde362921d648e378bdff5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/605a4849315e0bb0c67835f5923390ed.png)
![](https://i-blog.csdnimg.cn/blog_migrate/aa1078d37e69a87014a3110264d0c024.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9445e83a68c051603e41c6d23c786b74.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a293fe868197cbeefa7def77133ebb6d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/067493ca23fc1e7671a622eaac09bef4.png)
5.4 hvals key(获得hash中所有的value值)
例如:hvals myhash
5.3存储list
存储list常用命令:
1. 两端添加
1.1 lpush key value[value.....](从左边插入元素)
例如: lpush mylist a b c
1.2 rpush key value[value...](从右边插入元素)
例如:rpush mylist 1 2 3
2. 查看列表
lrange key start stop(查看某个list中起始位置到终止位置,-1表示倒数第一个位置,以此类推)
3. 两端弹出
3.1 lpop key(从list左边弹出)
3.2 rpop key(从list右边弹出)
4. 获取列表元素个数
llen key(获取list元素的个数)
5. 扩展命令
5.1 lpushx key value(向指定的list中左边插入元素,如果没有该list,则不会插入,有则插入)
5.2 rpushx key value(跟lpushx相反)
5.3 lrem key count value(从左向右,删除count个value值)
例如:lrem mylist3 2 3 //从左边开始删除两个3
lrem mylist3 -2 2 //从右边开始删除两个2
lrem mylist3 0 1 //删除所有的1
如下图所示:
5.4 lset key index value (往某一list的index插入value值)
5.5 linsert key BEFORE | AFTER pivot value (在某个值前|后插入某个值)
例如: linsert mylist4 AFTER b 456 //往mylist4中的b后面插入456,如下图所示:
5.6 rpoplpush source destination(从 source的右边弹出的值插入到destination的左边)
例如:rpoplpush mylist5 mylist6 //从mylist5的右边弹出一个值插入到mylist6的左边
rpoplpush的使用场景:
redis链表经常用于消息队列,来完成多个程序之间的一个消息的交互,那么假设一个应用程序正在执行lpush,向链表中添加新的元素,我们通常将这样的程序称之为“生产者”,另外一个程序正在执行rpop操作,从链表中取出元素,我们称之为“消费者”,与此同时,消费者程序在取出元素后立刻崩溃,由于该消息已经被取出,且没有被正常处理,那么我们就可以任务这个消息已经丢失了,那么由此可能会导致业务数据的丢失,或者是业务状态的不一致等现象的发生,然而可以通过rpoplpush这个命令,消费者程序在消息队列中取出元素之后,再将他插入到一个备份的队列当中,直到我们的消费者程序完成,正常的处理后,再将消息从备份队列中删除,这样我们可以提供一个守护的线程,当发现备份队列的消息过期的时候,可以将它放回主消息的队列当中,以便其他的消费者可以继续使用。
5.4 存储set
set中常用命令:
1.添加/删除元素
sadd key member[member...](添加key集合中元素,不能重复)
srem key member[member...] (删除key集合中指定的元素)
2.获得集合中的元素
smembers key(获得集合中的元素)
sismember key member(判断集合中的某一个值是否存在,不存在返回0,存在返回1)
3.集合中的差集运算
返回两个集合当中相差的成员。与key的顺序是有关系的
sdiff key [key...](差集运算)
4.集合中的交集运算
sinter key[key...](并集运算)
5.集合中的并集运算
sunion key[key...]
6.扩展的命令
scard key(得到集合的具体数量)
srandmember key [count](随机返回key集合中count个值)
sdiffstore destination key[key...](将key集合中的差集存储到desination集合中去)
sinterstore destination key[key...](将key集合中的交集存储到desination集合中去)
sunionstore destination key[key...](将key集合中的并集存储到desination集合中去)
set使用场景:
1. 跟踪一些唯一性数据
2. 用于维护数据对象之间的关联关系
使用这个redis-set数据类型,跟踪一些唯一性数据,比如说访问某一博客的唯一IP地址信息,对于这种场景仅需要在每一次访问该博客的时候,将访问者的IP存入到redis当中,然后set数据类型就会自动保证这个IP地址的唯一性。
可以用于维护数据对象之间的关联关系,比如我们所有购买某一电子产品的客户的IP存储到指定的set当中,二购买另一钟电子产品的客户IP被存储到另外的一个set当中,如果此时我们想获取有哪些客户同时购买了这两种电子产品,那么这时候就可以使用交集操作sinter即可。
5.5 存储Sorted-Set
他们都是字符串的一个集合,都不允许重复的成员出现在同一个set当中。
Sorted-Set 和 Set 的区别:Sorted-Set的每一个成员都会有一个分数与之关联,redis正是通过这个分数来为集合中的成员进行从小到大的排序。然而需要指出的是,尽管sorted-set的成员必须是唯一的,但是分数是可以重复的。那么在sorted-set中添加,删除,更新,一个成员,都是非常快速的操作,时间复杂度为n(logn),由于sorted-set的成员在集合是有序的,因此即便是访问与集合中的成员也是非常高效。redis具有的这个特征,在其他类型的数据库中,都是很难实现的。
主要运用于,游戏的排名上,微博的热点话题。
存储Sorted-Set的常用命令:
1. 添加元素
zadd key [NX|XX] [CH] [INCR] score member [score member...](添加某个set中分数+名字)
2. 获得元素
2.1 zscore key member (获取集合中名字的分数)
2.2 zcard key (获取集合中的个数)
3. 删除元素
zrem key member[member...](删除某个集合中的名字)
4. 范围查询
4.1 zrange key start stop [WITHSCORES](从集合中的范围查询)
从上图可知是从小到大排序
4.2 zrevrange key start stop [WITHSCORES]
通过范围进行删除:
4.3 zremrangebyrank key start stop
通过分数范围进行删除:
4.4 zremrangebyscore key min max
5. 扩展命令
5.1 zrangebyscore key min max [WITHSCORES] [LIMIT offset count](从某个集合中的分数范围获取)
min - max 分数范围
limit 取多少个个数
6. Keys的通用操作
(1)所有键列:keys *
(2)指定开头键列:keys [*]?
(3)删:del 键...
(4)判断存在:exists 键
(5)重命名:rename 旧键名 新键名
(6)设过期时间:expire 键 [seconds]
(7)查过期时间:ttl 键
(8)键的值类型:type 键
(9)清空缓存:flushall
7. Redis的特性
相关特性:
1. 多数据库
2. Redis事务
Redis一个实例包含多个数据库:默认16个客户端默认连接0号数据库
select 1 // 选择1号数据库
move name 1 // 移动 name 到1号数据库
----------------------
multi:开启事务
exec:提交,执行的命令被原子化执行
discard:回滚
8. Redis的持久化
redis的高性能是所有的数据都存储在内存当中。为了使redis重启之后,仍然保证数据不丢失,那么就需要将数据从内存当中存入到硬盘里,这个过程就是持久化的操作。
redis持久化有两种方式:
8.1 RDB方式
默认支持,不需要进行配置,在指定的时间间隔内,将数据集快照写入到磁盘,就是说我们给他指定多少秒,30秒,或者几秒,那么我们多久将这些数据写入到磁盘一次。
优势:
只有一个文件,时间间隔的数据,可以归档为一个文件,方便压缩转移(就一个文件)
1. 数据库只包含一个文件,通过文件备份策略,定期配置,恢复系统灾难:
整个redis的数据库将会只包含一个文件,那么这对于我们文件备份而言是完美的,比如说你可能打算每个小时归档一次最近24小时的一个数据,同时还要每天归档一次最近30天的数据,那么可以通过这样的备份策略,一旦系统出现灾难性的故障,我们可以非常容易地进行恢复。
2. 压缩文件转移到其他介质上:
对于灾难恢复而言,RDB是非常不错的选择,因为我们可以轻松的将一个单独的文件压缩后再将它转移到其他的存储介质上,就比如说我们可以把它拷贝走,然后恢复的时候再拷贝回来。
3. 性能最大化,redis开始持久化时,分叉出进程,由子进程完成持久化的工作,避免服务器进程执行I/O操作,启动效率高:
性能最大化,对于redis的服务进程而言,在开始持久化的时候,它唯一需要做的只是分叉出一些进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务器进程执行IO的操作,相比AOF的机制,如果数据集很大,RDB这种启动的效率会更高。
劣势:
如果宕机,数据损失比较大,因为它是没一个时间段进行持久化操作的。也就是积攒的数据比较多,一旦懵逼,就彻底懵逼了
1. 无法高可用:系统一定在定时持久化之前宕机,数据还没写入,数据已经丢失:
如果想保证数据的高可用性,就是最大限度避免数据的丢失,那么RDB不是一个很好的选择。因为系统一定在定时持久化之前,出现一些奔溃的情况,那么它还没来得及往硬盘上写入数据,数据就丢失了,比如说,我们30s写入硬盘一次,当到了25s的时候,可能服务器奔溃了,那么这前25秒的数据就丢失了。
2. 通过fock分叉子进程完成工作,数据集大的时候,服务器需要停止几百毫秒甚至1秒
RDB的配置:
在redis.window.conf中:
save 900 1 的意思是:
每900秒,就是15分钟,至少有一个Key发生变化,那么这个时候会持久化一次。往硬盘写入一次。
--------------------------------------------------------------------------------------
这里是数据保存文件名。
------------------------------------------------------------------------------------------------
这里是保存的路径,dir./ 就是在当前的路径下。
8.2 AOF方式
优势:
1. 带来更高的数据安全性。有三种同步策略。每秒同步、每修改同步、不同步。
事实上,“每秒同步”也是异步完成的,它的效率也是非常高的,所差的是,一旦系统出现宕机的现象,那么这一秒钟的数据就被丢失了,而“每修改同步”可以将其视为可同步持久化,就是在每一次发生数据的变化,都会被立即的记录到磁盘当中,虽然效率是最低的,但是是最安全的。
2. AOF 文件是一个只进行追加操作的日志文件,因此在写入过程中即使出现宕机现象也不影响之前已经存在的内容。
然而要是此次操作只写入了一半的数据,就出现了系统奔溃的问题,那么这种问题不用担心,在redis下一次启动之前,可以通过redis-check-aof这个工具来解决数据一致性的问题。
3. 如果日志过大,redis可以自动启动重写机制,redis会以append模式不断将修改的数据写入到老的磁盘文件当中,同时redis还会创建一个新的文件用于记录此期间产生了哪些修改命令被执行了,那么因此在进行重写切换的时候,可以更好的保证数据的安全性。
4. AOF包含一个格式非常清晰,易于理解的日志文件,用于记录所有的修改操作,我们可以通过这个文件来完成数据重建
劣势:
1. 对于相同数据量的数据集而言,aof这个文件比RDB文件要大一些。
2. 根据同步策略的不同,AOF在运行效率上往往会低于RDB。
因为AOF操作中,每修改就同步到硬盘上,所以效率没有RDB高。
配置:
appendonly no #AOF方式默认关闭
appendfilename appendonly.aof #配置文件#
appendfsync always #每修改一次,同步到磁盘上
appendsync everysec 每秒同步到磁盘一次
appensync no 不同步
实践打开AOF:(上面要改成下面所示:)
appendonly yes
appendfsync always