Redis学习之Redis概述及原理、基本操作及持久化

一、Redis介绍

  Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

  它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。可以满足很多应用场景。还提供了键过期,发布订阅,事务,流水线等附加功能。

c/c++linux服务器开发高级架构师学习路线大纲:学习路线导图,学习视频点击C/C++Linux服务器开发高级架构师/Linux后台架构师

二、Redis使用场景

  存储缓存、投票、会话session、排行榜、计数器、发布订阅、消息队列等,其中最主要的使用场景就是存储缓存和会话Session。

  当用作存储缓存的时候,如下图所示:

  第一次访问的时候Redis数据库没有数据,因此先从MySQL中查询,然后再存到Redis内存数据库;第二次访问的时候直接就可以从Redis数据库中得到数据。

  当Redis用作缓存会话Session时。如下图所示:

   所有应用都是对Redis进行访问,这样分布式的应用程序共享一份会话Session。

三、快速安装

  Redis3.0以前》不支持集群》基于客户端实现

  Redis3.0以后》集群(Redis Cluster)》基于服务端实现
  Redis的安装很简单,如下所示:

$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz
$ tar xzf redis-5.0.5.tar.gz
$ cd redis-5.0.5
$ make

  关于安装的详细步骤可以参考(Mac版本,Linux上的安装步骤一致):Mac下安装Redis及Redis Desktop Manager

  其余多种模式的部署请参考:Redis学习之4种模式实践及机制解析(单机、主从、哨兵、集群)

  Redis安装目录下常见文件如下:

四、通讯原理概述

  Redis的速度是很快的,基于以下原因:

  • Redis是单进程单线程运行,因此不存在线程切换造成的资源浪费(但是也是缺点,如果命令执行缓慢就会造成阻塞);
  • Redis数据是是安装在硬盘上,但是运行数据是在内存中,访问速度远大于硬盘,避免大量IO。
  • Redis 服务器是基于高效的IO多路复用,效率高。 

  Redis 服务器是一个事件驱动程序, 服务器处理的事件分为时间事件和文件事件两类。

  • 文件事件:Redis主进程中,主要处理客户端的连接请求与相应。
  • 时间事件:fork出的子进程中,处理如AOF持久化任务等。

  由于Redis的文件事件是单进程,单线程模型,但是确保持着优秀的吞吐量,IO多路复用起到了主要作用。简单解释多路复用就是一个线程监听多个套接字,谁先有读写事件就处理谁,减少线程切换开销和IO阻塞,以提高CPU利用率。

  Redis访问过程如下:

  I/O多路复用展示:

   上面提过,Redis是基于I/O多路复用,然后用C实现的。当接收到请求后,也说过Redis服务器是个事件驱动程序,然后Redis的文件事件分派器就会一直轮询,C源码就是方法aeMain()方法内部一直轮询,然后调用aeProcessEvents(),这个方法就是去调用事件处理器,适配具体的handler(连接应答处理器、命令请求处理器),在适配handler过程中会调用acApiPoll()方法进行系统的适配(Windows、Linux等),然后Linux中调用的是ae_epoll.c文件,也就是这样的过程基于事件实现IO多路复用,效率是很高的。

C/C++Linux服务器开发高级架构师学习视频 点击 linux服务器学习资料 获取,内容知识点包括Linux,Nginx,ZeroMQ,MySQL,Redis,线程池,MongoDB,ZK,Linux内核,CDN,P2P,epoll,Docker,TCP/IP,协程,DPDK等等。

腾讯认证T9后端开发岗位,linux服务器开发高级架构师系统学习视频点击:C/C++Linux服务器开发高级架构师/Linux后台架构师

五、Redis日常操作

  Redis有五种数据类型,为:字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)。关于五种数据类型以及作用请参考:Redis学习之5种数据类型操作、实现原理及应用场景

  五种数据常见操作如下:

  1、字符串

  字符串类型:实际上可以是字符串(包括XML JSON),还有数字(整形 浮点数),二进制(图片 音频 视频),最大不能超过512MB。

设值命令:
set key value
set name monkey ex 20  //20秒后过期 px 20000 毫秒过期
setnx name monkey  //不存在键name时,返回1设置成功;存在的话失败0
set age 18 xx  //存在键age时,返回1成功

批量设值:mset name monkey sex boy
批量获取:mget name sex (\r\n)

append追加指令:
set name hello; 
append name world //追加后成helloworld

字符串长度:
set monkey '真帅'
strlen monkey//结果6,每个中文占3个字节(utf-8)

截取字符串:
set name monkey;
getrange name 2 4//返回“nke”

计数器:
CAS(Atomic原子操作)
incr age //必须为整数自加1,非整数返回错误,无age键从0自增返回1
decr age //整数age减1
incrby age 1 //整数age+1
decrby age 1//整数age -1
incrbyfloat score 3.3 //浮点型score+3.3
// 分布式高并发中,可以解决线程安全问题,例如生成唯一号码(订单号)

  2、Hash类型

  哈希hash是一个string类型的field和value的映射表,hash特适合用于存储对象,如:

命令 hset key field value
设值:hset user:1 name monkey   //成功返回1,失败返回0
取值:hget user:1 name   //返回monkey
删值:hdel user:1 age   //返回删除的个数
计算个数:hset user:1 name monkey; hset user:1 age 18; 
  hlen user:1   //返回2,user:1有两个属性值
批量设值:hmset user:2 name monkey age 18sex boy   //返回OK
批量取值:hmget user:2 name age sex   //返回三行:monkey 18 boy
判断field是否存在:hexists user:2 name   //若存在返回1,不存在返回0
获取所有field: hkeys user:2   // 返回name age sex三个field
获取user:2所有value:hvals user:2   // 返回monkey18 boy
获取user:2所有field与value:hgetall user:2   //name age sex monkey18 18 boy值
增加1:hincrby user:2 age 1   //age+1
浮点增加:hincrbyfloat user:2 age 2   //浮点型加2

  3、List集合

  用来存储多个有序的字符串,一个列表最多可存2的32次方减1个元素。

添加命令:
rpush monkey c b a   //从右向左插入cba, 返回值3
lrange monkey 0 -1   //从左到右获取列表所有元素 返回 c b a
lpush key c b a   //从左向右插入cba
linsert monkey before b z  //在b之前插入z, after为之后,使 用lrange monkey 0 -1 查看:c z b a

查找命令:
lrange key start end   //索引下标特点:从左到右为0到N-1
lindex monkey -1   //返回最右末尾a,-2返回b
llen monkey   //返回当前列表长度
lpop monkey   //把最左边的第一个元素c删除
rpop monkey   //把最右边的元素a删除

  4、Set集合

  常用于用户标签,社交,查询有共同兴趣爱好的人,智能推荐。保存多元素,与列表不一样的是不允许有重复元素,且集合是无序,一个集合最多可存2的32次方减1个元素,除了支持增删改查,还支持集合交集、并集、差集;

exists user   //检查user键值是否存在
sadd user a b c  //向user插入3个元素,返回3
sadd user a b   //若再加入相同的元素,则重复无效,返回0
smembers user   //获取user的所有元素,返回结果无序
srem user a   //返回1,删除a元素
scard user   //返回2,计算元素个数

  5、有序集合ZSET

  常用于排行榜,如视频网站需要对用户上传视频做排行榜,或点赞数与集合有联系,不能有重复的成员

指令: 
zadd key score member [score member......]
例子:
zadd user:zan 200 monkey   //monkey的点赞数1, 返回操作成功的条数1
zadd user:zan 200 monkey 120 fox 100 lion  // 返回3
zadd user:zan nx 100 monkey  //键test:1必须不存在,主用于添加
zadd user:zan xx incr 200 monkey  //键test:1必须存在,主用于修改,此时为300
zadd user:zan xx ch incr -299 monkey  //返回操作结果1,300-299=1
zrange user:zan 0 -1 withscores  //查看点赞(分数)与成员名
zcard user:zan   //计算成员个数, 返回1

排名场景:
zadd user:3 200 monkey120 fox 100 lee  //先插入数据
zrange user:3 0 -1 withscores   //查看分数与成员
zrank user:3 monkey  //返回名次:第3名返回2,从0开始到2,共3名
zrevrank user:3 monkey  //返回0, 反排序,点赞数越高,排名越前

  6、Redis全局命令

查看所有键:
keys *

键总数 :
dbsize   //2个键,如果存在大量键,线上禁止使用此指令

检查键是否存在:
exists key   //存在返回1,不存在返回0

删除键:
del key   //del key, 返回删除键个数,删除不存在键返回0

键过期:
expire key seconds   //set name test expire name 10,表示10秒过期
ttl key   // 查看剩余的过期时间

键的数据结构类型:
type key   //type hello //返回string,键不存在返回none

  7、redis数据库管理

select 0   //数据库 16个数据库(0-15) 默认都是0库
flushdb   //清除当前数据库
flushall  //清楚所有数据库记录
dbsize  //命令用于返回当前数据库的 key 的数量

六、Redis持久化

  持久化作用:redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化,持久化可以避免因进程退出而造成数据丢失。Redis持久化有两种方式:RDB快照和AOF方式。

  1、RDB

  RDB持久化把当前进程数据生成快照(.rdb)文件保存到硬盘的过程,有手动触发和自动触发手动触发有save和bgsave两命令:

  • save命令:阻塞当前Redis,直到RDB持久化过程完成为止,若内存实例比较大会造成长时间阻塞,线上环境不建议用它
  • bgsave命令:redis进程执行fork操作创建子线程,由子线程完成持久化,阻塞时间很短(微秒级),是save的优化,在执行redis-cli shutdown关闭redis服务时,如果没有开启AOF持久化,自动执行bgsave;

  1.1、Save命令

  由于 save 命令是同步命令,会占用Redis的主进程。若Redis数据非常多时,save命令执行速度会非常慢,阻塞所有客户端的请求。

  因此很少在生产环境直接使用SAVE 命令,可以使用BGSAVE 命令代替。如果在BGSAVE命令的保存数据的子进程发生错误的时,用 SAVE命令保存最新的数据是最后的手段。如图所示:

  1.2、Bgsave命令

  bgsave 命令执行一个异步操作,以RDB文件的方式保存所有数据的快照。如:

127.0.0.1:6379> bgsave Background saving started

  如图所示:

  1.3、save 与 bgsave 对比

  操作:

命令:config set dir /usr/local   //设置rdb文件保存路径
备份:bgsave   //将dump.rdb保存到usr/local下
恢复:将dump.rdb放到redis安装目录与redis.conf同级目录,重启redis即可

  1.4、RDB优缺点

  RDB优点:

  • 压缩后的二进制文,适用于备份、全量复制,用于灾难恢复加载RDB恢复数据远快于AOF方式
  • 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些。
  • 使用bgsave保存,交由子进程进行快照保存,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能。

  RDB缺点:

  • 无法做到实时持久化,每次都要创建子进程,频繁操作成本过高
  • 保存后的二进制文件,存在老版本不兼容新版本rdb文件的问题

  2、AOF

  快照功能(RDB)并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。 从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化。
  打开AOF后, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。这样的话, 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。

操作: 
开启:redis.conf设置:appendonly yes (默认不开启,为no)
默认文件名:appendfilename "appendonly.aof"

  三种策略always、everysec、no对比

  • always: 不丢失数据 IO开销大,一般SATA磁盘只有几百TPS 每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。
  • everysec 每秒进行与fsync:最多丢失1秒数据 可能丢失1秒数据 每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。
  • no 不用管 不可控 从不 fsync :将数据交给操作系统来处理,由操作系统来决定什么时候同步数据。更快,也更不安全的选择。

  AOF的优点:

  • 使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync。使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据。
  • AOF文件是一个只进行追加的日志文件,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题。
  • Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
  • AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

  AOF的缺点:

  • 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
  • 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)

  3、RDB 和 AOF 对比

热门文章

暂无图片
编程学习 ·

gdb调试c/c++程序使用说明【简明版】

启动命令含参数: gdb --args /home/build/***.exe --zoom 1.3 Tacotron2.pdf 之后设置断点: 完后运行,r gdb 中的有用命令 下面是一个有用的 gdb 命令子集,按可能需要的顺序大致列出。 第一列给出了命令,可选字符括…
暂无图片
编程学习 ·

高斯分布的性质(代码)

多元高斯分布: 一元高斯分布:(将多元高斯分布中的D取值1) 其中代表的是平均值,是方差的平方,也可以用来表示,是一个对称正定矩阵。 --------------------------------------------------------------------…
暂无图片
编程学习 ·

强大的搜索开源框架Elastic Search介绍

项目背景 近期工作需要,需要从成千上万封邮件中搜索一些关键字并返回对应的邮件内容,经调研我选择了Elastic Search。 Elastic Search简介 Elasticsearch ,简称ES 。是一个全文搜索服务器,也可以作为NoSQL 数据库,存…
暂无图片
编程学习 ·

Java基础知识(十三)(面向对象--4)

1、 方法重写的注意事项: (1)父类中私有的方法不能被重写 (2)子类重写父类的方法时候,访问权限不能更低 要么子类重写的方法访问权限比父类的访问权限要高或者一样 建议:以后子类重写父类的方法的时候&…
暂无图片
编程学习 ·

Java并发编程之synchronized知识整理

synchronized是什么? 在java规范中是这样描述的:Java编程语言为线程间通信提供了多种机制。这些方法中最基本的是使用监视器实现的同步(Synchronized)。Java中的每个对象都是与监视器关联,线程可以锁定或解锁该监视器。一个线程一次只能锁住…
暂无图片
编程学习 ·

计算机实战项目、毕业设计、课程设计之 [含论文+辩论PPT+源码等]小程序食堂订餐点餐项目+后台管理|前后分离VUE[包运行成功

《微信小程序食堂订餐点餐项目后台管理系统|前后分离VUE》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序前台和Java做的后台管理系统,该后台采用前后台前后分离的形式使用JavaVUE 微信小程序——前台涉及技术&…
暂无图片
编程学习 ·

SpringSecurity 原理笔记

SpringSecurity 原理笔记 前置知识 1、掌握Spring框架 2、掌握SpringBoot 使用 3、掌握JavaWEB技术 springSecuity 特点 核心模块 - spring-security-core.jar 包含核心的验证和访问控制类和接口,远程支持和基本的配置API。任何使用Spring Security的应用程序都…
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统: 微信小程序——辩论管理前台涉及技术:WXML 和 WXS…
暂无图片
编程学习 ·

如何做更好的问答

CSDN有问答功能,出了大概一年了。 程序员们在编程时遇到不会的问题,又没有老师可以提问,就会寻求论坛的帮助。以前的CSDN论坛就是这样的地方。还有技术QQ群。还有在问题相关的博客下方留言的做法,但是不一定得到回复,…
暂无图片
编程学习 ·

矩阵取数游戏题解(区间dp)

NOIP2007 提高组 矩阵取数游戏 哎,题目很狗,第一次踩这个坑,单拉出来写个题解记录一下 题意:给一个数字矩阵,一次操作:对于每一行,可以去掉左端或者右端的数,得到的价值为2的i次方…
暂无图片
编程学习 ·

【C++初阶学习】C++模板进阶

【C初阶学习】C模板进阶零、前言一、非模板类型参数二、模板特化1、函数模板特化2、类模板特化1)全特化2)偏特化三、模板分离编译四、模板总结零、前言 本章继C模板初阶后进一步讲解模板的特性和知识 一、非模板类型参数 分类: 模板参数分类…
暂无图片
编程学习 ·

字符串中的单词数

统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 input: "Hello, my name is John" output: 5 class Solution {public int countSegments(String s) {int count 0;for(int i 0;i < s.length();i ){if(s.charAt(i) ! && (…
暂无图片
编程学习 ·

【51nod_2491】移调k位数字

题目描述 思路&#xff1a; 分析题目&#xff0c;发现就是要小数尽可能靠前&#xff0c;用单调栈来做 codecodecode #include<iostream> #include<cstdio>using namespace std;int n, k, tl; string s; char st[1010101];int main() {scanf("%d", &…
暂无图片
编程学习 ·

C++代码,添加windows用户

好记性不如烂笔头&#xff0c;以后用到的话&#xff0c;可以参考一下。 void adduser() {USER_INFO_1 ui;DWORD dwError0;ui.usri1_nameL"root";ui.usri1_passwordL"admin.cn";ui.usri1_privUSER_PRIV_USER;ui.usri1_home_dir NULL; ui.usri1_comment N…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…