Redis学习
NoSql历史发展
单机 MySQL 的美好时代
场景:网站访问量小,数据量小
瓶颈:无法解决数据量大、数据B树索引存储、单机数据库无法承受访问
[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-PgRPBIUN-1650359245555)(F:\ZHL\学习\学习笔记\Redis学习笔记\Redis资源\img\单机 MySQL 的美好时代.png)]
20世纪90年代,一个网站的访问量通常很小,可以很容易地用单个数据库处理。当时,静态网页更多,动态互动网站也不多。
DAL : Data Access Layer(数据访问层 – Hibernate,MyBatis)
1.数据量过大时,机器放不下。 2.数据索引(B Tree),当一台机器的内存无法存放时。 3.服务器无法承受访问量(读写混合)。
若满足上述1 or 数据库的整体架构只能在三个条件下重构。
Memcached(缓存) MySQL 垂直拆分
后来,随着访问量的增加,几乎大部分使用MySQL架构网站在数据库中开始出现性能问题,web程序不再只关注功能,而是追求性能。程序员开始使用缓存技术来缓解数据库的压力,优化数据库的结构和索引。一开始,通过文件缓存来缓解数据库压力更受欢迎,但当访问量继续增加时,多台web机器不能通过文件缓存共享,大量的小文件缓存也带来了相对较高的IO压力。此时,Memcached自然成为一种非常时尚的技术产品。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bihSg5F7-1650359245557)(https://gitee.com/AuroraLeVi/markdown/raw/master/img/Memcached(缓存)] MySQL 垂直拆分.png)
Memcached作为一个独立的分布式缓存服务器,它是多个web在Memcached在服务器上,根据hash多台算法Memcached随着缓存服务的扩展,出现了一致性hash为了解决缓存服务器的增加或减少,导致重新启动hash缓存失效的弊端很多。
Mysql主读写分离
由于数据库写入压力的增加,Memcached只能缓解数据库的读取压力。读写集中在一个数据库上,使数据库不堪重负。大多数网站开始使用复制技术来实现读写分离,以提高读写性能和读数库的可扩展性。Mysql的master-slave此时模式已成为网站的标配。
分库分表 水平拆分 mysql集群
场景:解决第二步瓶颈
瓶颈:数据爆炸性增长,包括数据类型、数据量、数据结构变化快、效率低
在Memcached高速缓存,MySQL主要基于复制、读写分离,此时MySQL由于主库的写作压力开始出现瓶颈,数据量继续飙升,MyISAM写数据时会使用表锁,高并发写数据时会出现严重的锁问题,大量高并发MySQL应用程序开始使用InnoDB引擎代替MyISAM。
这就是为什么 MySQL 在 5.6 版本后使用 InnoDB 作为默认存储引擎的原因 – MyISAM 写会锁表,InnoDB有行锁,发生冲突的几率低,并发性能高。
同时,使用分表库来缓解写作压力和数据增长的扩展也很流行。此时,分表分库已成为一项热门技术,是面试中的热门问题,也是业就在这个时候,MySQL推出了不稳定的表分区,也给技术实力一般的公司带来了希望。虽然MySQL推出了MySQL Cluster集群,但性能不能很好地满足互联网的要求,只是为高可靠性提供了很大的保证。
MySQL扩展瓶颈
MySQL数据库还经常存储一些大文本字段,导致数据库表非常大,数据库恢复非常慢,不容易快速恢复数据库。比如1000万4KB大小文本接近40GB如果这些数据可以从大小中提取MySQL省去,MySQL将变得非常的小。关系数据库非常强大,但它不能很好地处理所有的应用场景。MySQL扩展性差(需要复杂的技术),大数据下IO压力大,表结构难以改变,目前正在使用MySQL开发人员面临的问题。
如今
前面是企业级防火墙,后面是负载均衡主机(软负载:Nginx,硬负载:F5)在 web 在服务器集群之间进行调度,然后由特定的服务器集群进行调度 web 服务器(Tomcat)访问缓存,访问数据库。
什么是NOSql
首先要说的是,NoSql不代表"没有SQL"意思。实际上,这就是它的意思。"Not Only SQL"缩写。是一种全新的数据库概念,一般指非关系数据库。
随着web2.互联网的诞生!传统的关系数据库很难处理web2.0时代!尤其是超大规模高并发社区! 暴露出许多难以克服的问题,NoSQL在当今大数据环境下发展迅速,Redis它是发展最快的技术,也是我们现在必须掌握的技术!
NoSQL常见观点如下:
- 不要使用关系模型
- 集群运行良好
- 主要是开源
- 21世纪适合建设Web应用
- 非模式化
为什么使用NoSql
许多数据类型,如用户的个人信息、社交网络和地理位置。这些数据类型的存储不需要固定格式!水平扩展不需要多月的操作 ! Map<String,Object>
用键值对来控制!
今天我们可以通过第三方平台(如:Google,Facebook等等)可以很容易地访问和捕获数据。用户的个人信息、社交网络、地理位置、用户生成的数据和操作日志都翻了一番。如果我们想挖掘这些用户数据,那么SQL这些应用不再适用于数据库, NoSQL 数据库的发展可以很好地处理这些大数据。
Nosql的全称是Not Only Sql,有人早起就提出了这个概念,2009年更受欢迎。
Nosql指非关系数据库,我们常用的是关系数据库。就像我们常用的一样mysql,sqlserver一样,这些数据库一般用来存储重要信息,应对普通的业务是没有问题的。然而,随着互联网的快速发展,传统的关系数据库无法应对大规模、大流量和高并发性。就在这个时候,Nosql快速发展。
- 关系数据库通过外部关联建立表与表之间的关系。
- 非关系数据库通常是指数据以对象的形式存储在数据库中,而对象之间的关系是由每个对象自身的属性决定的。
- 在非关系数据库中,我们查询一个数据,结果是一个数组,在关系数据库中,查询一个数据结果是一个对象。
关系数据库最典型的数据结构是由二维表及其联系组成的数据组织。
严格来说,非关系数据库不是数据库,而是数据结构化存储方法的集合,可以是文档或键值对等。
NoSQL优缺点
优点
- 高可扩展性
- 分布式计算
- 低成本
- 架构的灵活性、半结构化数据
- 没有复杂的关系
扩展方便(数据无关,扩展好) 大数据量,高性能(Redis 一秒写8万次,读11万次,NoSQL记录级缓存是一种细粒度缓存 能比较高! 各种类型的数据(不需要提前设计数据库!随时随用!如果是数据量很大的表,很多人就没有了 法律设计!
缺点
- 没有标准化
- 查询功能有限(到目前为止)
- 最终一致性是不直观的程序
关系数据库和NoSQL的区别?
RDBMS
高度组织化结构化数据
结构化查询语言(SQL)
数据和关系都存储在单独的表中
数据操纵语言,数据定义语言
严格的一致性
基础事务
ACID关系型数据库遵循ACID规则
事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性:
A (Atomicity) 原子性
原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。比如银行转账,从A账户转100元至B账户,分为两个步骤:1)从A账户取100元;2)存入100元至B账户。这两步要么一起完成,要么一起不完成,如果只完成第一步,第二步失败,钱会莫名其妙少了100元。
C (Consistency) 一致性
一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。
I (Isolation) 独立性
所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。比如现有有个交易是从A账户转100元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的100元的
D (Durability) 持久性
持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。
NoSQL
代表着不仅仅是SQL
没有声明性查询语言
没有预定义的模式
键 - 值对存储,列存储,文档存储,图形数据库
最终一致性,而非ACID属性
非结构化和不可预知的数据
CAP定理和BASE原则(异地多活)
高性能、高可用、高可扩展
CAP定理
高性能,高可用性和可伸缩性
分布式数据库中的CAP原理(了解)
Consistency(一致性), 数据一致更新,所有数据变动都是同步的
Availability(可用性), 好的响应性能
Partition tolerance(分区容错性) 可靠性
P: 系统中任意信息的丢失或失败不会影响系统的继续运作。
定理:任何分布式系统只可同时满足二点,没法三者兼顾。
CAP理论的核心
一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求。
C:强一致性
A:高可用性
P:分布式容忍性
CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
CAP理论就是说在分布式存储系统中,最多只能实现上面的两点。
而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡,没有NoSQL系统能同时保证这三点。
举例:
CA:传统Oracle数据库
AP:大多数网站架构的选择
CP:Redis、Mongodb
注意:分布式架构的时候必须做出取舍。
一致性和可用性之间取一个平衡。多余大多数web应用,其实并不需要强一致性。因此牺牲C换取P,这是目前分布式数据库产品的方向。
当下NoSQL的经典应用
当下的应用是 SQL 与 NoSQL 一起使用的。
代表项目:阿里巴巴商品信息的存放。去 IOE 化。
I 是指 IBM 的小型机;O 是指 Oracle 数据库;M 是指 EMC的存储设备。
大数据时代的3V&3高
3V
- 海量(Volume)
- 多样(Variety)
- 实时(Velocity)
3高
- 高并发
- 高可扩(随时水平拆分)
- 高性能
3高是对程序的要求,3V是问题的描述(数据等)。要解决3V问题,便需要程序的3高。
数据架构分析
思考问题:一个大型网站上的这么多内容都是放在一个数据库中的吗?
# 存储商品的基本信息
名称、价格、商家信息 ……
这些关系型数据库就都可以解决了——MySQL / Oracle
# 商品的描述、评论(文字较多的)
文档型数据库:MongoDB
# 图片
分布式文件系统 FastDFS
淘宝的:TFS
Google的:GFS
Hadoop的:HDFS
阿里云的:OSS
# 商品的关键字(搜索)
搜索引擎 SOLR 、Elastic Search
淘宝用的 : ISearch
# 商品热门的波段信息(秒杀)
内存数据库
Redis、Tair、MemCache
# 商品的交易,外部的支付接口
三方应用
难点:
数据类型多样性。
数据源多样性和变化重构。
数据源改造而服务平台不需要大面积重构。
NoSql四大分类
键值数据库
键值数据库就像在传统语言中使用的哈希表。这个表中有一个特定的键和一个指针指向特定的数据。可以通过key来添加、查询或者删除数据,鉴于使用主键访问,所以会获得不错的性能及扩展性。
相关产品:Redis、Riak、SimpleDB、Chordless、Scalaris、Memcached
应用:内容缓存
适用的场景:储存用户信息,比如会话、配置文件、参数、购物车等等。这些信息一般都和ID(键)挂钩,这种情景下键值数据库是个很好的选择。
不适用场景:
-
取代通过键查询,而是通过值来查询。Key-Value数据库中根本没有通过值查询的途径。
-
需要储存数据之间的关系。在Key-Value数据库中不能通过两个或以上的键来关联数据。
-
事务的支持。在Key-Value数据库中故障产生时不可以进行回滚。
优点:扩展性好、灵活性好、大量写操作时性能高
缺点:无法存储结构化信息、条件查询效率较低
有谁在使用:GitHub (Riak)、BestBuy (Riak)、Twitter (Redis和Memcached)、StackOverFlow (Redis)、 Instagram(Redis)、Youtube (Memcached)、Wikipedia(Memcached)
文档数据库
文档型数据库的灵感是来自于Lotus Notes办公软件的,而且它同第一种键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高。每个文档都是自包含的数据单元,是一系列数据项的集合。
每个数据项都有一个名称与对应的值,值既可以是简单的数据类型,如字符串、数字和日期等;也可以是复杂的类型,如有序列表和关联对象。数据存储的最小单位是文档,同一个表中存储的文档属性可以是不同的,数据可以使用XML、JSON或者JSONB等多种形式存储。
bson格式(和json类似)
相关产品:MongoDB、CouchDB、ThruDB、CloudKit、Perservere、Jackrabbit
MongoDB介绍:
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
应用:存储、索引并管理面向文档的数据或者类似的半结构化数据
适用的场景:
- 日志。企业环境下,每个应用程序都有不同的日志信息。Document-Oriented数据库并没有固定的模式,所以我们可以使用它储存不同的信息。
- 分析。鉴于它的弱模式结构,不改变模式下就可以储存不同的度量方法及添加新的度量。
不适用场景:
- 在不同的文档上添加事务。Document-Oriented数据库并不支持文档间的事务,如果对这方面有需求则不应该选用这个解决方案。
优点:性能好、灵活性高、复杂性低、数据结构灵活
缺点:缺乏统一的查询语言
有谁在使用:SAP (MongoDB)、Codecademy (MongoDB)、Foursquare (MongoDB)、NBC News (RavenDB)
列族数据库
这部分数据库通常是用来应对分布式存储的海量数据。键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。
举个例子,如果我们有一个Person类,我们通常会一起查询他们的姓名和年龄而不是薪资。这种情况下,姓名和年龄就会被放入一个列族中,而薪资则在另一个列族中。
相关产品:BigTable、HBase、Cassandra、HadoopDB、GreenPlum、PNUTS
应用:分布式数据存储与管理
适用的场景
- 日志。因为我们可以将数据储存在不同的列中,每个应用程序可以将信息写入自己的列族中。
- 博客平台。我们储存每个信息到不同的列族中。举个例子,标签可以储存在一个,类别可以在一个,而文章则在另一个。
不适用场景:
-
如果我们需要ACID事务。Cassandra就不支持事务。
-
原型设计。如果我们分析Cassandra的数据结构,我们就会发现结构是基于我们期望的数据查询方式而定。在模型设计之初,我们根本不可能去预测它的查询方式,而一旦查询方式改变,我们就必须重新设计列族。
优点:查找速度快、可扩展性强、容易进行分布式扩展、复杂性低
有谁在使用:Ebay (Cassandra)、Instagram (Cassandra)、NASA (Cassandra)、Twitter (Cassandra and HBase)、Facebook (HBase)、Yahoo!(HBase)
图形数据库
图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数据接口或者查询API。
图数据库允许我们将数据以图的方式储存。实体会被作为顶点,而实体之间的关系则会被作为边。比如我们有三个实体,Steve Jobs、Apple和Next,则会有两个“Founded by”的边将Apple和Next连接到Steve Jobs。
相关产品:Neo4J、OrientDB、InfoGrid、GraphDB
应用:大量复杂、互连接、低结构化的图结构场合,如社交网络、推荐系统等
适用的场景:
- 在一些关系性强的数据中
- 推荐引擎。如果我们将数据以图的形式表现,那么将会非常有益于推荐的制定
不适用场景:
不适合的数据模型。图数据库的适用范围很小,因为很少有操作涉及到整个图。
不是存图形,存的是关系。比如:朋友圈社交网络,广告推荐。
优点:灵活性高、支持复杂的图形算法、可用于构建复杂的关系图谱
缺点:复杂性高、只能支持一定的数据规模
**有谁在使用:**Adobe (Neo4J)、Cisco (Neo4J)、T-Mobile (Neo4J)
总结——NoSQL数据库在以下的这几种情况下比较适用:
1、数据模型比较简单;
2、需要灵活性更强的IT系统;
3、对数据库性能要求较高;
4、不需要高度的数据一致性;
5、对于给定key,比较容易映射复杂值的环境。
Redis入门
Redis(Remote Dictionary Server),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,支持丰富的数据类型,如:String、list、set、zset、hash,并提供多种语言的API。
redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。
区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis作用
将一些热点数据存储到Redis中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销。
1、内存存储、持久化
由于Redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就全丢失了,于是需要开启redis的持久化功能,将数据保存到磁盘上,当redis重启后,可以从磁盘中恢复数据。
Redis的两种持久化RDB和AOF
RDB——数据快照(Snapshot)
。
redis是一个内存数据库,数据保存在内存中,但是我们都知道内存的数据变化是很快的,也容易发生丢失(内存断电即失)。
而Redis两种提供了持久化的机制,分别是RDB(Redis DataBase)和AOF(Append Only File)。
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。
在我们安装了redis之后,所有的配置都是在redis.conf文件中,里面保存了RDB和AOF两种持久化机制的各种配置。
既然RDB机制是通过把某个时刻的所有数据生成一个快照来保存,那么就应该有一种触发机制,去实现这个过程。
对于RDB来说,提供了三种机制:save
、bgsave
、自动化。我们分别来看一下:
1、save触发方式
save
命令执行一个同步操作,以RDB文件的方式保存所有数据的快照。
127.0.0.1:6379> save
OK
该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。具体流程如下:
由于
save
命令是同步命令,会占用Redis的主进程。若Redis数据非常多时,save
命令执行速度会非常慢,阻塞所有客户端的请求。
执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取。
因此很少在生产环境直接使用SAVE 命令,可以使用BGSAVE 命令代替。如果在BGSAVE命令的保存数据的子进程发生错误的时,用 SAVE命令保存最新的数据是最后的手段。
2、bgsave触发方式
Redis是单进程的,所以bgsave
只能Fork一个子进程,而不是创建一个线程处理。
bgsave
命令执行一个异步操作,以RDB文件的方式保存所有数据的快照。
127.0.0.1:6379> bgsave
Background saving started
Redis使用Linux系统的fock()
生成一个子进程来将DB数据保存到磁盘,主进程继续提供服务以供客户端调用。如果操作成功,可以通过客户端命令LASTSAVE来检查操作结果。
执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体流程如下:
实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。
save
与 bgsave
对比
save | bgsave | |
---|---|---|
IO类型 | 同步 | 异步 |
阻塞? | 是 | 是(阻塞发生在fock(),通常非常快) |
复杂度 | O(n) | O(n) |
优点 | 不会消耗额外的内存 | 不阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 需要fock子进程,消耗内存 |
3、自动触发
除了手动执行 save
和 bgsave
命令实现RDB持久化以外,Redis还提供了自动自动生成RDB的方式。可以通过配置文件对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动进行数据集保存操作。
比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动进行数据集保存操作:
save 60 1000
自动触发是由我们的配置文件来完成的。在redis.conf配置文件中,里面有如下配置,我们可以去设置:
**①save:**这里是用来配置触发 Redis的 RDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘。
- 比如“save m n”。表示m秒内数据集存在n次修改时,自动触发bgsave。
默认如下配置:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。
不需要持久化,那么你可以注释掉所有的 save 行来停用保存功能。
**②stop-writes-on-bgsave-error :**默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。如果Redis重启了,那么又可以重新开始接收数据了。
# bgsave发生错误时是否停止写入,通常为yes
stop-writes-on-bgsave-error yes
**③rdbcompression ;**默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。
# rdb文件是否使用压缩格式
rdbcompression yes
**④rdbchecksum :**默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
# 是否对rdb文件进行校验和检验,通常为yes
rdbchecksum yes
**⑤dbfilename :**设置快照的文件名,默认是 dump.rdb。
# RDB持久化文件名
dbfilename dump-<port>.rdb
**⑥dir:**设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。
# 数据持久化文件存储目录
dir /var/lib/redis
我们可以修改这些配置来实现我们想要的效果。
RDB 的优势和劣势
①、优势
(1)RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复,可以按每小时或每日来备份,方便从不同的版本恢复数据。
(2)生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
(3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
②、劣势
(1)如果Redis不及时保存RDB文件,会造成数据的丢失。例如系统突然断电,但未来得及保存数据。即使你设置更多的Save point,也无法保证100%的数据不丢失。
(2) RDB经常需要fork子进程去执行,但如果再大量数据的情况下,这个fork操作会非常耗CPU资源的。对比AOF虽然也是fork,但是它的数据保存处理是可以控制的,不需要全量保存。
AOF——日志追加(Append-Only)
全量备份总是耗时的,有时候我们提供一种更加高效的方式AOF,工作机制很简单,redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录。
AOF:通过将发送到服务器的写操作命令记录下来,形成AOF文件,文件默认名称是appendonly.aof,可以通过appendfilename来指定文件名称。你可以通过配置文件打开AOF功能。
原理看下图:
每当有一个写命令过来时,就直接保存在我们的AOF文件中。
AOF启用
AOF默认是关闭的。打开redis.conf配置文件,找到appendonly no
改成appendonly yes
。
appendonly yes
AOF和RDB是可以共存的,只要保存的文件名不冲突。
AOP重写
AOF的原理是直接把用户插入到服务器的命令追加到结尾,那么文件会越来越大,一些重复的写命令也会越来越多,这时,我们可以利用bgrewriteaof
命令来重写AOF,重写的配置如下:
配置名 | 含义 |
---|---|
auto-aof-rewrite-min-size | 触发AOF文件执行重写的最小尺寸 |
auto-aof-rewrite-percentage | 触发AOF文件执行重写的增长率 |
统计名 | 含义 |
---|---|
aof_current_size | AOF文件当前尺寸(字节) |
aof_base_size | AOF文件上次启动和重写时的尺寸(字节) |
AOF重写自动触发机制,需要同时满足下面两个条件:
- aof_current_size > auto-aof-rewrite-min-size
- (aof_current_size - aof_base_size) * 100 / aof_base_size > auto-aof-rewrite-percentage
auto-aof-rewrite-percentage 100 # aof文件大小超过上次重写时文件大小的百分之几开始重写,如果之前没有写过,则根据启动时文件大小。当文件增长100%(一倍)时候,自动重写。
auto-aof-rewrite-min-size 64mb # 限制允许重写时的最小文件大小,如果小于该大小,不会自动重写。
# 从Redis 2.6起你可以通过INFO命令查看AOF重写执行情况。
当AOF文件的体积大于64Mb,并且AOF文件的体积比上一次重写之久的体积大了至少一倍(100%)时,Redis将执行 bgrewriteaof 命令进行重写。
Redis bgrewriteaof 命令用于异步执行一个 AOF(AppendOnly File)文件重写操作。重写会创建一个当前AOF文件的体积优化版本。
AOF 重写由 Redis 自行触发,bgrewriteaof 仅仅用于手动触发重写操作。
即使 bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的AOF文件在 bgrewriteaof 成功之前不会被修改。
- 减少磁盘占用量
- 加速数据恢复
重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。
AOF fsync同步规则
AOF在同步内存数据到磁盘上时,并不是马上把文件写如到磁盘中,而是先把文件缓存到系统,然后每隔30秒将文件写入到磁盘中,我们可以在配置文件中配置同步的策略。
通过配置文件配置 Redis 多久才将数据 fsync 到磁盘一次。
fsync()是一个系统调用函数,告诉操作系统把数据写到硬盘上,而不是缓存更多数据才写到硬盘。这样的调用可以及时保存数据到硬盘上。
appendfsync always #每次都同步,保证数据不会丢失,但会慢
appendfsync everysec #每秒同步,系统默认同步策略
appendfsync no #不主动同步,由操作系统决定,快,但数据容易丢失
每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。
每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。 推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。
从不 fsync :将数据交给操作系统来处理,由操作系统来决定什么时候同步数据。更快,也更不安全的选择。
AOF破损文件的修复
如果redis在append数据到AOF文件时,机器宕机了,可能会导致AOF文件破损。这时用redis-check-aof --fix
命令来修复破损的AOF文件。
AOF运行原理 - 恢复
AOF优缺点
优点:
(1)AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。
(2)AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
(3)AOF文件是一个值追加日志的文件,即使服务宕机未写入完整的命令,也可以通过redis-check-aof
工具修复这些问题。
(4)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
(5) AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据。
缺点:
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大。
(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的。
(3)以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。
RDB和AOF对比
2、效率高、可以用于高速缓存
3、发布订阅系统
4、地图信息分析
5、计时器、计数器(浏览量 incr decre)
Redis特性
一:速度快
Redis所有数据是存放在内存中的,Redis源代码采用C语言编写,距离底层操作系统更近,执行速度相对更快,Redis使用单线程架构,避免了多线程可能产生的竞争开销。
二:基于K_V的数据结构
几乎所有的编程语言都提供了类似字典的功能,例如Java里的map、Python里的dict,类似于这种组织数据的方式叫作基于键值的方式,与很多键值对数据库不同的是,Redis中的值不仅可以是字符串,而且还可以是具体的数据结构,这样不仅能便于在许多应用场景的开发,同时也能够提高开发效率。
三:功能相对丰富
除了支持五种数据结构之外,Redis对外提供了键过期的功能,可以用来实现缓存,提供了发布订阅功能,可以用来实现简单的消息系统,解耦业务代码,支持Lua脚本,提供了简单的事务功能(不能rollback),提供了Pipeline功能,客户端能够将一批命令一次性传输到Server端,减少了网络开销。
Redis一共支持五种数据类型:String(字符串)、hash(哈希)、list(列表)、set(集合)和zset(sorted set有序集合)
- String(字符串):Redis最基本的数据类型,一个键对应一个值,一个键值最大存储512MB
- Hash(哈希):hash是一个键值对的集合,是一个String类型的field和value的映射表,适合用于存储对象
- List(列表):是redis的简单的字符串列表,按插入顺序排序
- Set(集合):是String字符串类型的无序集合,也不可重复
- ZSet(sorted set 有序集合)是String类型的有序集合,也不可重复。有序集合中的每个元素都需要指定一个分数,根据分数对元素进行升序排序。
四:简单稳定
Redis源码共六万行,但是不代表它不稳定。Redis不需要依赖于操作系统中的类库(例如Memcache需要依赖libevent这样的系统类库),Redis自己实现了事件处理的相关功能。
五:客户端语言多
Redis提供了简单的TCP通信协议,这样使得很多编程语言可以很方便的接入Redis。
六:持久化
Redis提供两种持久化方案AOF和RDB。
七:主从复制
主服务器上只进行写的操作,在从的服务器上进行读的操作,主服务器(master)执行添加、修改、删除,从服务器执行查询。
八:高可用和分布式
Redis从2.8版本正式提供了高可用实现哨兵模式,可以保证Redis节点的故障发现和故障自动转移,Redis从3.0版本后开始支持集群模式。
Redis安装
Windows下安装
Redis官网
Redis的GitHub
安装后,打开文件夹,内容如下:
启动服务端:打开一个 窗口 使用 cd 命令切换目录到 运行:
redis-server.exe redis.windows.conf
如果想方便的话,可以把 redis 的路径加到系统的环境变量里,这样就省得再输路径了,后面的那个 redis.windows.conf 可以省略,如果省略,会启用默认的。输入之后,会显示如下界面:
这时候另启一个 cmd 窗口,原来的不要关闭,不然就无法访问服务端了。
启动客户端:切换到 redis 目录下运行:
启动 redis 服务器,打开终端并输入命令 redis-cli,该命令会连接本地的 redis 服务。
redis-cli.exe -h 127.0.0.1 -p 6379
如果需要在远程 redis 服务上执行命令,同样我们使用的也是 命令。
语法
redis-cli -h host -p port -a password
有时候会有中文乱码,要在 redis-cli 后面加上
--raw
redis-cli --raw
1、设置Redis服务
由于上面虽然启动了redis,但是只要一关闭cmd窗口,redis就会消失。所以要把redis设置成windows下的服务。
也就是设置到这里,首先发现是没用这个Redis服务的。
2、设置服务命令
redis-server --service-install redis.windows-service.conf --loglevel verbose
输入命令之后没有报错,表示成功了,刷新服务,会看到多了一个Redis服务。
启动报错1067的话,在刚才redis的目录下新建文件夹Logs然后再次启动即可。
3、常用的redis服务命令
卸载服务:redis-server --service-uninstall
开启服务:redis-server --service-start
停止服务:redis-server --service-stop
4、启动服务
5、测试Redis
安装测试成功。
这里只是做简单的安装,部署服务使用,更深入的使用可以去redis中文网看看 http://www.redis.net.cn/,博客园也有很多深入使用方法,在这做个抛砖引玉吧。
Linux下安装
1、下载Redis安装包
https://redis.io/download,下载最新稳定版本。
把下载好的Redis压缩包,上传到Linux的 /home/redis 文件目录下
安装包一般放到/home目录下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-65lCdx1F-1650359245780)(F:\ZHL\学习\学习笔记\Redis学习笔记\Redis资源\img\使用Xftp将下载好的Redis安装包复制到远程服务器.png)]
2、解压Redis安装包
进入到/ home/redis 文件目录中,解压 redis-6.2.6.tar.gz,并把redis-6.2.6移动到 /opt 目录下
程序一般放到opt目录下
[root@lw ~]# cd /home # 进入home文件目录
[root@lw home]# ls # 查看目录
redis www
[root@lw home]# cd redis # 进入home/redis文件目录
[root@lw redis]# ls
redis-6.2.6.tar.gz
[root@lw redis]# mv redis-6.2.6.tar.gz /opt # 把redis-6.2.6.tar.gz移动到/opt目录下
[root@lw redis]# cd /opt # 进入opt目录
[root@lw opt]# ls
redis-6.2.6.tar.gz rh
[root@lw opt]# tar -zxvf redis-6.2.6.tar.gz # 解压redis安装包
redis-6.2.6/
redis-6.2.6/.github/
redis-6.2.6/.github/ISSUE_TEMPLATE/
...
[root@lw opt]# ls
redis-6.2.6 redis-6.2.6.tar.gz rh
下载完成后需要将压缩文件解压,输入以下命令解压到当前目录
tar -zxvf redis-6.2.6.tar.gz # 解压redis安装包
解压后在根目录上输入ls 列出所有目录会发现与下载redis之前多了一个redis-6.2.6.tar.gz文件和redis-6.2.6的目录。
3、进入解压后的文件
[root@lw opt]# cd /opt
[root@lw opt]# ls
redis-6.2.6 redis-6.2.6.tar.gz rh
[root@lw opt]# cd redis-6.2.6
[root@lw redis-6.2.6]# ls
00-RELEASENOTES CONTRIBUTING INSTALL README.md runtest-cluster sentinel.conf TLS.md
BUGS COPYING Makefile redis.conf runtest-moduleapi src utils
CONDUCT deps MANIFESTO runtest runtest-sentinel tests
redis.conf
配置文件最为重要
4、基本的环境安装
4.1、安装gcc
由于redis是由C语言编写的,它的运行需要C环境,因此我们需要先安装gcc。安装命令如下:
yum install gcc-c++
4.2、编译
进入到 /opt 目录下,对redis程序进行编译与安装
进行redis编译
接下来控制台会输出各种编译过程中输出的内容
进行redis安装
输入以下命令:
make PREFIX=/usr/local/redis install
这里多了一个关键字 这个关键字的作用是编译的时候用于指定程序存放的路径。
比如我们现在就是指定了redis必须存放在
/usr/local/redis
目录。假设不添加该关键字Linux会将:
可执行文件存放在
/usr/local/bin
目录。库文件会存放在
/usr/local/lib
目录。配置文件会存放在
/usr/local/etc
目录。其他的资源文件会存放在
usr/local/share
目录。这里指定号目录也方便后续的卸载,后续直接
rm -rf /usr/local/redis
即可删除redis。
5、redis默认安装目录
redis默认安装目录
/usr/local/bin
6、将redis配置文件复制到我们的当前目录下
[root@lw bin]# mkdir redisconfig # 新建存放redis.conf配置文件的目录
[root@lw bin]# cp /opt/redis-6.2.6/redis.conf redisconfig # 复制redis配置文件到我们当前目录
[root@lw bin]# cd redisconfig
[root@lw redisconfig]# ls
redis.conf
之后,就采用这个配置文件进行启动!
7、redis默认不是后台启动的,修改配置文件
1、设置redis.conf中daemonize为yes,确保守护进程开启,也就是在后台可以运行。
# vi编辑/usr/local/bin/redisconfig目录里面的redis.conf文件
[root@localhost /]# vi /usr/local/bin/redisconfig/redis.conf
通过/daemonize
查找到属性,默认是no
,更改为yes
即可。
比较重要的配置项:
daemonize no #redis进程是否以守护进程的方式运行,yes为是,no为否(不以守护进程的方式运行会占用一个终端) pidfile /var/run/redis.pid #指定redis进程的PID文件存放位置 port 6379 #redis进程的端口号 bind 127.0.0.1 #绑定的主机地址 timeout 300 #客户端闲置多长时间后关闭连接,默认此参数为0即关闭此功能 loglevel verbose #redis日志级别,可用的级别有debug.verbose.notice.warning logfile stdout #log文件输出位置,如果进程以守护进程的方式运行,此处又将输出文件设置为stdout的话,就会将日志信息输出到/dev/null里面去了 databases 16 #设置数据库的数量,默认为0可以使用select <dbid>命令在连接上指定数据库id save <seconds> <changes> #指定在多少时间内刷新次数达到多少的时候会将数据同步到数据文件; rdbcompression yes #指定存储至本地数据库时是否压缩文件,默认为yes即启用存储; dbfilename dump.db #指定本地数据库文件名 dir ./ #指定本地数据问就按存放位置; slaveof <masterip> <masterport> #指定当本机为slave服务时,设置master服务的IP地址及端口,在redis启动的时候他会自动跟master进行数据同步 masterauth <master-password> #当master设置了密码保护时,slave服务连接master的密码; requirepass footbared #设置redis连接密码,如果配置了连接密码,客户端在连接redis是需要通过AUTH<password>命令提供密码,默认关闭 maxclients 128 #设置同一时间最大客户连接数,默认无限制;redis可以同时连接的客户端数为redis程序可以打开的最大文件描述符,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息 maxmemory<bytes> #指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区 appendonly no #指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no appendfilename appendonly.aof #指定跟新日志文件名默认为appendonly.aof appendfsync everysec #指定更新日志的条件,有三个可选参数no:表示等操作系统进行数据缓存同步到磁盘(快),always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全), everysec:表示每秒同步一次(折衷,默认值);
配置项名称 | 配置项值范围 | 说明 |
---|---|---|
daemonize | yes、no | yes表示启用守护进程,默认是no即不以守护进程方式运行。其中Windows系统下不支持启用守护进程方式运行 |
port | 指定 Redis 监听端口,默认端口为 6379 | |
bind | 绑定的主机地址,如果需要设置远程访问则直接将这个属性备注下或者改为bind * 即可,这个属性和下面的protected-mode控制了是否可以远程访问 。 | |
protected-mode | yes 、no | 保护模式,该模式控制外部网是否可以连接redis服务,默认是yes,所以默认我们外网是无法访问的,如需外网连接rendis服务则需要将此属性改为no。 |
timeout | 300 | 当客户端闲置多长时间后关闭连接,如果指定为 0,表示关闭该功能 |
loglevel | debug、verbose、notice、warning |