Redis
NoSql概述
为什么要用NoSql
单机MySQL的年代
一个基本的网站访问量一般不会太大,单个数据库完全足够
更多的使用静态网页,服务器没有太大的压力
整个网站的瓶颈:
- 数据量如果太大,一个机器放不下了
- 数据的索引,一个机器内存放不下
- 访问量(读写混合),一个服务器承受不了
只要开始出现以上三个情况之一,那必须晋级
Memcached(缓存)+MySQL+垂直拆分
网站80%的情况都是在读,每次都要去查数据库就十分麻烦,所以我们希望减轻数据库的压力,可以用缓存来保证效率
发展过程:优化数据结构和索引-》文件缓存-》Memcached
分库分表+水平拆分+MySQL集群
本质:数据库读写
早些年MyISAM:表锁,十分影响效率,高并发会出现严重的锁问题
InnoDB:行锁
慢慢地就开始分库分表来解决写的压力
最近的年代
MySQL关系型数据库不够用。数据量很多,变化快
MySQL使用一些较大的文件。数据库表很大,效率降低。如果有一种数据库来专门处理这种数据,MySQL压力就会变小
大数据的压力下,表几乎无法更改
目前一个基本的互联网项目
为什么要用NoSQL
用户的个人信息,社交网络,地理位置,用户自己产生的数据,用户的日志等等爆发式增长
这时我们需要使用NoSQL数据库,可以很好地处理以上情况
什么是NoSQL
Not Only SQL
泛指非关系型数据库
随着web2.0的互联网诞生,传统的关系型数据库很难对付,尤其是超大规模的高并发的社区。暴露出来很多难以克服的问题
关系型数据库:表格、行、列(POI)
很多数据类型的存储不需要一个固定的格式,不需要多余的操作就可以横向扩展
NoSQL特点
方便扩展(数据之间无关系)
大数据量高性能(是一种细粒度的缓存)
数据类型多样(不需要事先设计数据库,随取随用)
传统RDBMS和NoSQL
1
2
3
4
5
6
7传统RDBMS
- 结构化组织
- SQL
- 数据和关系都在单独的表中
- 数据定义语言
- 严格的一致性
- 基础的事务1
2
3
4
5
6
7NoSQL
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库
- 最终一致性
- CAP定理和BASE(异地多活)
- 高性能,高可用,高可扩展性了解:3V+3高
3V:海量,多样,实时
3高:高并发,高可拓,高性能
真正在公司中的时间:NoSQL+RDBMS一起使用才是最强的
阿里巴巴演进分析
思考问题:这么多东西难道在一个数据库中吗?
任何一家互联网公司,都不可能只是简简单单让用户能用就好了
没有什么是加一层解决不了的
1 | #商品的基本信息 |
要知道,一个简单地网页背后的技术一定不是想象的那么简单
大型互联网应用问题:
- 数据类型太多
- 数据源繁多。经常重构
- 数据要改造,需要大面积改造
解决问题:UDSL(统一数据服务平台)
以上都是NoSQL入门概述,不仅能提高知识,还能帮助了解大厂工作内容
NoSQL的四大分类
KV键值对:
- 新浪:Redis
- 美团:Redis+Tair
- 阿里、百度:Redis+Memcached
文档型数据库:
- MongoDB
- 是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档
- 是一个介于关系型数据库和非关系型数据库的产品。MongoDB是非关系型数据库中功能最丰富,最像关系型数据库的。
- ConthDB
列存储数据库:
- HBase
- 分布式文件系统
图形关系数据库:
- 不是存图形,放的是关系,比如:朋友圈社交网络,广告推荐
- Neo4j
Redis入门
概述
Redis是什么
Redis,即远程字典服务
是当下最热门的NoSQL技术之一,也被人们称之为结构化数据库
Redis能做什么
- 内存存储,持久化。内存是断电即失,所以说持久化很重要(RDB、AOF)
- 效率高,可以用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(浏览量)
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
学习中要用到的东西
- 官网
- Redis中文网
Redis推荐在Linux服务器上搭建,基于Linux学习
Windows安装
默认端口号:6379
Windows下使用确实简单,但是Redis推荐我们使用Linux开发
Linux安装
下载安装包
redis-6.2.5.tar.gz
解压Redis的安装包 程序在opt下
进入解压后的文件,可以看到Redis的配置文件
基本的环境安装
1
2
3yum install gcc-c++
make
make installRedis的默认安装路径:
usr/local/bin
将Redis配置文件复制到当前目录下
Redis默认不是后台启动的,修改配置文件
启动Redis服务
使用Redis客户端进行连接
查看Redis的进程是否开启
如何关闭Redis服务?(shutdown)
再次查看进程是否存在
后面会使用单机多Redis集群
测试性能
redis-benchmark是一个压力测试工具
redis-benchmark -h localhost -p 6379 -c 100 -n 10000
基础知识
Redis默认有16个数据库,默认使用的是第0个数据库
1 | select n//切换数据库 |
为什么Redis是6379?(了解一下即可)
Redis是单线程的!
Redis是很快的。官方表示,Redis基于内存操作,CPU不是Redis的性能瓶颈,Redis的瓶颈是根据机器的内存和网络的带宽。既然能用单线程实现,那就用单线程。
Redis是C语言写的。官方数据为100000+的QPS,这个不必Memcached差
Redis为什么单线程还这么快?
- 误区1:高性能的服务器一定是多线程的?
- 误区2:多线程(CPU上下文会切换)一定比单线程效率高?
核心:Redis将所有数据放在内存中,所以说使用单线程操作效率最高。对于内存来说,如果没有上下文切换效率就是最高的。多次读写都在一个CPU上。
五大数据类型
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
Redis-Key
1 | keys *//查看所有key |
String
1 | set key1 v1 |
String类型应用场景:
- 字符串
- 计数器
- 统计多单位的数量
- 对象缓存存储
List
在Redis中,能把list用成栈、队列、阻塞队列
1 | LPUSH list one#将值插到列表头部 |
小结
- 实际上是一个链表,left、right都可以插入值
- 如果key不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也代表不存在
- 在两边插入或者改动值,效率最高。中间元素相对来说效率会低一点
Set
Set中的值是不能重复的
1 | Sadd myset "hello" |
共同关注,共同爱好
Hash
Map集合,key-Map集合
1 | Hset myhash field1 aaa |
Hash存储变更的数据,尤其是用户信息之类的,经常变动的信息。Hash更适合于对象的存储,String更加适合字符串存储
Zset(有序集合)
在Set的基础上,增加了一个值
1 | Zadd myset 1 one |
其余的一些API,通过我们的学习,剩下的如果工作中有需要,这个时候可以去看看官网
三种特殊数据类型
Geospatial地理位置
只有六个命令
GEOADD
添加地理位置
规则:两极无法直接添加,我们一般会下载城市数据,通过java程序一次性导入
参数:纬度、经度、名称
GEOPOS
获取指定的经度和纬度:一定是一个坐标值
GEODIST
两人之间的距离
GEORADIUS
查看方圆半径内的地址
获得指定数量的人
GEORADIUSMEMBER
找出位于指定范围内的元素,中心点是由给定的位置元素决定
GEOHASH
返回一个或多个位置元素
GEO底层原理其实就是Zset。我们可以使用Zset来操作GEO
Hyperloglog
基数
Redis2.8.9版本就更新了Hyperloglog数据结构
是用来做基数统计的算法
网页的UV(一个人访问一个网站多次,但还是算作一个人)
传统的方式:Set保存用户的id,然后就可以统计Set中的元素数量作为标准判断。这个方式如果保存大量的id,就会比较麻烦。我们的目的是计数,而不是保存id
Hyperloglog:占用的内存是固定的,2^64不同元素的计数,只需要12KB的内存。如果从内存角度来比较,Hyperloglog首选
1 | PFadd mykey a b c d e f g h i j |
如果允许容错,就可以使用Hyperloglog,否则使用Set或其它
Bitmap
位存储
两个状态的,都可以使用Bitmap
都是操作二进制位来进行记录,只有0和1两个状态
1 | #使用Bitmap记录周一到周日的打卡 |
事务
Redis事务本质:一组命令的集合。一个事务中的所有命令都会被序列化。在事务执行的过程中,会按照顺序执行。
一次性、顺序性、排他性。执行一系列的命令
Redis事务没有隔离级别的概念
所有的命令在事务中并没有直接被执行,只有发起执行命令时才会被执行
Redis单条命令保证原子性,但是事务不保证原子性
Redis事务:
- 开启事务(Multi)
- 命令入队
- 执行事务(Exec)
正常执行事务
1 | 127.0.0.1:6379> multi |
放弃事务
1 | 127.0.0.1:6379> multi |
编译型异常(命令有错),事务中所有的命令都不会被执行
1 | 127.0.0.1:6379> multi |
运行时异常(例如1/0),如果事务队列中存在语法型错误,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常
1 | 127.0.0.1:6379> set k1 "v1" |
监控(watch)
悲观锁:
- 认为什么时候都会出问题,无论做什么都会加锁
乐观锁:
- 认为什么时候都不会出现问题,所以不会上锁。更新数据时去判断一下,在此期间是否有人修改过这个数据,version
- 获取version
- 更新时比较version
Redis监视测试
正常执行成功
1 | 127.0.0.1:6379> set money 100 |
1 | 127.0.0.1:6379> watch money#watch可当做乐观锁操作 |
Jedis
通过Java操作Redis
什么是Jedis?
Java操作Redis中间件
测试
- 导入对应的依赖
1 | <dependencies> |
编码测试
- 连接数据库
- 操作命令
- 断开连接
1
2
3
4
5
6public class TestPing {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
System.out.println(jedis.ping());
}
}输出:PONG
常用API
String
List
Set
Hash
Zset
事务
1 | public class RedisTX { |
SpringBoot整合
说明:在SpringBoot2.x之后,原来使用的Jedis被替换成了lettuce
Jedis:直连,多个线程操作的话不安全,如果要避免,使用Jedis pool
Lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全,可以减少线程数量
Redis.conf详解
启动的时候,通过配置文件来启动
单位
- 配置文件unit单位对大小写不敏感
包含
网络
1 | bind 127.0.0.1 -::1#绑定的ip |
通用General
1 | daemonize yes#以守护进程的方式运行,默认是no,我们需要开启为yes |
快照
持久化。在规定的时间内,执行了多少次操作,则会持久化到文件,则会持久化到文件.rdb .aof
1 | # save 3600 1 如果900s内,至少有1个key进行了修改,就持久化 |
REPLICATION 复制,后面主从复制再讲解
SECURITY安全
可以设置redis密码,默认是没有密码的
限制
1 | maxclients 10000#设置Redis的最大客户端数量 |
APPEND ONLY模式 aof配置
1 | appendonly no#默认不开启aof模式,默认rdb方式持久化。在大部分情况下,rdb够用 |
Redis持久化
RDB(Redis DataBase)
什么是RDB
在主从复制中,RDB备用
默认的是RDB,一般情况下不需要修改这个配置
缺点:最后一次持久化后的数据可能丢失
RDB保存的文件是dump.rdb都是在配置文件的快照中进行配置
触发机制
- save的规则满足的情况下,会自动触发RDB规则
- 执行flushall命令,也会触发RDB规则
- 退出Redis,会触发
备份就会自动生成一个dump.rdb文件
如何恢复RDB文件
- 只要将RDB文件放到Redis启动目录,Redis启动会检查dump.rdb,会自动恢复数据
- 查看需要存放的位置
基本上默认的配置就够用了
优点:
- 适合大规模的数据恢复
- 对数据的完整性要求不高
缺点:
- 需要一定的时间间隔进程操作。如果Redis宕机了,最后一次的数据就没了
- fork进程的时候,会占用一定内存
AOF(Append Only File)
将我们的所有命令都记录下来,history,回复的时候就把这个文件全部再执行一遍
是什么
以日志的形式记录每一个操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件
Aof保存的是appendonly.aof文件
append
默认不开启,我们需要手动进行配置
重启Redis就能生效
如果aof文件有错误,Redis是启动不起来的,我们需要修复配置文件
Redis给我们提供了一个工具redis-check-aof --fix
优点和缺点
优点:
- 每一次修改都同步,文件完整性会更加好
- 每秒同步一次,可能会丢失数据
- 从不同步,效率最高
缺点:
- 相对于数据文件来说,aof远远大于rdb,修复速度比rdb慢
- aof运行效率比rdb低
扩展:
Redis发布订阅
通信 队列 发送者 订阅者
订阅、发布消息图
命令
原理
使用场景:
- 实时消息系统
- 实时聊天(频道作为聊天室,信息回显即可)
- 订阅、关注
稍微复杂的场景我们会使用消息中间件
Redis主从复制
概念
一主二从
环境配置
只配置从库,不配置主库
1 | info replication#查看当前库的信息 |
一主二从
默认情况下,每台Redis服务器都是主节点
我们一般情况只用配置从机就好
1 | slaveof x.x.x.x port |
真是的主从配置应该在配置文件中配置,这样的话是永久的
细节
主机可以设置值,从机只能读不能写。主机中的所有信息和数据都会被从机保存
测试:主机断开连接,从机依旧连接到主机,但是没有写操作。如果主机恢复了,从机会立刻恢复连接
如果使用命令行配置来配置主从,这时候重启了,就会变为主机。只要变为从机,就会立刻从主机中获取值
复制原理
层层链路
上一个M连接下一个S这时候也可以完成我们的主从复制
如果没有老大了,能不能自己选择一个老大呢?
如果主机断开了连接,我们可以使用slaveof no one
让自己变成主机,其他主机可以手动连接到这个新的主节点
如果老大修复了,只能重新配置
哨兵模式
概述
测试
配置哨兵文件sentinel.conf
1
sentinel monitor myredis ip port 1
后面的数字1,代表主机挂了,slave投票看让谁接替成为主机,票数最多的就会成为主机
启动哨兵
断开主机
如果Master节点断开了,就会从从机中选择一个服务器
如果主机此时回来了,只能归并到新的主机下,当做从机,这就是哨兵模式的规则
哨兵模式
优点:
- 哨兵集群基于主从复制模式,所有的主从配置有点他都有
- 主从可以切换,故障可以转移,系统可用性更好
- 哨兵模式是主从模式的升级,手动到自动,更加健壮
缺点:
- Redis不好在线扩容,达到上限,在线扩容十分麻烦
- 实现哨兵模式十分麻烦,有很多选择
Redis缓存穿透和雪崩
缓存穿透(查不到)
概念
解决方案
布隆过滤器
缓存空对象
缓存击穿(量太大,缓存过期)
概述
解决方案
缓存雪崩
概念
某个时间段,缓存集中过期失效,或者Redis宕机
解决方案