Redis从入门到阿里

1.Nosql讲解
(1)Nosql概述
①我们现在处于大数据时代
②90年代,一个基本的网站访问量不会太大,单个数据库就完全足够使用,那个时候,更多的是使用静态网页Html,所以服务器根本没有太大的压力
③这种情况下,整个网站的瓶颈是什么?
1)数据量如果太大,一个机器完全放不下
2)当数据的索引(Mysql使用B+Tree)很大时,机器的内存也不够用
3)访问量(读写混合)太大,一个服务器完全承受不了…
只要开始出现了这三种情况,就必须晋级…
(2)Memcached(缓存) + Mysql(免费) + 垂直拆分(读写分离)
①网站80%的情况下都是在执行读取操作,每次都要去查询数据库的话就会十分麻烦,而且耗费大量时间,所以说我们希望可以减轻数据库的压力,于是可以使用缓存机制来保证效率!
②发展过程: 优化Mysql底层的数据结构和索引----->文件缓存(IO)----->Memcached(当时最热门的缓存技术)
(3)分库分表 + 水平拆分 + Mysql集群
①技术和业务在发展的同时,对人的要求也越来越高
②数据库的本质: 读 + 写
③早些年使用MyISAM: 表锁,十分影响效率,在高并发下就会出现严重的问题(锁定表)
之后转战Innodb: 行锁(锁定行)
慢慢的就开始使用分库分表来解决写的压力
Mysql在那个年代推出了表分区,但是并没有多少公司使用,之后Mysql推出了集群,这个就很好的满足了那个年代的很多需求
④如今的年代,Mysql等关系型数据库就不够用了,数据量很多,变化很快
有的利用Mysql来存储一些比较大的文件(比如博客),图片 等,这样数据库表就很大,访问时效率较低
如果有一种数据库来专门处理这种数据的话,那么Mysql 的压力就会变得很小(我们现在研究的就是如何处理这些 问题)
(4)为什么要使用Nosql
①如今时代的高速发展,用户的个人信息、社交网络、地理位置、用户自己产生的数据、用户日志等爆发式增长
Mysql等关系型数据库已经不实用了,这个时候我们就需要使用Nosql数据库(非关系型数据库),Nosql数据库可以很好的处理这些情况
(5)Nosql的概念
①Nosql = Not only SQL (不仅仅是sql,泛指非关系型数据库)
②随着web2.0互联网的诞生,传统的关系型数据库很难对付web2.0时代,尤其是大规模的、高并发的社区,这样就会暴露出来很多难以克服的问题,Nosql在当今大数据环境下发展的非常迅速,是我们必须要掌握的一门技术!
③很多的数据类型(用户的个人信息、社交网络、地理位置、用户自己产生的数据、用户日志等)的存储不需要一个固定的格式,不需要多余的操作就可以实现横向扩展(多个用户同时操作)
④Nosql的特点
1)方便扩展(数据之间没有关系,耦合性低,很好扩展)
2)大数据量、高性能(Redis一秒可以写8万次,读取11万次,Nosql是一种细粒度的缓存,性能会比较高)
3)数据类型是多样性的(不需要事先设计数据库,随取随用,一般数据量比较大的表,很多人根本无法设计出来)
4)传统的关系型数据库和NoSQL的区别
a.传统的关系型数据库RDBMS
a)结构化组织(行和列)
b)结构化SQL查询
c)数据和关系都定义在单独的表中
d)数据操作语言,数据定义语言…
e)基础的事务
f)严格的一致性(任何时候都要求一致)
b.Nosql
a)不仅仅是数据
b)没有固定的查询语言
c)键值对存储、列存储、文档存储、图形数据库(社交关系)
d)最终一致性(只要求结果一致)
e)CAP定理和BASE理论
f)高性能、高可用、高扩展(三高)
c.了解: 3v + 3高
a)3v—主要是描述问题的
i.海量Volume
ii.多样Variety
iii.实时Velocity
b)3高—主要是对程序的要求(即解决问题)
i.高性能
ii.高并发
iii.高可扩
d.真正在公司中的实践: NoSQL + RDBMS一起使用才是最强的
2.阿里巴巴架构演进
(1)思考: 这么多东西难道都是放在一个数据库当中的吗
Redis从入门到阿里_第1张图片

(2)开源才是技术的王道
任何一家互联网公司,都不可能只是简简单单的让用户能用就好了
大量公司做的都是相同的业务,随着这样的竞争,业务是越来越完善,然后对开发者的要求也是越来越高
(3)要知道,一个简单的网页背后的技术一定不是大家所想的那么简单
大型互联网存在的问题:
数据类型太多
数据源繁多,经常需要重构
数据经常需要大面积的改造
解决方法:
Redis从入门到阿里_第2张图片

Redis从入门到阿里_第3张图片
Redis从入门到阿里_第4张图片

在这里插入图片描述
Redis从入门到阿里_第5张图片

以上都是Nosql入门概述,不仅能够提高知识,还可以帮 助我们了解大厂的工作内容.
3.Nosql四大分类
(1)KV键值对
①新浪: Redis(用C语言编写的,单线程的)
②美团: Redis + Tair
③阿里、百度: Redis + Memcache
(2)文档型数据库(bson格式,和json类似)
①MongoDB(一般必须要掌握)
1)MongoDB是一个基于分布式文件存储的数据库,主要用来处理大量的文档,用c++编写的
2)MongoDB是一个介于关系型数据库和非关系型数据库中间的产品,MongoDB是非关系型数据库当中功能最丰富、最像关系型数据库的
(3)列存储数据库
①HBase
②分布式文件系统
(4)图形关系数据库
①它不是用来存图形的,存放的是关系,比如: 社交网络、广告推荐
Redis从入门到阿里_第6张图片

4.Redis入门
(1)Redis是什么
①Redis(Remote Dictionary Server ),即远程字典服务
②是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
③免费和开源
是当下最热门的Nosql技术之一,也被人们称之为结构化 数据库
④redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步
Redis从入门到阿里_第7张图片


(2)Redis能干嘛
①内存存储、持久化(内存中是断电即失,所以说持久化很重要)
②效率高,可以用于高速缓存
③发布订阅系统(即一些简单的消息队列操作)
④地图信息分析
⑤计时器、计数器(比如: 某条信息的浏览量)
⑥…
(3)Redis的特性
①多样的数据类型
②持久化
③集群
④事务
⑤…
5.Redis安装(windows & linux)
(1)注意: Windows在GitHub上下载(已经停更很久了)
(2)Redis推荐都是在Linux服务器上搭建的,所以我们都是基于linux的Redis学习
(3)Redis解压目录
Redis从入门到阿里_第8张图片

启动Redis
Redis从入门到阿里_第9张图片

使用客户端连接Redis
Redis从入门到阿里_第10张图片

Windows下使用Redis确实简单,但是推荐使用Linux去开发 使用Redis
(4)linux下安装Redis
①将Redis安装包发送到home目录下的redis文件夹
②将安装包移动到/opt文件夹目录下
1)mv redis-5.0.7.tar.gz /opt
③解压
1)tar -zxvf redis-5.0.7.tar.gz
④得到的Redis文件
在这里插入图片描述

⑤进入Redis解压后的文件
在这里插入图片描述

⑥基本的环境安装
1)yum install gcc-c++
2)make
Redis从入门到阿里_第11张图片
Redis从入门到阿里_第12张图片

3)make install (只是一个确认命令)

4)Redis默认的安装路径: /usr/local/bin/
Redis从入门到阿里_第13张图片

5)移动配置文件,避免因为更改配置文件内容后对其产生影响
在这里插入图片描述

6)Redis默认不是后台启动的,修改配置文件使其后台启动
Redis从入门到阿里_第14张图片

7)启动Redis服务(通过指定的配置文件启动)
在这里插入图片描述

8)测试是否成功–使用Redis客户端进行连接
Redis从入门到阿里_第15张图片

9)查看redis的进程是否开启
ps -ef|grep redis: 查看此时开启的进程
Redis从入门到阿里_第16张图片

10)如何关闭Redis服务: shutdown exit
Redis从入门到阿里_第17张图片
在这里插入图片描述

11)后面我们会使用单机多Redis启动集群测试

12)测试性能
a.redis-benchmark 是一个压力测试工具
b.官方自带的性能测试工具
c.使用: redis-benchmark 命令参数
Redis从入门到阿里_第18张图片

简单测试一下:
测试: 100个并发连接,100000个请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
Redis从入门到阿里_第19张图片

Redis从入门到阿里_第20张图片

6.Redis的基础知识说明
(1)Redis默认有16个数据库
Redis从入门到阿里_第21张图片

默认使用的是第0个数据库
可以使用select进行切换数据库
在这里插入图片描述

查看数据库大小
在这里插入图片描述
Redis从入门到阿里_第22张图片

不同的数据库可以存放不同的值
Redis从入门到阿里_第23张图片

查看数据库所有的key
在这里插入图片描述

清除当前数据库
在这里插入图片描述

清除所有数据库的内容
Redis从入门到阿里_第24张图片

(2)Redis是单线程的
①Redis其实是很快的,官方表示Redis是基于内存操作的,CPU不是Redis的性能瓶颈,Redis的瓶颈其实是机器的内存和网络的带宽,官方觉得既然Redis可以使用单线程来实现,所以就使用单线程即可
②为什么Redis端口号默认为6379
粉丝效应(了解即可)
③为什么Redis是单线程还这么快
1)Redis是基于c语言编写的,官方提供的数据为100000+的QPS(每秒查询率),完全不比同样是使用key-value的MeMecache差
2)我们对于线程存在的误区
a.高性能的服务器一定是多线程的
b.多线程(CPU会上下文切换)一定比单线程效率高
我们要知道读取速度是CPU>内存>硬盘
3)核心: Redis是将所有的数据都全部存放在内存中的,所以说使用单线程去操作,效率就是最高的,多线程(CPU存在上下文切换,耗时的缺点),对于内存系统来说,如果没有上下文切换,效率就是最高的,每次读写都是在一个CPU上,所以这个就是最佳的方案
4)Redis的三大作用
a.可以用做数据库
b.缓存
c.消息中间件MQ

7.五大基本数据类型
(1)关于Redis-key的基本命令
Redis从入门到阿里_第25张图片

EXISTS: 判断是否存在当前key
Move: 从哪个数据库移除哪些key
EXPIRE: 设置当前key多长时间后过期(单位是秒)
TTL: 查看当前key的剩余时间
Type: 查看当前key的类型
Redis从入门到阿里_第26张图片

(2)String
①Append: 追加字符串(如果当前key不存在,就相当于set key value)
②Strlen: 获取字符串长度
Redis从入门到阿里_第27张图片

③Incr: 自增1
④Decr: 自减1
⑤Incrby: 可以设置步长,指定增量
⑥Decrby: 指定减量
Redis从入门到阿里_第28张图片

⑦Getrange: 截取字符串(闭区间)
Redis从入门到阿里_第29张图片

⑧Setrange: 替换从指定位置开始的字符串
Redis从入门到阿里_第30张图片

⑨Setex: (exist)设置过期时间(过期之前是可以访问的)
⑩Setnx: (not exist)不存在才设置(若存在则设置失败,在分布式锁中经常使用)
Redis从入门到阿里_第31张图片

⑪Mset: 批量设置key
⑫Mget: 批量获取值
⑬Msetnx: 是一个原子性的操作,要么一起成功,要么一起失败
Redis从入门到阿里_第32张图片

⑭设置对象
1)这里的key是一个巧妙的设计,user:{id}:{filed},这样的设计在Redis中是完全可以的
Redis从入门到阿里_第33张图片

⑮Getset: 先get再set
1)如果不存在值,则返回nil
2)如果存在值,则获取原来的值并返回,然后再设置新的值
Redis从入门到阿里_第34张图片

(3)List
①基本的数据类型,列表
②在Redis里面,我们可以把List完成栈、队列、阻塞队列(即两边均可通)
③!!!所有的List命令都是用l开头的
1)Lpush: 将一个或多个值,插入到列表的头部(左边)
Redis从入门到阿里_第35张图片

④Rpush: 插入到列表的尾部(右边)
Redis从入门到阿里_第36张图片

⑤Redis不区分大小写命令
⑥Lpop: 从左边取出值
⑦Rpop: 从右边取出值
Redis从入门到阿里_第37张图片

⑧通过下标获取值
在这里插入图片描述

⑨Llen: 获取列表的长度
在这里插入图片描述

⑩Lrem: 移除指定的值(可以移除多个相同的值)
Redis从入门到阿里_第38张图片

⑪Ltrim: 从左边开始通过下标截取指定长度的元素
此时的List已经被修改了,只剩下截取了的元素
Redis从入门到阿里_第39张图片

⑫Rpoplpush: 移除列表的最后一个元素,并将它移动到新的列表当中
Redis从入门到阿里_第40张图片

⑬Lset: 将列表中指定下标的值替换为另外一个值,相当于更新操作
Exists: 判断该列表是否存在,如果存在,会更新当前下标的值,不存在则会报错
Redis从入门到阿里_第41张图片

⑭Insert: 将某个具体的值插入到列表中某个元素的前面或者后面
Redis从入门到阿里_第42张图片

⑮小结
1)List实际上是一个链表
2)如果key不存在,则会创建新的链表
3)如果key存在,则会增加内容
4)如果移除了所有值,那么就是一个空链表
5)在两边插入或者改动值,效率最高,中间元素可能效率相对来说会低一点
6)可以做成栈(Lpush Lpop)、也可以做成队列(Lpush Rpop)
(4)Set
①set中的值是不能重复的
Sadd: 向set中添加元素
Smembers: 查看指定set中的所有值
Sismember: 判断某一个值是否在set集合中
Redis从入门到阿里_第43张图片

②Scard: 获取set集合中的元素个数
在这里插入图片描述

③Srem: 移除指定的元素
Redis从入门到阿里_第44张图片

④Srandmember: 随机抽选出一个元素
后面也可以指定随机抽取的元素个数
Redis从入门到阿里_第45张图片

⑤Spop: 随机移除元素
Redis从入门到阿里_第46张图片

⑥将set集合中一个指定的值移动到另外一个set集合中
Redis从入门到阿里_第47张图片

⑦例如: 微博、b站都有共同关注(交集)
1)数字集合类
a.差集 sdiff
b.交集 sinter
c.并集 sunion
Redis从入门到阿里_第48张图片

(5)Hash
①Map集合: key-map–key-
②本质上和String类型没有太大区别,还是一个简单的key-value
在这里插入图片描述

③Hdel: 删除指定的key字段,对应的value也一起删除
Redis从入门到阿里_第49张图片

④Hlen: 获取当前hash的长度
在这里插入图片描述

⑤Hexists: 判断指定字段是否存在
Redis从入门到阿里_第50张图片

⑥只获得所有的key
⑦只获得所有的value
Redis从入门到阿里_第51张图片

⑧Hsetnx: 如果不存在,则可以设置,如果存在,则不设置
Redis从入门到阿里_第52张图片

⑨Hash更适合于对象的存储,String更适合字符串存储
在这里插入图片描述

(6)Zset
①有序集合,即可以排序的集合
②在set的基础上,增加了一个值
Redis从入门到阿里_第53张图片

③排序的实现
1)Zrangebyscore: 通过成绩进行排序
2)-inf: 负无穷 +inf: 正无穷
3)Zrevrange: 从大到小排序(默认从小到大排序)
4)Withscores: 打印成绩
Redis从入门到阿里_第54张图片

④移除指定元素
Redis从入门到阿里_第55张图片

⑤获取有序集合中的个数
在这里插入图片描述

⑥Zcount: 获取指定区间的元素个数
Redis从入门到阿里_第56张图片

8.三种特殊数据类型
(1)Geospatial(Geo)
①地理位置 例如:定位、附近的人、打车距离的计算…
②Redis的Geo在Redis3.2版本就已经推出了,这个功能可以推算出地理位置的信息,包括: 两地之间的距离…
③总共有6个命令
Redis从入门到阿里_第57张图片

④Geoadd: 将指定的地理空间位置(经度、纬度、名称)添加到指定的key中
规则:两级无法直接添加,我们一般会下载城市数据,直 接通过java程序一次性写入
有效经度: -180到180度
有效纬度: -85.05112878 到 85.05112878 度
Redis从入门到阿里_第58张图片

⑤Geopos: 获取指定的城市的经度和纬度
获得当前定位,一定是一个坐标值
Redis从入门到阿里_第59张图片

⑥Geodist: 返回两个给定位置之间的距离
1)返回两个位置的距离
2)如果两个位置之间的其中一个不存在,则返回空值
3)指定单位的参数 unit 必须是以下单位的其中一个:
默认为m
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
Redis从入门到阿里_第60张图片

⑦Georadius: 以当前给定的经纬度为中心,找出某一半径内的元素
1)前提: 所有数据都应该存放到set集合中,才会让结果更加准确
2)Withdist: 显示到中间位置的距离
3)Withcoord: 经纬度
4)Count: 指定查找的个数
Redis从入门到阿里_第61张图片
Redis从入门到阿里_第62张图片

⑧Georadiusbymember: 找出位于指定范围内的元素,中心点是由给定的元素位置决定
Redis从入门到阿里_第63张图片

⑨Geohash: 该命令将返回11个字符的Geohash字符串
1)其实就是将二维的经纬度转换为一维的字符串
2)如果两个字符串越接近,那么这两个城市的距离就越近
在这里插入图片描述

Geo底层的实现原理: 其实就是Zset有序集合
Geo命令中没有删除指令,我们可以使用Zset中的删除命令
来操作Geo,从而达到删除实现
所以我们可以使用Zset命令来操作Geo

Redis从入门到阿里_第64张图片

(2)Hyperloglog
①用来做基数统计,是一种数据结构
1)基数: 不重复的元素,可以接收一定的误差
2)例如: 一个人统计一个网站的多个网页,统计网站访问人数时,只能算一个人
3)传统的统计方式: 用set保存用户的id,然后就可以统计set中的元素数量作为判断标准
这个方式如果保存大量的用户id,将会非常麻烦,因为这种方式非常消耗内存空间,对性能有影响
我们的目的不是为了保存用户id,而是为了计数
4)优点: 占用的内存是固定的,保存2^64个不同的元素,只需要占用12KB的内存,所以如果从内存角度来比较的话,Hyperloglog应该是首选
②测试使用
Redis从入门到阿里_第65张图片

③如果允许容错,那么一定可以选择Hyperloglog
④如果不允许容错,就使用set集合或者自己实现的数据类型即可
(3)Bitmap
①位图,也是一种数据结构
②都是操作二进制位来进行记录,只有0和1两个状态
③实现: 统计用户信息、活跃或不活跃、登录或未登录、打卡和未打卡
④只要是两个状态的,就可以使用Bitmap
⑤例如: 使用周一到周日的打卡情况(后面不需要自己手写,直接使用java中的循环即可)
前面的第一个0表示周一
后面的1表示打卡了,0表示未打卡
Redis从入门到阿里_第66张图片

⑥查看某一天是否打卡过
在这里插入图片描述

⑦统计打卡的天数
统计这周打卡的天数,如果小于总天数,就可以扣全勤奖
在这里插入图片描述

9.Redis事务操作
(1)Redis的单条命令是保证原子性的,但是Redis的事务是不保证原子性的
(2)事务的本质: 一组命令的集合
(3)一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行(相当于队列)
(4)一次性、顺序性、排他性(即不会被其他语句干扰)
(5)Redis事务没有隔离级别的概念,所有的命令在事务中其实并没有直接被执行,只有发起执行命令的时候才会被执行
(6)事务执行步骤
①开启事务—multi
②命令入队—就是我们写的命令
③执行事务—exec
(7)正常执行事务
每一个事务执行完就会被销毁,要想再使用事务,就需要再次开启事务
Redis从入门到阿里_第67张图片

(8)放弃事务
①一旦放弃事务,事务中的所有语句都不会被执行
Redis从入门到阿里_第68张图片

(9)事务中的命令存在错误
①编译型异常(代码有问题,命令写错)
1)此时事务中的所有命令都不会被执行
Redis从入门到阿里_第69张图片

②运行时异常(语法错误)
1)执行命令的时候,除了报错的命令无法执行,其他命令是可以被正常执行的,错误命令会抛出异常

Redis从入门到阿里_第70张图片

10.Redis实现乐观锁(使用watch进行监控)
(1)悲观锁
①很悲观,认为什么时候都会出现问题,无论做什么都会加锁
(2)乐观锁
①很乐观,认为什么时候都不会出现问题,所以不会上锁,更新数据的时候去判断一下,在此期间是否有人修改过这个数据
②获取version
③更新的时候比较version
(3)Redis监视测试
①正常测试成功
事务正常结束
数据在此期间没有任何变动,这个时候就会正常执行成功
Redis从入门到阿里_第71张图片

②测试多线程修改值,使用watch可以当作Redis的乐观锁来操作
注: 事务一旦提交,watch监控便会停止,如果需要监控,就需要再次开启监控
第一个线程中,事务提交之前,在第二个线程中对money做了改变,这样watch监控就会知道事务中的数据已经改变了,就不会提交事务,返回nil
Redis从入门到阿里_第72张图片
在这里插入图片描述
Redis从入门到阿里_第73张图片

一旦提交失败,此时的watch监控就没什么用了,就先解锁,获取最新的值,然后在重新加锁,再执行事务,便可成功
提交事务时,会比对监视的值是否发生了变化,如果没有变化,那么可以执行成功,如果变了,就会执行失败

Redis从入门到阿里_第74张图片
Redis从入门到阿里_第75张图片

11.通过Jedis来操作Redis
(1)我们可以使用Java来操作Redis
(2)什么是Jedis
①是Redis官方推荐的Java连接开发工具,使用java操作Redis的一个中间件
(3)测试
①导入相应的依赖
Redis从入门到阿里_第76张图片

②编码测试
1)连接数据库
2)操作命令
3)断开连接
Redis从入门到阿里_第77张图片

12.SpringBoot集成Redis
(1)Redis属于SpringData
(2)在springboot2.x之后,Jedis就被替换成了lettuce
Redis从入门到阿里_第78张图片

(3)区别
①Jedis: 采用的直连,如果多个线程同时操作的话,是不安全的,要想避免不安全,就要使用Jedis pool连接池,更像BIO模式
②Lettuce: 底层采用的是Netty网络框架,实例可以在多个线程当中进行共享,不存在线程不安全的情况,可以减少线程的数量,更像NIO模式
(4)源码分析
①默认的RedisTemplate没有过多的设置,Redis对象都是需要序列化的
②两个泛型都是Object类型,后面使用需要强制转换
③由于String类型是Redis中最常使用的类型,所以说单独提出来了一个bean
Redis从入门到阿里_第79张图片

(5)测试
①导入依赖
②配置连接
1)在配置文件中修改或者使用连接池时,应该选择lettuce pool连接池,因为Jedis pool连接池中的很多依赖在现在的springboot版本中根本没实现
在这里插入图片描述
在这里插入图片描述

③测试

Redis从入门到阿里_第80张图片

序列化配置
Redis从入门到阿里_第81张图片

在这里插入图片描述

(6)自定义redisTemplate
①存储对象时,需要序列化
如果不序列化,将会报错
Redis从入门到阿里_第82张图片
在这里插入图片描述

②默认使用JDK序列化,我们也可以使用其他的序列化方式
Redis从入门到阿里_第83张图片
在这里插入图片描述

③编写一个自己的redisTemplate模板
Redis从入门到阿里_第84张图片

④使用自己编写的redisTemplate实现序列化
Redis从入门到阿里_第85张图片
Redis从入门到阿里_第86张图片

⑤在企业中,我们不会直接使用redisTemplate的原生API
而是会自己编写一个redisTemplate的工具类,将一些常用的方法实现
13.Redis配置文件详解
(1)启动的时候,就通过配置文件来启动
(2)分析
①单位
不区分大小写
Redis从入门到阿里_第87张图片

②包含其他文件
Redis从入门到阿里_第88张图片

③网络配置
Redis从入门到阿里_第89张图片
在这里插入图片描述

④通用的配置
1)以守护线程的方式执行,默认为no,我们需要改为yes
在这里插入图片描述

2)pid文件: 如果以后台的方式运行,我们就需要指定一个pid文件
在这里插入图片描述

3)日志
Redis从入门到阿里_第90张图片

4)日志生成的文件名,后面需要修改
在这里插入图片描述

5)是否总是显示logo,默认为yes
在这里插入图片描述

6)快照
a.主要用于持久化,即在规定的时间内,执行了多少次操作,则会持久化到文件中
b.Redis是内存数据库,如果没有持久化,那么数据就会断电即失
c.save 900 1
a)如果900秒内,至少有一个key进行了修改,我们就需要进行持久化操作
d.save 300 10
a)如果300秒内,至少有10个key进行了修改,我们就需要进行持久化操作
e.save 60 10000
a)如果60秒内,至少有10000个key进行了修改,我们就需要进行持久化操作
f.我们之后学习持久化,会自己定义这个时间
Redis从入门到阿里_第91张图片

7)持久化如果出错了,是否还需要继续工作,默认为yes
在这里插入图片描述

8)是否压缩rdb文件,需要消耗一些cpu的资源,默认为yes
在这里插入图片描述

9)保存rdb文件的时候,是否需要进行错误的检查校验,默认为yes
在这里插入图片描述

10)rdb文件保存的目录
在这里插入图片描述

11)主从复制,后面讲解
Redis从入门到阿里_第92张图片

12)设置密码
Redis默认是没有密码的,我们可以自己设置
方式一: 直接在配置文件中设置(不推荐使用这种)
Redis从入门到阿里_第93张图片

方式二: 通过命令设置
Redis从入门到阿里_第94张图片

13)客户端的一些限制
设置能连接Redis的最大客户端的数量
Redis从入门到阿里_第95张图片

14)Redis能配置的最大内存容量
Redis从入门到阿里_第96张图片

15)当Redis内存的使用达到上限之后的处理策略
maxmemory-policy 六种方式
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
2、allkeys-lru : 删除lru算法的key
3、volatile-random:随机删除即将过期key
4、allkeys-random:随机删除
5、volatile-ttl : 删除即将过期的
6、noeviction : 永不过期,返回错误

Redis从入门到阿里_第97张图片

16)AOF配置
默认是不开启AOF模式的,默认使用RDB方式进行持久化,在大部分的情况下,RDB完全够用

持久化文件的名字: “appendonly.aof”
Redis从入门到阿里_第98张图片

always: 每次修改都会同步,消耗性能
everysec: 每秒执行一次同步,也有可能会丢失这一秒的数据
no: 不执行同步,这个时候操作系统会自己同步数据,速度最快
Redis从入门到阿里_第99张图片

14.Redis持久化
(1)面试和工作中,持久化都是重点
(2)Redis是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务进程退出,服务器中的数据库状态也会消失,所以Redis提供了持久化功能
(3)RDB(Redis DataBase)
①概念
Redis从入门到阿里_第100张图片

②分析
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是快照,它恢复时是将快照文件直接读到内存中
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程结束了,再用这个临时文件替换掉上次持久化好的文件,在整个过程中,主进程是不进行任何IO操作的,这样就确保了极高的性能,如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那么RDB方式比AOF方式更加的高效,RDB的缺点就是最后一次持久化后的数据可能会丢失
我们默认的方式就是RDB,一般情况下够用,不需要修改这个配置
③RDB保存的文件的dump.rdb文件
在这里插入图片描述

④触发规则
1)save的规则满足的情况下,会自动触发RDB规则
2)执行flushall命令,也会触发我们的RDB规则
3)退出Redis时,默认也会产生RDB文件
备份就会自动生成一个dump.rdb文件
在这里插入图片描述

⑤如何恢复RDB文件
1)只需要将RDB文件放在我们的Redis启动目录中即可,Redis启动时就会自动检查dump.rdb文件并恢复其中的数据
2)如果在bin这个目录下存在dump.rdb文件,启动时就会自动恢复其中的数据
在这里插入图片描述

3)其实RDB文件自己默认的配置就够我们使用了,但是我们还是要去学习了解
4)有时候在生产环境中,我们会将这个RDB文件进行备份
⑥RDB文件的优点和缺点
1)优点
a.适合大规模的数据恢复
b.对数据的完整性要求不高
2)缺点
a.需要一定的时间间隔进行操作(我们可以自己设置时间间隔),如果Redis意外宕机了,那么最后一次修改的数据就没了
b.fork子进程的时候,会占用一定的内存空间
(4)AOF(Append Only File)
①概念
Redis从入门到阿里_第101张图片

②分析
1)AOF其实就是将我们所有的命令都记录下来,恢复的时候就把这个文件的所有命令全部在执行一遍
2)以日志的形式来记录每一个操作,将Redis执行过的所有指令都记录下来(读取的操作不记录),只许追加文件,不可以改写文件,Redis启动之后就会读取该文件并重新构建数据,简而言之,就是Redis重启的话,就会根据日志文件的内容将写指令从前到后执行一遍,以完成数据的恢复工作
③AOF保存的文件是appendonly.aof文件
Redis从入门到阿里_第102张图片

④默认是不开启AOF的,我们需要手动进行配置,只需要将appendonly改为yes即可
Redis从入门到阿里_第103张图片

⑤重启Redsi就可以生效了
在这里插入图片描述

⑥如果AOF配置文件有错误,这个时候Redis是启动不起来的
1)我们先设置几个值
Redis从入门到阿里_第104张图片

2)然后关闭Redis
在这里插入图片描述

3)再删除RDB文件并查看AOF文件
Redis从入门到阿里_第105张图片

4)然后我们给AOF文件随便加点东西,导致其有错误
Redis从入门到阿里_第106张图片

5)再重启Redis,发现无法启动
在这里插入图片描述

⑦解决办法
1)Redis给我们提供了一个工具: redis-check-aof
2)这个工具可以修复错误的AOF文件
Redis从入门到阿里_第107张图片

3)如果AOF文件恢复正常,再次重启Redis,可以正常启动
在这里插入图片描述

⑧AOF文件的优点和缺点
1)优点
a.每一次修改都同步,文件的完整性会更好
b.默认每秒同步一次,可能会丢失一秒的数据
c.从不同步,效率最高
2)缺点
a.相对于数据文件来说,AOF远远大于RDB,修复的速度也比RDB慢
b.AOF运行的效率也要比RDB慢,所以我们Redis默认的配置就是RDB持久化
⑨重写操作(了解即可)
1)如果AOF文件大于64兆,Redis就会fork一个新的进程来将AOF文件进行重写
2)因为AOF默认的就是文件的无限追加,这样文件的大小就会越来越大
在这里插入图片描述

⑩扩展
1.Redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中。
2.RDB 持久化适合大规模的数据恢复但它的数据一致性和完整性较差。
3.Redis 需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中。
4.AOF 的数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率。
5.Redis 针对 AOF文件大的问题,提供重写的瘦身机制。
6.若只打算用Redis 做缓存,可以关闭持久化。
7.若打算使用Redis 的持久化。建议RDB和AOF都开启。其实RDB更适合做数据的备份,留一后手。AOF出问题了,还有RDB
15.Redis实现订阅发布
(1)Redis发布订阅(pub/sub)是一种消息通信模式,发送者(pub)发送消息,订阅者(sub)接收消息
(2)Redis客户端可以订阅任意数量的频道
(3)订阅/发布消息图示
Redis从入门到阿里_第108张图片

(4)下图展示了频道channel1,以及订阅这个频道的三个客户端之间的关系
Redis从入门到阿里_第109张图片

(5)当有新消息通过PUBLISH命令发送给频道时,这个消息就会被发送给订阅它的三个客户端
Redis从入门到阿里_第110张图片

(6)Redis发布订阅的常用命令
这些命令被广泛用于构建即时通信应用,比如网络聊天室、实时广播、实时提醒等
Redis从入门到阿里_第111张图片

(7)测试一下
①订阅端
Redis从入门到阿里_第112张图片

②发送端
在这里插入图片描述

(8)原理
①Redis是使用C实现的,通过分析Redis源码里的pubsub.c文件,可以了解发布和订阅机制的底层实现,借此加深对Redis的理解
②Redis通过PUBLISH、SUBSCRIBE、PSUBSCRIBE等命令实现发布和订阅功能
③通过SUBSCRIBE命令订阅某频道后,redis-server里面维护了一个字典,字典的键就是一个个频道,而字典的值便是一个链表,链表中保存了所有订阅这个频道的客户端,SUBSCIRBE命令的关键,就是将客户端添加到给定频道的订阅链表之中
④通过PUBLISH命令向订阅者发送消息,redis-server会使用给定的频道作为键,在它所维护的频道字典中查找订阅了这个频道的所有客户端的链表,遍历这个链表,将消息发布给所有的订阅者
⑤Pub/sub从字面上理解就是发布和订阅,在Redis中,你可以设定对某一个key值进行消息发布和消息订阅,当一个key值上进行消息发布后,所有订阅它的客户端都会收到相应的消息,这一功能最明显的用法就是用作实时消息系统、普通的聊天、群聊等功能
16.Redis集群环境搭建
(1)
17.Redis主从复制
(1)概念
①主从复制: 是指将一台Redis服务器的数据,复制到其他的Redis服务器,前者称为主节点(master/leader),后者称为从节点(slave/follower),数据的复制是单向的,只能由主节点到从节点,master以写为主,slave以读为主
②默认情况下,每台Redis服务器都是主节点,且一个主节点可以有多个从节点(或者没有从节点),但一个从节点只能有一个主节点
③主从复制的作用
1)数据冗余: 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
2)故障恢复: 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复,实际上是一种服务的冗余
3)负载均衡: 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从结点提供读服务(即写Redis数据时连接主节点,读取Redis数据时连接从节点),分担服务器负载,尤其是在写少读多的场景下,通过多个从结点分担读的负载,可以大大提高Redis服务器的并发量
4)高可用(集群)基石: 除了上述作用外,主从复制还是哨兵和集群能够实施的基础,所以说主从复制是Redis高可用的基础
(2)一般来说,要将Redis运行在工程项目中的话,只使用一台Redis是万万不能的,原因如下:
①从结构上来说,单个Redis服务器可能会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大
②从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不能将所有的内存都用做Redis存储的内存,一般来说,单台Redis最大使用内存不应该超过20G
③例如: 电商网站上的商品,一般都是一次上传,无数次浏览的,也就是”少写多读”
④主从复制结构
主从复制,读写分离(一主二从)80%的情况下,都是在进行读操作,减缓服务器的压力,架构中经常使用
Redis从入门到阿里_第113张图片

(3)在公司中,主从复制是必须要使用的,因为在真实的项目中不可能单机使用Redis
(4)环境配置
①查看当前库的信息
1)Role: 默认为主节点
2)Connected_slaves: 从节点个数
Redis从入门到阿里_第114张图片

②复制三个配置文件,然后修改对应的信息
1)端口号
2)Pidfile
3)日志log
4)Dump.rdb
③启动3个Redis
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

④一主二从
1)默认情况下,每台Redis服务器都是主节点
2)主机(79)、从机(80、81)
3)我们一般情况下只需要配置从机就好了
Redis从入门到阿里_第115张图片
Redis从入门到阿里_第116张图片

(5)这个时候再查看主机的信息
Redis从入门到阿里_第117张图片

(6)真实的主从配置应该在配置文件中配置,这样的话就是永久的,我们这里使用的是命令配置的,这样是暂时的
Redis从入门到阿里_第118张图片

(7)解析细节
①主机可以写,但是从机不能写,只能读,主机中的所有信息和数据,都会自动被从机保存
在这里插入图片描述
Redis从入门到阿里_第119张图片
在这里插入图片描述

②如果主机断开连接,从机依旧是连接到主机的,但是这个时候没有写操作。这个时候,如果主机连接上了,从机依旧可以和主机连上,可以直接获取到主机写的信息
③如果是使用命令行来配置的主从复制,这个时候如果从机断开了连接,再次重启时,就会变为主机,只要让它再次变为从机,并连接到主机,依旧是可以访问到主机的所有数据的
(8)主从复制原理
①slave从机启动成功后连接到master主机后会发送一个sync同步命令
②master主机接到命令后,会启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master主机将传送整个数据文件到slave从机,并完成一次完全同步
③全量复制: 而slave从机服务在接收到数据文件的数据后,将其存盘并加载到内存中
④增量复制: master主机继续将新的所有收集到的修改命令依次传给slave从机,完成同步
⑤但是只要是重新连接到master主机,一次完全同步(全量复制)将被自动执行,我们的数据就一定可以在从机中看到

18.宕机后手动配置主机
(1)层层链路
这个时候也是可以完成我们的主从复制的
Redis从入门到阿里_第120张图片

(2)这个时候,我们将79断开,此时80、81依旧都是从节点,这个时候,我们可不可以选择一个老大来当主机呢(手动选择)
Redis从入门到阿里_第121张图片

(3)如果这个时候,79又重新连接上了,也只是变回了主机,没有从机,只能重新配置从机
19.Redis哨兵模式(重点)
(1)这是一种自动选取主机的模式
(2)概述
①主从切换技术的方法是: 当主服务器宕机后,需要手动把一台服务器切换为主服务器,这就需要人工干预,费时费力,还会造成一段时间内服务不可用,这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式,Redis 2.8开始就正式提供了Sentinel(哨兵)架构来解决这个问题
②能够自动后台主机是否出现了故障,如果出现了故障,就会根据投票数自动将从机转为主机
③哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行,其原理是哨兵通过发送命令,等待Redis服务器的响应,从而监控运行时的多个Redis实例
④图示
这里的哨兵主要有两个作用
1.通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器
2.当哨兵监测到master宕机后,会自动将slave转换为master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机
Redis从入门到阿里_第122张图片

(3)然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,因此,我们可以使用多个哨兵进行监控,各个哨兵之间还会进行监控,这样就形成了多哨兵模式
Redis从入门到阿里_第123张图片

假设主服务器宕机,哨兵1会先检测到这个结果,系统不会马上进行从新选举的一个过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到了一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行故障转移操作。切换成功后,就会通过发布订阅方式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
(4)测试一下
①我们目前的状态是一主二从
②首先编写哨兵配置文件
不能写错单词,否则会报错
格式: sentinel monitor 被监视的名称 host port 1
后面的数字1表示: 当主机挂了的时候,slave投票看让谁接替成为主机比较好,票数最多的就会成为新的主机
Redis从入门到阿里_第124张图片

③启动哨兵
Redis从入门到阿里_第125张图片

④测试当主机79宕机了之后,哨兵会怎么办
Redis从入门到阿里_第126张图片
Redis从入门到阿里_第127张图片
Redis从入门到阿里_第128张图片
Redis从入门到阿里_第129张图片

⑤如果主机此时回来了,只能归并到新的主机下,当作从机,这就是哨兵模式的规则
Redis从入门到阿里_第130张图片
Redis从入门到阿里_第131张图片
在这里插入图片描述

(5)哨兵模式的优点和缺点
①优点
1)哨兵集群,基于主从复制模式,所有的主从配置的优点,它全都有
2)主从可以切换,故障可以转移,系统的可用性就会更好
3)哨兵模式就是主从模式的升级版,从最开始的手动到自动,更加健壮
②缺点
1)Redis不好在线扩容,集群容量一旦到达上限,在线扩容就会显示十分麻烦
2)实现哨兵模式的配置其实是很麻烦的,里面有很多选择
(6)哨兵模式配置文件详解

Example sentinel.conf

哨兵sentinel实例运行的端口 默认26379

port 26379

哨兵sentinel的工作目录

dir /tmp

哨兵sentinel监控的redis主节点的 ip port

master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。

quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了

sentinel monitor

sentinel monitor mymaster 127.0.0.1 6379 2

当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码

设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码

sentinel auth-pass

sentinel auth-pass mymaster MySUPER–secret-0123passw0rd

指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒

sentinel down-after-milliseconds

sentinel down-after-milliseconds mymaster 30000

这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,

这个数字越小,完成failover所需的时间就越长,
但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。

sentinel parallel-syncs

sentinel parallel-syncs mymaster 1

故障转移的超时时间 failover-timeout 可以用在以下这些方面:

#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了

默认三分钟

sentinel failover-timeout

sentinel failover-timeout mymaster 180000

SCRIPTS EXECUTION

#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。

#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,
这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,
一个是事件的类型,
一个是事件的描述。
如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本

sentinel notification-script

sentinel notification-script mymaster /var/redis/notify.sh

客户端重新配置主节点参数脚本

当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。

以下参数将会在调用脚本时传给脚本:

目前总是“failover”,

是“leader”或者“observer”中的一个。

参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的

这个脚本应该是通用的,能被多次调用,不是针对性的。

sentinel client-reconfig-script

sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

20.Redis的缓存穿透、击穿及雪崩(面试高频、工作常用)
(1)缓存穿透(查不到)
①缓存穿透的概念很简单,用户想要查询一个数据,发现Redis内存数据库当中并没有,也就是缓存没有命中,于是就会向持久层数据库发起查询,发现也没有该数据,于是本次查询就会失败,当用户很多的时候,缓存都没有命中,于是所有的请求就都会去找持久层数据库,这就给持久层数据库造成了很大的压力,这时候就相当于出现了缓存穿透。
(2)解决方案
①布隆过滤器
是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力
Redis从入门到阿里_第132张图片

②缓存空对象
当存储层(持久层数据库)不命中后,即使返回的空对象也将其缓存起来,同时还会设置一个过期时间,之后再访问这
个数据将会从缓存中获取,保护了后端的持久层数据库
但是这个方法存在两个问题:
1.如果空值能够被缓存起来,这就意味着缓存需要更多的空间来存储更多的键,因为这当中可能会有很多空值的键
2.即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务有一定的影响
(3)缓存击穿(查的次数太多,缓存过期)
①概述
1)这里需要注意和缓存穿透的区别,缓存击穿,是指一个key非常热点,中不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就会穿破缓存,直接请求数据库。
2)当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导致数据库瞬间压力变大
②解决方案
1)设置热点数据永不过期
a.从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题,但是另一方面,Redis的缓存有可能到达极限,这个时候可能就需要删除一些key,并不能保证每个key能够永久不过期
2)加互斥锁
a.分布式锁: 使用分布式锁,可以保证对于每一个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大
(4)缓存雪崩
①概述
1)缓存雪崩,是指在某一个时间段,缓存集中过期失效,比如Redsi宕机
2)产生雪崩的原因之一,比如在双十一零点,会迎来一波抢购,这波商品比较集中的放在了缓存中,假设缓存一个小时,那么到了凌晨一点的时候,这批商品的缓存时间就过期了,而这批商品的访问查询,就会全部落到数据库上,对于数据库而言,就会产生周期性的压力波峰,于是所有的请求都会到达存储层,存储层的调用量会暴增,最终造成存储层挂掉
3)其实集中过期,并不是非常致命,比较致命的缓存雪崩,是缓存服务器某个结点宕机或断网,因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,这个时候,数据库也是可以顶住压力的。无非就是对数据库产生了周期性的压力而已,而缓存服务节点的宕机,对数据库服务造成的压力是不可预知的,很有可能瞬间就把数据库压垮。
4)比如: 双11的时候,淘宝便会停掉一些服务,保证主要的服务高可用
②解决方案
1)Redis高可用
这个思想的含义就是,既然Redis有可能挂掉,那我多增设几台Redis,这样一台挂掉之后其他的还可以继续工作,其实说简单点就是搭建集群
2)限流降级
这个解决方案的思想就是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如: 对某个key只允许一个线程查询和写缓存,其他线程则等待
3)数据预热
数据预热的含义就是,在正式部署之前,我先把可能得数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中,在即将发生大并发访问之前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

你可能感兴趣的:(redis,数据库,nosql)