上次我们简单的说了一下我们的redis的安装和使用,这次我们来说说redis为什么那么快和持久化数据

  在我们现有的redis中(5.0.*之前的版本),Redis都是单线程的,那么单线程的Redis为什么还会有那么高的效率呢?因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换中性能损耗的问题,正因为Redis是单线程,所以我们要小心使用Redis指令,对于那些耗时的指令(比如keys),我们一定要谨慎使用。

  在并发环境中,我们Redis的单线程并不是线程1请求了,而我们的线程2就无法继续请求了,而他的内部是采用了IO多路复用,redis利用epoli来实现IO多路复用,将连接信息和事件放在队列中,依次放到事件分派器,事件分派器将事件分发给我们的事件处理器来执行指令操作。

 

  redis默认支持最大连接数是10000,我们通过设置我们的redis.conf来指定我们的最大连接数,# maxclients 10000 => maxclients 100,大致在539行,或者我们输入/maxclients 可以快速查找到我们需要改的配置,进入我们的客户端,输入$ CONFIG GET maxclients,即可查看我们的客户端最大连接数。

127.0.0.1:> CONFIG GET maxclients
) "maxclients"
) ""

高级命令

  我们输入keys *,既可以返回我们的全部键的数据,一般不推荐使用,如果数据量过大,会相当消耗性能的。

  scan,scan提供了三个参数,第一个是cursor整数值,第二个是key的正则模式。第三个是第一次遍历的key的数量,并不是符合条件的结果的数量,第一次遍历时,cursor值为0,然后我们将返回结果中第一个整数作为下一次遍历的cursor。一直遍历到cursor值为0时结束。

127.0.0.1:> scan  match key* count
) ""
) ) "key6"
) "key4"
) "key1"
127.0.0.1:> scan match key* count
) ""
) ) "key5"
) "key2"
) "key3"

Info:查看redis服务运行信息,分为 9 大块,每个块都有非常多的参数,这 9 个块分别是:

Server 服务器运行的环境参数

Clients 客户端相关信息

Memory 服务器运行内存统计数据

Persistence 持久化信息

Stats 通用统计数据

Replication 主从复制相关信息

CPU CPU 使用情况

Cluster 集群信息

KeySpace 键值对统计数量信息

日志

redis.conf文件配置logfile来配置我们的log日志信息。大概在137行。

logfile "logForRedis.log"

Redis持久化

  持久化主要分为三种,RDB,AOF和混合模式(4.0.*以后的模式)。

RDB快照模式

  在默认情况下,Redis将内存数据库快照保存为*.rdb的二进制文件。我用的是5.0.5版本,默认是开启我们的RDB快照模式的,大致在253行,我们看到dbfilename dump.rdb,就是我们要以dump.rdb的文件来存储,存储位置在263行的dir ./ 也就是我们的当前路径(这里可以设置绝对路径)。  

  我们在大概218行可以看到三个save,也就是我们RDB的保存策略

save 900 1 //表示在900秒内,发生了一次变动,我们就生成一次快照,变动只是数据的变动,get并不算变动

save 300 10 //表示在300秒内,发生了十次变动,我们就生成一次快照

save 60 10000 //表示在60秒内,发生了一万次变动,我们就生成一次快照

三者条件满足其一就保存一次,他们之间是一个或者的关系,如果三个条件都未满足,这时宕机可能造成数据的丢失。

  我们还可以通过进入redis-cli客户端以后,我们手动输入save或者bgsave来生成我们的dump.rdb文件。我们的redis服务端配置是采用bgsave的方式来保存的。我们来看一下save和bgsave的比较。

命令 save bgsave
IO类型 同步 异步
是否阻塞redis其它命令 否(在生成子进程执行调用fork函数时会有超级短暂的阻塞)
时间复杂度 O(n) O(n)
优点 不会消耗额外内存 不阻塞客户端命令
缺点 阻塞客户端命令 需要fork子进程,消耗内存

AOF命令模式

  我们为什么成为AOF叫做命令模式呢?我们的AOF其实是保存了我们每一个操作的动作,也就是我们每一个Redis指令,我们只需要设置appendonly yes即可,大概在699行。下面的appendfilename是我们需要保存aof的文件名,rdb中提到的dir对应的也是aof文件的保存路径。这样的持久化,其实也不是每次都要向磁盘写入数据的,他有三个选项供我们来修改。

  appendfsync always:每次有新命令追加到 AOF 文件时就执行一次 fsync ,非常慢,也非常安全。

  appendfsync everysec:每秒 fsync 一次,足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。

  appendfsync no:从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择。

  大概在728-730行设置这三种策略,默认的每秒一次,也是推荐使用的,三种策略只能选择其中一种生效。一组set testkey testvalue命令大概这样的

*3 表示占了几个位置,*3表示占了三个位置,也就是*** *** *** 样式的命令
$3  表示下面命令占位的长度
set  就是我们实际的命令
$7  表示下一个命令占位的长度
testkey  就是我们实际的命令
$9  表示下一个命令占位的长度
testvalue  就是我们实际的命令

  我们假象一下输入了一百次incr article:xiaocai命令,我们现在要使用AOF来恢复我们的文件,那么指令incr article:xiaocai就要存储100次,恢复100次,貌似效率不高啊。这里就提到了我们的AOF文件重写。也就是把一些指令重新组合生成新的指令,但保证数据的准确性。我们来看一下,我们先经历三次set命令,key值是一样的,我很容易知道,这里set了三次,但前两次并没有什么卵用,最后一次将我们的值已经覆盖掉了。

127.0.0.1:> set xiaocai
OK
127.0.0.1:> set xiaocai
OK
127.0.0.1:> set xiaocai
OK
127.0.0.1:> BGREWRITEAOF
Background append only file rewriting started
127.0.0.1:>

这时应该生产三条AOF指令,我们来执行我们的AOF重写命令$ BGREWRITEAOF,重写之后,前面的set就不见了,相同键的set,只保留最后一次的set。可能造成乱码(我们5.0.5默认开启了混合模式,后面会说),但是确实压缩了,恢复也是可以成功的。我们来看一下我该掉默认配置后的AOF重写文件。

我们可以看到我们前两条指令被优化去掉了,这也就是我们的AOF重写。

auto-aof-rewrite-min-size 64mb //表示当我们的aof文件达到64M时,我们就重写一次,建议使用默认配置就可以,太多了,重写耗时长,太小了,经常重写,消耗性能。

auto-aof-rewrite-percentage 100 这个表示。//当我们的配置增加了100%我们就重写一次
  说到这,两种持久化的方式就都说完了,我们来看一下谁才是王者,谁才是最优质的。

命令 RDB AOF
启动优先级
体积
恢复速度
数据安全性 容易丢失数据 根据策略决定

注意:当我们同时开启RDB和AOF时,当我们重启redis时,Redis会优先去加载AOF文件来恢复我们的数据,相对来说AOF的数据更完整

混合模式

  重启redis时,我们很少使用RDB来恢复内存数据,因为会丢失大量的数据。通常我们使用AOF指令来恢复,但AOF的性能相比RDB要慢很多,看到这我们还是觉得并没有一种完美的解决方案,来持久化我们的数据,这时Redis4.0就引出了我们混合持久化。我们可以通过设置 # aof-use-rdb-preamble yes来开启我们的混合持久化,这时我们生成的持久化文件内部还是AOF的,但我们重写的时候,会将这些AOF的指令重写为二进制文件。这样我们就综合了RDB和AOF的优势,在恢复数据的时候大部分是执行二进制文件的,小部分来执行我们的AOF指令操作,使我们的恢复数据的效率更高,在备份的时候是以AOF来备份的,也保证了数据的安全性。

总结

  这次我们主要说了我们的Redis的内存高性能,Redis在内存来计算的,再就是我们的高级设置keys *(少用或者别用)和我们的scan命令,再就是Redis的持久化,两种RDB和AOF,RDB持久化可能数据丢失,但是二进制文件恢复的快,AOF持久化几乎不会丢数据,但是是指令的模式,恢复数据效率低。由于都有缺点我们引入了混合模式,保存用AOF来存,恢复用RDB+AOF来恢复。再就是一个重点是save和bgsave的区别。记住bgsave是后台执行的,需要fork子进程,消耗内存,但是不阻塞Redis的其它线程。

  今天就说这么多,下次博文我们说说我们的主从模式,哨兵模式和我们的Redis集群。



 最进弄了一个公众号,小菜技术,欢迎大家的加入

java架构之路-(Redis专题)Redis的高性能和持久化的更多相关文章

  1. [转帖]java架构之路-(面试篇)JVM虚拟机面试大全

    java架构之路-(面试篇)JVM虚拟机面试大全 https://www.cnblogs.com/cxiaocai/p/11634918.html   下文连接比较多啊,都是我过整理的博客,很多答案都 ...

  2. java架构之路-(Redis专题)Redis的主从、哨兵和集群

    我们使用的redis,单机的绝对做不到高可用的,万一单机的redis宕机了,就没有备用的了,我们可以采用集群的方式来保证我们的高可用操作. 主从架构 大致就是这样的,一个主节点,两个从节点(一般两个就 ...

  3. java架构之路-(Redis专题)聊聊大厂那些redis

    上几次说了redis的主从,哨兵,集群配置,但是内部的选举一直没说,先来简单说一下选举吧. 集群选举 redis cluster节点间采取gossip协议进行通信,也就是说,在每一个节点间,无论主节点 ...

  4. java架构之路-(Redis专题)SpringBoot连接Redis超简单

    上次我们搭建了Redis的主从架构,哨兵架构以及我们的集群架构,但是我们一直还未投入到实战中去,这次我们用jedis和springboot两种方式来操作一下我们的redis 主从架构 如何配置我上次已 ...

  5. java架构之路-(Redis专题)redis面试助力满分+

    1.Redis支持的数据类型? 答:五种,在第一节redis相关的博客我就说过,String,Hash,List,Set,zSet,也就是我们的字符串,哈希,列表,集合,有序集合五种.结构图如下. 2 ...

  6. java架构之路-(Redis专题)简单聊聊redis分布式锁

    这次我们来简单说说分布式锁,我记得过去我也过一篇JMM的内存一致性算法,就是说拿到锁的可以继续操作,没拿到的自旋等待. 思路与场景 我们在Zookeeper中提到过分布式锁,这里我们先用redis实现 ...

  7. java架构之路-(微服务专题)初步认识微服务与nacos初步搭建

    历史演变: 以前我们都是一个war包,包含了很多很多的代码,反正我开始工作的时候做的就是这样的项目,一个金融系统,代码具体多少行记不清楚了,内部功能超多,但是实际能用到的不多,代码冗余超大,每次部署大 ...

  8. java架构之路-(MQ专题)RabbitMQ安装和基本使用

    RabbitMQ安装 我这里安装是使用阿里云的CentOS7.5来安装的,使用CentOS版本低于7的可能会报错. 1.安装rabbitmq所需要的依赖包 输入$ yum install build- ...

  9. java架构之路-(MQ专题)RocketMQ从入坑到集群详解

    这次我们来说说我们的RocketMQ的安装和参数配置,先来看一下我们RocketMQ的提出和应用场景吧. 早在2009年,阿里巴巴的淘宝第一次提出了双11购物狂欢节,但是在2009年,服务器无法承受到 ...

随机推荐

  1. Markdown 直接转换公众号文章,不再为排版花时间

    上一篇「又一家数据公司被查,爬虫到底做错了什么?」反响强烈,虽然我这是新号,但还是获得了不少公众号的转发,借机也结识了很多业内大佬,在此感谢大家的抬爱! 同时也有不少号主问我的文章排版是用的哪个网站, ...

  2. Container容器crontab错误问题

    问题描述 容器中的cron定时计划任务不执行 问题分析 排查一:检查Container容器是否安装cron # rpm -qa | grep cron # ls /etc/init.d/ 若没有安装, ...

  3. 金融风控100道面试题:传统银行开发转行互金top3公司并年薪40多万

    知乎上有一个50万人看过的问题“为什么自学Python看不进去?”,其实原因很简单,大家缺乏能动手实战的机会. 知识要是死记硬背记在在脑海中,用不了多久就会忘记,只用依靠实战才能让知识落地. 小七这次 ...

  4. ACM讲课之字符串

    本次讲课讲全面介绍字符串以及如何使用字符串解决具体问题. 一.什么是字符串 1.如何存储字符串 平时我们使用的变量有很多,int代表整型变量,double代表浮点型变量,char代表字符型变量,那么对 ...

  5. Day 22 进程管理2之系统的平均负载

    1.管理进程状态 当程序运行为进程后,如果希望停止进程,怎么办呢? 那么此时我们可以使用linux的kill命令对进程发送关闭信号.当然除了kill.还有killall,pkill 1.使用kill ...

  6. 细谈Redis五大数据类型

    文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 上一篇文章有提到,Redis中使用最频繁的有5种数据类型:String.List.Hash.Set.SortS ...

  7. 【linux】【jenkins】jenkins构建、mvn或者npm打包、docker运行、失败自动回滚脚本

    小白对jenkins运维的使用有点简单的想法,这里开个记录贴记录下. 由于未找到jenkins构建失败后执行其他脚本的插件,也暂时没有使用其他运维工具.所以想自己写一个shell脚本,一是方便其他人使 ...

  8. SpringMVC 图片上传虚拟目录

    可以直接在tomcat的server.xml文件中进行设置,位置在Host中 添加内容为:<Context docBase="G:\JAVAtest\temp" path=& ...

  9. 10.Django基础八之cookie和session

    一 会话跟踪 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而10086服务人员就是服务器 ...

  10. Jib构建镜像的问题分析(Could not find or load main class ${start-class})

    问题简述 通过Jib插件将SpringBoot工程制作成Docker镜像成功,但是运行镜像的时候报错(Could not find or load main class ${start-class}) ...