文档章节

Redis

百花
 百花
发布于 2017/02/23 16:04
字数 4163
阅读 1
收藏 0

特性

  • 内存式KV数据库
  • 内部有6种数据结构,SDS、链表、字典、跳跃表、整数集合、压缩列表
  • 由6种数据结构保证成5中对外的对象:字符串、列表、哈希表、集合、有序集合

特性

  • 内存式KV数据库
  • 内部有6种数据结构,SDS、链表、字典、跳跃表、整数集合、压缩列表
  • 由6种数据结构保证成5中对外的对象:字符串、列表、哈希表、集合、有序集合
  • redis 串行的执行redis命令
  • redis 被设计为:执行任何redis命令必须有对应的redis客户端状态
  • redis 数据采用hash 方式存储,当需要进行rehash的时候,redis采用的是渐进式的rehash方式
  • redis服务器的所有数据都存储在redisServer.db 数组中,数组的数量由redisServer.dbnum 保存
  • db 由 dict 和 expires 两个字典构成,dict 负责保存键值对,expires字段负责保存键的过期时间
  • redis 使用惰性删除和定期删除两种策略配合使用来删除过期的键。

redis 数据库错误

  • 如对错误
  • 执行错误
  • 停机错误

Redis 持久模式

  • 内存模式
  • RDB持久化模式,redis只有在特定的条件满足时,才会执行BGSAVE命令进行RDB持久化,异步执行
  • AOF持久化模式
    • appendfsync=always 时候,当redis命令执行后同步执行持久化动作
    • appendfsync=everysecond时候,每秒钟一次异步执行持久化动作
    • appendfsync=no 时候,redis程序由操作系统决定何时执行持久化动作
  • no-appendfsync-on-rewrite 选项,此选项可以与 appendfsync 为always 或者 everyseconds 的 AOF模式配合使用。当此选项打开的时候,当执行BGSAVE 或者 BGREWRITEAOF命令期间,服务器会暂时停止对AOF文件进行同步。此选项默认是关闭状态。

redis事物

  • 使用 multi,exec,watch 来实现事物
  • 将多个请求打包,一次性,按照顺序的执行
  • 执行完成后,将执行结果一次性返回给客户端
  • 在事物执行期间,redis 不会执行其他命令请求(待事物的所有命令都执行完毕之后,才去执行其他客户端请求)
  • multi开启事物,exec 提交事物
  • watch 命令可以在事物开始之前监视一组key,当事物提交的时候,如果任意一个key发生了变化,redis将拒绝执行事物
  • 每个redis客户端都持有一个事物状态REDIS_DIRTY_CAS,当watch的key 变化,会将事物REDIS_DIRTY_CAS状态打开
  • redis事物具有原子性,但是不具备回滚机制。(原子性是指,事物的所有命令被作为一个整体,要么全部执行,要么全部都不执行)
    • redis 2.6之前,入队错误不会影响事物的执行,如对错误的命令会被事物忽略,2.6之后,redis会拒绝入队错误的事物
    • 如果其中一个命令执行出错,之前执行的命令不会受到影响,之后的命令可以继续执行。
  • redis事物具有一致性,(一致是指,数据符合数据库本身的定义和要求,没有包含非法或者无效的错误数据。)
  • redis事物具有隔离性,(数据库的隔离性是指,即使事物是并行执行的,各个事物之间也不会相互影响,和事物串行执行的效果是一样的),redis事物是串行执行的。
  • redis 在不同的持久化模式下耐久性。(耐久性,也有叫做持久性,是指事物执行的结果被成功的保存到永久存储介质中,比如磁盘)
    • redis 只有运行在AOF 持久化模式,appendfsync=always 且 no-appendfsync-on-rewrite关闭的时候才具有耐久性
    • 不论redis运行在什么模式下,在一个事物的最后加上save命令可以保证事物的耐久性(不过这种做法效率很低)

sentinel 主从监控及故障转移

  • 可以通过SLAVEOF命令或者 slaveof 选项让一个服务器去复制另一个服务器(主从模式)
  • saveof 命令将在从服务器的redisServer 结构中记录 主服务器的ip和端口,slaveof命令是异步命令,返回ok后才回去真正连接主服务器
  • redis 2.8及之后,通过psync 命令使用部分重同步的方式进行同步
    • 主从服务器通过复制偏移量,复制积压缓冲区来实现部分重同步
  • 主服务器会记录复制自己的从服务器列表,列表中的每一项记录着从服务器的ip,复制端口,状态,最后ACK时间间隔,复制偏移量等等
  • 复制开始后,主服务器和从服务器互为客户端
  • 主服务器通过作为从服务器的客户端并发送自己受到的写命令来保持主从服务器一致
  • 从服务器每秒发送一次ACK(REPLCONF ACK)命令给主服务器,以检查链路并更新自己在主服务器的状态
  • 为了防止主服务器在不安全的情况下执行写命令,redis提供如下两个配置项:
    • min-slaves-to-write 当从服务器数量小于此数值,主服务器将拒绝向从服务器执行写命令
    • min-slaves-max-lag 从服务器的延迟(ACK lag记录的时间)都大于此数值的时候,主服务器将拒绝向从服务器执行写命令

sentinel

  • 是redis 的HA解决方案,

  • sentinel 本身也是一个redis服务器,这是运行模式为sentinel

  • 通过运行redis服务器在 --sentinel模式下指定要监视的主服务列表方式启动

  • sentinel兵符使用数据库(不进行持久化)

  • 可以由一个或者多个sentinel组成

  • 监视任意多个redis主服务器,监视主服务器属下的所有从服务器

  • 在主服务器下线的时候自动将主服务器的从服务器之一升级为主服务器

  • 下线的主服务器重新上线后,将重新作为从服务器复制接替自己位置的redis服务器

  • sentinel根据用户设定的下线时长来判断是否应该对一个主服务器进行故障转移

  • sentinel将一个从服务器升级为主服务器并通过向其他从服务器重新发送复制命令使之复制新的主服务器

  • sentinel服务器启动后,初始化sentinel状态(数据结构),并在此中记录masters 字典(key是主服务器的名称,值是被监视的主服务器的sentinelRedisInstance结构)

  • 当sentinel监视一个主服务器,sentinel会成为主服务器的客户端

  • sentinel与被监视的主服务器建立两个异步网络连接

    • 命令连接:专门用于向主服务器发送命令并接受回复
    • 订阅连接:专门订阅被监视的主服务器的_sentinel:hello 频道(因为常规的redis频道会在客户端断线或者下线的时候丢失消息)
  • sentinel 默认会以每10秒一次的频率向北监视的主服务器发送INFO命令来获得如下信息

    • 主服务器信息
    • 主服务器的从服务器信息(当获得了从服务器信息后,sentinel 也会与从服务器建立上述的两个连接)
  • sentinel 会每隔2秒(默认)的频率向所监视的所有redis服务器(主服务器 & 从服务器)的_sentinel:hello 频道发送sentinel自己和自己所监视的主服务器的信息

  • sentinel 也会订阅每个redis的hello频道,直到连接断开为止

  • 一个sentinel发布的信息会被其他sentinel 接收到,sentinel 集群用此方法更新所有sentinels 对于整个redis 集群的感知,以及对整个sentinels集群中其他sentinel的感知

  • 因为sentinel 对整个集群的感知能力,所以在添加或者启动sentinel的时候并不需要指定当前的sentinel 列表信息

  • 监视同一个主服务器的多个sentinel之间会相互建立命令连接(不需要建立订阅连接,因为sentinel已经通过与redis服务器的订阅连接感知到了整个网络)

  • sentinel 默认以每秒一次的频率向所有与其建立命令连接的服务器(主服务器,从服务器,其他sentinel)发送ping命令

  • sentinel 根据 目标服务器对ping命令的返回判断此服务器是否下线(通过主观下线和客观下线两种方式)

  • 当一个主服务被判断为客观下线的时候,监视这个主服务器的多个sentinel 会进行选举,获得半数以上选举票数的sentinel会成为主sentinel,由主sentinel对发生故障的主服务器进行故障转移

sentinelRedisInstance

  • 可以表示一个被监视的主服务,或者主服务器的从服务器,或者其他的sentinel服务器
  • sentinelRedisInstance 里面记录了,一个redis服务器超时多久会被sentinel鉴定为主观下线,
  • 也记录了其他也认为此redis 已经下线的sentinel 的数量,作为客观下线投票数(quorum)
  • 记录了一个配置项,超过多少客观超时投票数可以将此redis判断为下线
  • 记录了多少从服务器可以复制新晋升的主服务器

lua脚本

  • redis从2.6开始执行lua脚本
  • redis 会原子地执行地执行一个lua脚本(里面的多个redis命令)

发布与订阅

  • SUBSCRIBE 命令订阅一个频道
  • PSUBSCRIBE 命令订阅符合一个模式(pattern)的模式
  • PUBLISH 发布消息到一个频道
  • UNSUBSCRIBE 和 PUNSUBSCRIBE 退订频道 和 模式
  • redisService 通过一个名称为pubsub_channels 的 dict 来记录渠道与订阅者关系,渠道名称是key,订阅者列表是dict的值
  • redisServer 通过一个名称为pubsub_patterns的 list 来记录模式订阅者,list的的单个元素的数据结构中,记录着订阅模式的client 和 模式本身的pattern
  • 可以通过PUBSUB命令可以查看redis 渠道或者模式订阅的信息(此命令在2.8及之后才有)
  • 在redis当前的发布和订阅功能中,发布的消息并么有保存在redis服务器里面(也没有持久化),如果在信息发送的时候,想要接受信息的客户端下线或者断线,那么这个客户端将丢失这个信息

集群

节点加入

  • 加入当前集群有N个节点,新节点A向任意一个集群节点B发送CLUSTER MEET命令既可以加入集群,让自己和集群中所有的节点相互感知(节点A和B先握手,然后节点B向集群通过gossip协议发送信息,集群节点挨个与节点A进行CLUSTER MEET)

槽指派

  • redis集群通过分片的方式保存数据库中的键值对
  • 集群的整个数据库被分为16384个槽(SLOT),数据库中的每一个键值对必然属于一个槽
  • 集群中的每个节点可以处理 0 到16384个槽
  • 当数据库中的16384个槽都有节点在处理是,集群是上线状态,如果有任何一个槽没有得到处理,那么集群处于下线状态
  • CLUSTER MEET 命令只是将各个node连接到一起,但是集群没有上线,因为槽没有进行分配
  • 使用CLUSTER ADDSLOT 命令可以向指定的节点添加槽
  • 每个被分配了槽的节点,在自己的clusterNode结构中通过二进制数组的方式记录自己负责了哪些槽,还会降自己负责哪些槽的信息发送给集群中其他的节点。这样,每个节点即知道自己负责哪些槽,又知道其他节点负责哪些槽

在集群中执行命令

  • 一个集群节点接收到命令的时候,如果命令对应的key所属的槽是当前节点处理,则节点直接处理此命令,如果key所属的槽不是当前节点负责,则节点向客户端返回MOVED错误和处理这个槽的节点ip和端口,客户端可以重新请求
  • 计算key属于哪个槽:slot_index_of_key = CRC16(KEY) & 16384
  • 一个客户端通常与集群中多个节点进行套接字连接,所谓的MOVED错误和请求迁移,只是切换一个套接字连接罢了
  • 与单机redis服务器不同的是集群节点redis服务器只能使用0号数据库,而单机数据库没有此限制

重新分片

  • 重新分片是指,将已经指派给节点A的一些槽重新指派给节点B,并将这些槽的键值对从节点A转移到节点B
  • 重新分配可以在线进行,集群不需要下线,而且A节点和B节点都可以继续处理请求

复制与故障转移

  • redis集群中的服务器分为master节点和 slave节点两种节点,主节点负责处理槽,从节点负责复制主节点,并在主节点下线的情况下代替主节点
  • 一个节点成为一个主节点的从节点并开始复制这个主节点,这个关系信息会发送给集群里面的其他节点,最终整个集群中的所有节点都会知道从节点复制这个主节点的关系信息。
  • 集群中的节点会定期向集群中的其他节点发送ping消息,如果对应的节点没哟回复,则当前节点会标记目标节点为疑似下线(PFAIL)
  • 集群的节点会通过发送信息的方式相互交换集群信息
  • 如果集群中半数或者半数以上的负责槽的主节点认为一个主节点为疑似下线,则此主节点被标示为下线,标示此主节点下线的节点向集群中其他节点发送消息:有一个节点下线了,接收到消息的节点,将自己数据结构中对应的下线节点的信息标记为下线状态
  • 当下线的主节点的从节点得知自己复制的主节点下线的时候,从节点会选出新的主节点,并接替下线的主节点负责的槽,以达到故障转移。
  • 当集群的摸个节点开始一次故障转移的时候,集群的配置纪元增加1
  • 集群节点通过

慢日志查询

  • Redis服务器有两个和慢日志查询相关的配置项
  • slow-log-slower-than 选项指定执行时间超过多少微秒(千分之一秒)的命令到日志上
  • slowlog-max-len 选项指定服务器最多保存多少条慢日志,当慢日志条数多余此数值的时候,最早的一条记录将被删除
  • 可以通过CONFIG SET 命令在运行时设置这两个选项
  • redisServer 通过一个slowLog 的 list 来记录慢日志
  • slowLog 里面记录了慢日志的命令和参数

什么是Pipelining

  • redis 请求是通过tcp完成的,tcp 请求中设计RTT ,Pipelining 就是为了减少RTT .
  • A Request/Response server can be implemented so that it is able to process new requests even if the client didn't already read the old responses. This way it is possible to send multiple commands to the server without waiting for the replies at all, and finally read the replies in a single step.
  • redis 在执行pipeLining 的时候需要对请求进行queue ,并对response 进行缓存,这是需要消耗一定的内存的,所以如果有特别多的请求需要pipepining,将这些请求分批(比如每批次 10K)是一个好注意

Pipelining VS Scripting

Using Redis scripting (available in Redis version 2.6 or greater) a number of use cases for pipelining can be addressed more efficiently using scripts that perform a lot of the work needed at the server side. A big advantage of scripting is that it is able to both read and write data with minimal latency, making operations like read, compute, write very fast (pipelining can't help in this scenario since the client needs the reply of the read command before it can call the write command).

Sometimes the application may also want to send EVAL or EVALSHA commands in a pipeline. This is entirely possible and Redis explicitly supports it with the SCRIPT LOAD command (it guarantees that EVALSHA can be called without the risk of failing).

© 著作权归作者所有

上一篇: MySql Sql 语句大全
下一篇: MongoDB
百花
粉丝 1
博文 67
码字总数 25011
作品 0
海淀
架构师
私信 提问

暂无文章

mysql概览

学习知识,首先要有一个总体的认识。以下为mysql概览 1-架构图 2-Detail csdn |简书 | 头条 | SegmentFault 思否 | 掘金 | 开源中国 |

程序员深夜写bug
42分钟前
3
0
golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架...

非正式解决方案
今天
3
0
前端——使用base64编码在页面嵌入图片

因为页面中插入一个图片都要写明图片的路径——相对路径或者绝对路径。而除了具体的网站图片的图片地址,如果是在自己电脑文件夹里的图片,当我们的HTML文件在别人电脑上打开的时候图片则由于...

被毒打的程序猿
今天
2
0
Flutter 系列之Dart语言概述

Dart语言与其他语言究竟有什么不同呢?在已有的编程语言经验的基础上,我们该如何快速上手呢?本篇文章从编程语言中最重要的组成部分,也就是基础语法与类型变量出发,一起来学习Dart吧 一、...

過愙
今天
2
0
rime设置为默认简体

转载 https://github.com/ModerRAS/ModerRAS.github.io/blob/master/_posts/2018-11-07-rime%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%AE%80%E4%BD%93.md 写在开始 我的Arch Linux上......

zhenruyan
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部