redis三两事(一)

1. 什么是redis

官网介绍:Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。

详细介绍:Redis:(REmote DIctionary Server),它是一个完全开源免费且遵守BSD协议,用C语言开发的,高性能key-value型分布式内存数据库,它是基于内存运行支持持久化的NoSQL数据库。另外,Redis 也经常用来做分布式锁。除此之外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。

2. redis的优劣势

优势:

  1. 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)

Redis为什么这么快?
1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速;
2、数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;
3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
4、使用多路 I/O 复用模型,非阻塞 IO;
5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

  1. 支持丰富数据类型,支持string,list,set,sorted set,hash
  2. 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
  3. 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除

3 .支持的数据类型有哪些?

Redis主要有5种数据类型,包括String,List,Set,Zset,Hash,满足大部分的使用要求

数据类型可以存储的值操作应用场景
String字符串,整数,浮点数字符串或其中一部分,整数,浮点数自增或自减键值对缓存 (bitfield 可以用作签到)
List列表压入或弹出元素,操作单个或多个元素存储一些列表型的数据结构,类似粉丝列表,文章的评论列表之类的数据
Set无序集合添加,获取,移除单个元素,检查元素是否存在,计算交集,并集,差集,随机获取元素交集,并集,差集的操作,可以把两个人的粉丝列表整成一个交集
Zset有序集合添加,获取,移除元素,根据分值范围或成员来获取元素,计算一个键的排名去重可以排序,如获取排名前几的用户,或者最近访问记录
Hash包含键值对的无序散列表添加,获取,移除元素,检查元素是否存在,获取所有键值对结构化的数据,比如一个对象

Redis中高级用户,还需要加上HyperLogLog、Geo、Pub/Sub等数据结构,Redis Module等。

1.HyperLogLog: 是用来做基数统计的算法。优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。目前只支持3个命令,PFADD、PFCOUNT、PFMERGE。

在数学上,基数或势,即集合中包含的元素的“个数”,是日常交流中基数的概念在数学上的精确化(并使之不再受限于有限情形)。有限集合的基数,其意义与日常用语中的“基数”相同,例如{{a,b,c}的基数是3。无限集合的基数,其意义在于比较两个集的大小,例如整数集和有理数集的基数相同;整数集的基数比实数集的小。
基数就是指一个集合中不同值的数目,比如[a,b,c,d]的基数就是4,[a,b,c,d,a]的基数还是4,因为a重复了一个,不算。基数也可以称之为Distinct Value,简称DV。

  • PFADD:将参数中的元素都加入指定的HyperLogLog数据结构中,这个命令会影响基数的计算。如果执行命令之后,基数估计改变了,就返回1;否则返回0。如果指定的key不存在,那么就创建一个空的HyperLogLog数据结构。该命令也支持不指定元素而只指定键值,如果不存在,则会创建一个新的HyperLogLog数据结构,并且返回1;否则返回0。
  • PFCOUNT:对于单个key,该命令返回的是指定key的近似基数,如果变量不存在,则返回0。
    对于多个key,返回的是多个HyperLogLog并集的近似基数,它是通过将多个HyperLogLog合并为一个临时的HyperLogLog,然后计算出来的。
    HyperLogLog可以用很少的内存来存储集合的唯一元素。(每个HyperLogLog只有12K加上key本身的几个字节)
    HyperLogLog的结果并不精准,错误率大概在0.81%。
    需要注意的是:该命令会改变HyperLogLog,因此使用8个字节来存储上一次计算的基数。所以,从技术角度来讲,PFCOUNT是一个写命令。
  • PFMERGE:用法:PFMERGE destkey sourcekey [sourcekey …]
    合并多个HyperLogLog,合并后的基数近似于合并前的基数的并集(observed Sets)。计算完之后,将结果保存到指定的key。
  • 除了这三个命令,我们还可以像操作String类型的数据那样,对HyperLogLog数据使用SET和GET命令
2.Geo:主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。目前支持6个命令
  • GEOADD:增加某个地理位置的坐标。可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。
    有效的经度从-180度到180度。
    有效的纬度从-85.05112878度到85.05112878度。
    当坐标位置超出上述指定范围时,该命令将会返回一个错误。
    语法格式如下:

    GEOADD key longitude latitude member [longitude latitude member …]

  • GEOPOS:获取某个地理位置的坐标,返回一个数组, 数组中的每个项都由两个元素组成: 第一个元素为给定位置元素的经度, 而第二个元素则为给定位置元素的纬度。不存在的返回 nil。语法格式如下:

    GEOPOS key member [member …]

  • GEODIST:获取两个地理位置的距离。语法格式如下:

    GEODIST key member1 member2 [m|km|ft|mi]

    member1 member2 为两个地理位置。
    最后一个距离单位参数说明:
    m :米,默认单位。
    km :千米。
    mi :英里。
    ft :英尺。

  • GEORADIUS:以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。

  • GEORADIUSBYMEMBER:和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 georadiusbymember 的中心点是由给定的位置元素决定的, 而不是使用经度和纬度来决定中心点。
    georadius 与 georadiusbymember 语法格式如下:

    GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

    GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

    参数说明:
    m :米,默认单位。
    km :千米。
    mi :英里。
    ft :英尺。
    WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
    WITHCOORD: 将位置元素的经度和维度也一并返回。
    WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
    COUNT 限定返回的记录数。
    ASC: 查找结果根据距离从近到远排序。
    DESC: 查找结果根据从远到近排序。

  • GEOHASH:获取某个地理位置的 geohash 值
    语法格式如下:

    GEOHASH key member [member …]

3.Pub/Sub: 即发布及订阅功能。基于事件的系统中,Pub/Sub是目前广泛使用的通信模型,它采用事件作为基本的通信机制,提供大规模系统所要求的松散耦合的交互模式:订阅者(Subscriber)可以订阅自己感兴趣的频道(Channel),发布者(Publisher)可以将消息发往指定的频道(Channel)。熟悉设计模式的朋友应该了解这与23种设计模式中的观察者模式极为相似。

同样,Redis的pub/sub是一种消息通信模式,主要的目的是解耦消息的发送者和接收者,Redis作为一个pub/sub的server,在订阅者和发布者之间起到了消息路由的功能。目前支持6个命令

  • PSUBSCRIBE pattern [pattern1 …]

    - 说明:订阅一个或多个符合给定模式的频道,每个模式以*作为匹配符
    - 参数:pattern(给定的模式)
    - 返回:接受到的信息
    
  • PUNSUBSCRIBE pattern [pattern1 …]

  • - 说明:用于退订所有给定模式的频道
    - 参数:pattern(给定的模式)
    - 返回:这个命令在不同的客户端中有不同的表现。
    
  • SUBSCRIBE channel [channel1 …]

     -说明:用于订阅给定的一个或多个频道的信息
     -参数:channel(给定的频道名)
     -返回:接收到的信息
    
  • UNSUBSCRIBE channel [channel1 …]

  • -说明:用于退订给定的一个或多个频道的信息
    -参数:channel(给定的频道名)
    -返回:这个命令在不同的客户端中有不同的表现
    
  • PUBLISH channel message

    -说明:用于将信息发送到指定的频道
    -参数:channel(频道名称),message(将要发送的信息)
    -返回:接收到此消息的订阅者数量
    
  • PUBSUB < subcommand > argument [argument1 …]

    -说明:用于查看订阅与发布系统状态,它由数个不同格式的子命令组成
    -参数:subcommand(子命令),argument(子命令参数)
    -返回:由活跃频道组成的列表
    -子命令如下
    
    ubcommandargument说明
    HANNELS[pattern]返回指定模式pattern的活跃的频道,指定返回由SUBSCRIBE订阅的频道
    MSUBchannel channel2 …返回指定频道的订阅数量
    UMPAT返回订阅模式的数量,注意:这个命令返回的不是订阅模式的客户端的数量, 而是客户端订阅的所有模式的数量总和
4.Redis Module: 在redis 4.0以上,redis支持了可扩展了module,让用户可以自己根据需求自己扩展redis相关的功能。如:在4.0之前,如果用户想拥有一个带TTL的INCRBY 命令,那么用户只能自己去改代码,重新编译了。在4.0版本推出之后,想实现一个自定义的命令就简单的多了。
  • neural-redis 主要是神经网络的机器学,集成到redis 可以做一些机器训练感兴趣的可以尝试
  • RedisSearch 主要支持一些富文本的的搜索
  • RedisBloom 支持分布式环境下的Bloom 过滤器

4.应用场景有哪些?

  1. 计数器,网站访问统计等

    可以对 String 进行自增(incrBy )自减(decrBy )运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。

  2. 缓存(数据查询、短连接、新闻内容、商品内容等等,最常用)

    将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。

  3. 会话缓存
    可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。比其他存储(如Memcached)的优势在于:Redis提供持久化。

  4. 全页缓存(FPC)
    除基本的会话token之外,Redis还提供很简便的FPC平台。以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。

  5. 查找表
    例如 DNS 记录就很适合使用 Redis 进行存储。查找表和缓存类似,也是利用了 Redis 快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效,因为缓存不作为可靠的数据来源。

  6. 消息队列(发布/订阅功能)
    List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过最好使用 Kafka、RabbitMQ 等消息中间件。

  7. 分布式锁实现
    在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。

  8. 数据过期处理(可以精确到毫秒),优惠券/红包等
    监听redis,针对不同的数据时效,进行对应的数据处理

  9. 其它
    Set 可以实现交集、并集等操作,从而实现共同好友等功能。ZSet 可以实现有序性操作,从而实现排行榜等功能。

5.事务

1. 什么是事务?

事务是一个单独的隔离操作:事务中的所有命令都会序列化,按顺序的执行。事务在执行的过程中,不会被其他客户端发送来的命令请求打断。
事务是一个原子性的操作:事务中的命令要么全部执行,要么全部不执行

2. Redis事务的概念

Redis 事务的本质是通过MULTI、EXEC、WATCH等一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
总结说:redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。

3. Redis事务的三个阶段
  • 事务开始 MULTI
  • 命令入队
  • 事务执行 EXEC

事务执行过程中,如果服务端收到有EXEC、DISCARD、WATCH、MULTI之外的请求,将会把请求放入队列中

4. 事务管理(ACID)概述
  • 原子性(Atomicity)
    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

  • 一致性(Consistency)
    事务前后数据的完整性必须保持一致。

  • 隔离性(Isolation)
    多个事务并发执行时,一个事务的执行不应影响其他事务的执行

  • 持久性(Durability)
    持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

Redis的事务总是具有ACID中的一致性和隔离性,其他特性是不支持的。当服务器运行在_AOF_持久化模式下,并且appendfsync选项的值为always时,事务也具有持久性。

5. Redis事务支持隔离性吗?

Redis 是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。因此,Redis 的事务是总是带有隔离性的。

6. Redis事务保证原子性吗,支持回滚吗?

Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。

7. Redis事务其他实现
  • 基于Lua脚本,Redis可以保证脚本内的命令一次性、按顺序地执行,
    其同时也不提供事务运行错误的回滚,执行过程中如果部分命令运行错误,剩下的命令还是会继续运行完

  • 基于中间标记变量,通过另外的标记变量来标识事务是否执行完成,读取数据时先读取该标记变量判断是否事务执行完成。但这样会需要额外写代码实现,比较繁琐

Redis高可用概述

在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999% 等等)。但是在Redis语境中,高可用的含义似乎要宽泛一些,除了保证提供正常服务(如主从分离、快速容灾技术),还需要考虑数据容量的扩展、数据安全不会丢失等。

在Redis中,实现高可用的技术主要包括持久化、复制、哨兵和集群。

  • 持久化:持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
  • 复制:复制是高可用Redis的基础,哨兵和集群都是在复制基础上实现高可用的。复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
  • 哨兵:在复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。
  • 集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。

6.持久化

1. 什么是Redis持久化?

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失

2. Redis 的持久化机制是什么?各自的优缺点?

Redis提供了RDB (默认) 和 AOF以及混合持久化

- RDB:是Redis DataBase缩写快照

是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb。

优点:
1、只有一个文件 dump.rdb,方便持久化。
2、容灾性好,一个文件可以保存到安全的磁盘。
3、性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO 最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能
4.相对于数据集大时,比 AOF 的启动效率更高。

缺点:
1、数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)
2、如果数据量大的话,而且写操作频繁,会引起大量的磁盘I/O操作,严重影响性能。

RDB的三种主要触发机制:

  • 手动 save命令(同步数据到磁盘上)
  • 手动 bgsave(y异步保存数据到磁盘上)
  • 修改redis.conf 中的 save
- AOF :即Append Only File持久化

将Redis执行的每次写命令记录到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。要开启AOF,需要在配置文件中配置:
appendonly yes
当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复

优点:
1、数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次 命令操作就记录到 aof 文件中一次。
2、通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
3、AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))

缺点:
1、AOF 文件比 RDB 文件大,且恢复速度慢。
2、数据集大的时候,比 rdb 启动效率低。

AOF常用的配置项,以及默认值:

  • appendonly no:是否开启AOF
  • appendfilename “appendonly.aof”:AOF文件名
  • dir ./:RDB文件和AOF文件所在目录
  • appendfsync everysec:fsync持久化策略
  • no-appendfsync-on-rewrite no:AOF重写期间是否禁止fsync;如果开启该选项,可以减轻文件重写时CPU和硬盘的负载(尤其是硬盘),但是可能会丢失AOF重写期间的数据;需要在负载和安全性之间进行平衡
  • auto-aof-rewrite-percentage 100:文件重写触发条件之一
  • auto-aof-rewrite-min-size 64mb:文件重写触发提交之一
  • aof-load-truncated yes:如果AOF文件结尾损坏,Redis启动时是否仍载入AOF文件

AOF写数据三种策略

  • always(每次)
    每次写入操作均同步到AOF文件中,数据零误差,性能较低,如果不是对数据非常严格不建议使用
  • everysec(每秒)
    每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能较高,建议使用,也是默认配置。在系统突然宕机的情况下丢失1秒内的数据
  • no(系统控制)
    由操作系统控制每次同步到AOF文件的周期,整体过程不可控

AOF重写
因为AOF的运作方式是不断地将命令追加到文件的末尾,所以随着写入命令的不断增加,AOF文件体积也会越来越大。
为了处理这个情况,可以使用以下两种解决方式

  • 手动重写 bgrewriteaof
  • 自动重写
    auto-aof-rewrite-min-size size #设置触发aof的最小尺寸
    auto-aof-rewrite-percentage percent #达到重写的百分比

自动重写触发机制,需满足下面两个条件

  • aof_current_size(AOF当前尺寸) > auto-aof-rewrite-min-size
  • aof_current_size - aof_base_size(AOF上次启动或重写时的尺寸))*100/aof_base_size > auto-aof-rewrite-percentage
- 混合持久化

redis4.0开始支持该模式。为了解决的问题:
redis在重启时因为RDB数据不完整,所以加载AOF,但AOF相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动的时候需要花费很长的时间。
开启方式: aof-use-rdb-preamble true
开启后,AOF在重写时会直接读取RDB中的内容
运行过程:
通过bgrwriteaof完成,不同的是当开启混合持久化后,
1 子进程会把内存中的数据以RDB的方式写入aof中,
2 把重写缓冲区中的增量命令以AOF方式写入到文件
3 将含有RDB个数和AOF格数的AOF数据覆盖旧的AOF文件
新的AOF文件中,一部分数据来自RDB文件,一部分来自Redis运行过程时的增量数据

当我们开启了混合持久化时,启动redis依然优先加载aof文件,aof文件加载可能有两种情况如下:
1.aof文件开头是rdb的格式, 先加载 rdb内容再加载剩余的 aof。
2.aof文件开头不是rdb的格式,直接以aof格式加载整个文件。

优点:既能快速备份又能避免大量数据丢失
缺点:RDB是压缩格式,AOF在读取它时可读性教差

3. 如何选择合适的持久化方式?

在这里插入图片描述

总结

1、持久化在Redis高可用中的作用:数据备份,与主从复制相比强调的是由内存到硬盘的备份。

2、RDB持久化:将数据快照备份到硬盘;触发条件(包括手动出发和自动触发)、RDB文件等,特别需要注意的是文件保存操作由fork出的子进程来进行。

3、AOF持久化:将执行的写命令备份到硬盘(类似于MySQL的binlog),介绍了其开启方法等,特别需要注意的是文件同步策略的选择(everysec)、文件重写的流程。

4、一些现实的问题:包括如何选择持久化策略,以及需要注意的fork阻塞、AOF追加阻塞等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值