美文网首页
聊聊Redis

聊聊Redis

作者: Bardon_X | 来源:发表于2019-03-09 18:32 被阅读0次

    本篇文章从以下几个方面介绍一下Redis。

    1、Redis数据类型

    2、Redis持久化

    3、Redis集群

    4、Redis常见问题

    前言:

    Redis是基于内存的非关系型数据库,一般是简单的存取操作,时间主要花费在I/O上,所以读取速度快。Redis使用非阻塞I/O,I/O多路复用,使用单线程来轮询描述符,将数据库的开、关、读、写都转换成事件,减少线程切换上下文的时间。此外,Redis全程使用hash结构,读取速度快。

    一、Redis数据结构

    String类型,可以是字符串、整数、浮点数,可对字符串或字符串的一部分进行操作,对整数和浮点数执行自增或自减操作。

    List类型,一个链表,链表上每个节点都包含一个字符串。从链表的两端推入或弹出;根据偏移量对链表进行修剪;读取单个或多个元素;根据值查找或移除元素。

    Set类型,包含字符串的无序收集器,并且被包含的每个字符串都是独一无二各不相同的。添加、获取、移除单个元素,检查一个元素是否存在集合中,计算交集、并集、差集,从集合中随机获取元素。

    Hash类型,包含键值对的无序散列表,添加、获取、移除单个键值对,获取所有键值对。

    Zset类型,字符串成员和浮点数分值之间的有序映射,元素的排列顺序由分值的大小决定。添加、获取、删除单个元素,根据分值范围或成员来获取元素。

    二、Redis持久化

    Redis提供两种持久化方式:快照(RDB文件)和追加式文件(AOF文件)

    RDB:会在特定的时间间隔保存那个时间点的数据快照。原理:redis调用fork()方法,产出一个子进程讲数据写到临时RDB文件,更新后替换旧的RDB文件。 优点:单文件、适合做备份;主进程不会有I/O操作;数据量大时,启动快。 缺点:容易造成数据丢失(当服务器在持久化之前挂掉,那挂掉瞬间到上次持久化这段时间的数据就丢失了)、数据量很大时,会造成redis服务停止

    AOF:每次有更新或写操作,直接将操作追加到AOF文件末尾,当文件达到一定大小,会优化文件,对命令进行汇集,减小文件大小。 优点:比RDB可靠,可制定不同的同步策略。 缺点:相同数据集下,AOF文件更大;某些同步策略下,AOF速度比RDB慢。

    三、Redis集群

    集群的设计,旨在为适应高并发高吞吐量场景设计,大多数业务场景下都是读操作,redis集群可由子节点分担访问压力,主节点处理更新和写操作,再同步给子节点。

    数据分区:当数据量十分巨大,单节点无法承载时,可使用数据分片来实现。一个集群包含16384个哈希槽,每一台主节点机器分配一个范围,使用CRC(key)%16384来计算键属于那个槽。同时redis客户端在访问后也会缓存一个哈希糟与节点IP的映射表,以提高访问速度。当集群要扩容时,集群会停止服务,通过配置表重新分配哈希槽,再转移数据,扩容完毕,集群恢复可用(故建议在凌晨访问量低的情况下进行扩容)。

    容错机制:redis提供了每个节点之间放松ping命令以测试健康状态的机制。当子节点向主节点发送ping命令没有得到pong返回是,子节点会通知其他节点给主节点方式ping。如果集群超过半数节点给主节点发送ping都没有得到返回,坐实主节点挂掉,立马启动备份服务器。

    主从复制:为了使得集群在一部分节点无法与集群大多数节点通讯的情况下仍然运作,集群中的每一个节点都有1到N个复制。主节点会把数据同步给子节点,但是在同步数据之前,主节点就挂掉了,未同步的数据就会丢失。对于追求高可用性这点,redis并不合适,同时redis只保证最终一致性。

    四、Redis常见问题

    1、缓存雪崩:指缓存集中失效,全部的请求都访问到数据库,导致数据库崩溃。

    缓存集中失效,是因为缓存数据设置了相同的过期时间,导致redis将这部分数据全部删光。这里可以设置一下redis对过期键的策略,主要有惰性删除和定期删除。定期删除其实很难做到,以为当数据量大时,redis不可能一直去遍历所有的键,判断是否过期再删除掉。所以设置定期删除,会限制执行时长和频率。惰性删除,主要是在取键的时候,判断该键是否过期,过期则删除。

    预防雪崩问题:①给过期时间添加一个随机值 ②设置本地缓存+限流(hystrix)③设置redis集群,避免单机

    2、缓存穿透:指未命中缓存,导致请求访问到数据库。

    预防穿透问题:①过滤不合法请求 ②数据库查询为空时,也存储到缓存

    3、缓存与数据库双写一致

    在做更新操作时,数据库与缓存数据不一致

    ①先删除缓存后更新数据库。

    线程A删除缓存,线程B查询缓存,发现不存在,查询数据库得到旧值,线程B写入缓存,线程A写入数据库。解决思路,将删除缓存、修改数据库、读缓存等操作积压到对列,实现串行化。

    ②先更新数据库后删除缓存。

    缓存刚好失效,线程A查询数据库,得到一个旧值,线程B将新值写入数据库,线程B删除缓存,线程A将旧值写入缓存。解决思路,将要删除的key放到消息队列,重试直到成功。

    总结

    这部分知识其实在团队里就整理过,还做了分享,当初对集群、一致性还是懵懵懂懂的。现在再看,特别是配合raft协议、zab协议,对redis的局限性有了更深一点的认知。

    参考:

    1、《Redis实战》

    2、Java3y

    相关文章

      网友评论

          本文标题:聊聊Redis

          本文链接:https://www.haomeiwen.com/subject/ngospqtx.html