20问快速了解redis

通过20问来了解redis

  前人栽树,后人乘凉。本文中的问题来自公众号:《java专栏》,帮我们总结了了解redis,必须要掌握的20问,当然,很多答案个人按照自己的理解做了解读,主要还是用于自己加深理解;

  1. redis的特点:

redis本质上是一个key-value类型的内存数据库,整个数据库统统加载在内存中进行操作,定期通过异步操作吧数据同步到硬盘上保存起来。由于是纯内存操作,redis的性能非常出色(这里的原因我觉得他没说完整,还有redis的单线程特性,关于这点,要衍生就是一篇...),目前来说redis可以说是最好的key-value数据库。不仅仅由于他的快,还有丰富的数据结构,这样就能用redis来实现许多功能,比如用redis的list来做FIFO的双向链表,实现一个轻量级的消息队列服务器等。同时还能对key设置过期时间(这点用于短信验证码是真的方便)。redis的缺点:由于数据库加载在内存中操作,那么一定会收到内存的限制,不能存储大量的数据;

  1. 使用redis有哪些好处

速度快: 数据操作在内存中进行,单线程操作避免频繁的线程上下文切换;
数据类型丰富: string list set hash zset;
功能多: 定时过期、发布订阅、键值存储;
支持事务,操作都是原子性;

  1. redis和memcached比较的优势

redis异步同步数据到硬盘,memcached重启数据就会丢失;
redis支持的数据结构更多;
redis的存储速度更快;
redis的功能更多(发布订阅、过期超时);
redis底层的模型不同,通信应用协议不同,redis实现了自己的vm,减少了调用系统函数,提高了效率;

  1. redis的适用场景

redis的数据结构丰富使得redis的适用场景也非常的多,这里举几个常用的例子:
高频数据缓存;
队列应用(排行榜、关注列表、评论);
发布订阅(简单的消息传递,不能堆积消息,最好还是用mq);
分布式会话缓存;
分布式锁;
分布式id自增或是计数器;
....

  1. redis的缓存失效策略和失效机制

redis有给key设置过期时间的功能,可以通过ttl key来查看key的过期时间(-1)是不会过期;
缓存失效那么就要有定时任务定期清理过期的key,如果定时任务过于频繁,就会影响redis的性能,所以redis的key的过期清理是通过定时任务加上读时判断。也就是说读取key的时候如果key已过期,那么就会删除key;
在redis中,如果没有设置server.maxmemory(最大缓存), 那么如果redis已经满了,再有新的数据添加进来,redis就会报错或崩溃;设置了之后redis在容量达到一定程度的时候就会执行key的淘汰策略,redis提供了6种key的淘汰策略:
· volatile-lru: 从设置了过期时间的数据中挑选近期最少适用的数据淘汰;
· volatile-ttl: 从设置了过期时间的key种挑选将要过期的淘汰;
· volatile-random: 从设置了过期时间的key中随机淘汰;
· allkeys-lru: 从所有的key中挑选最少适用的淘汰;
· allkeys-random: 从所有的key中随机淘汰;
· no-enviction: 禁止淘汰数据;

  1. 为什么redis要将所有的数据方在内存中

首先想到的就是快;redis为了达到最快的读写速度,将操作都在内存中操作使得redis的操作非常的快速(不然不就和mysql一样,磁盘io瓶颈)。

  1. redis为什么是单线程的

这个问题这里回答的并不好,我看到另一个地方的回答:如果一个线程进行一个操作耗时30us,那么这个线程10次操作耗时300us。如果换成多线程,每次线程上下文切换需要120us,那么执行10次至少上下文切换的时间就是1200us;而redis基于内存操作,每个操作的耗时短,就适合单线程来完成。这里说的只是单核cpu,但是要知道,对于多核cpu来说,单线程肯定不能完全利用多核cpu的特性。那么我们知道,如果操作数据,要考虑操作同一数据的并发问题,是不是就需要加锁,引入了多线程,就引入了锁竞争,也引入了设计的复杂性。所以既然单线程已经这么快了,为什么还要引入这些可能变慢的因素呢?
至于所说的redis并不能良好的应用多核cpu,所以可以在redis启动的时候绑定cpu核心,让固定的核心处理redis,然后再一台机器上部署多个redis来合理利用机器资源;

  1. redis如何解决并发竞争

redis使用了单线程的模式,所以redis没有锁,使用队列模式将并发访问变成串行访问。但是值得注意的是,尽管redis不存再竞争,但是操作redis的客户端还是要考虑自身并发读写redis的问题,比如并发写reids同一key,可能造成的更新顺序问题,这个问题的本质是客户端,也有一些连接超时、数据转换错误等连接错误也是需要客户端处理。
这里有一个很常见的问题,在实现分布式锁的时候,不能先set key,然后再设置过期时间。可以使用setnx或lua脚本来实现,而redission帮助我们封装了它。

  1. redis常见的性能问题和解决方案

Master写内存快照,save命令调度rdbSave函数,会阻塞主线程,当快照比较大的时候对性能影响会非常大,甚至间断性暂停服务。所以Master最好不要写内存快照.(redis数据同步到磁盘的策略之一的RDB的save命令的缺陷,也可以使用bgsave命令派生一个子线程来同步,占用系统资源还是在大文件的时候会对性能有影响);
Master AOF持久化, 如果不重写AOF文件,AOF相对来说影响较小,但是AOF文件会不断增大,会影响Master的重启速度。最好的方式是Master不要做任何的持久化工作,特别重要的数据让Slave开启AOF持久化,每秒同步一次。(AOF相对于RDB内存快照,使用的是追加命令的形式,可设置每秒同步一次,那么理论上最多丢失1S的数据,RDB则不那么稳定,但是AOF有一些bug,而且相同数据的文件会比RDB的方式大)
Master Slave 同步数据的问题, 为了主从同步数据的稳定性和速度,最好将redis的主从放置在一个局域网。

  1. redis存在事务吗

redis帮助我们提供了事务的支持,在redis中MULTI/EXEC/DISCARD/WATCH这几个命令帮助我们实现事务。但是相比较mysql的事务,在redis中如果有一条命令执行失败,但是其他的命令还是会执行;我们使用MULTI开启事务,EXEC执行或者是DISCARD回滚事务(他的回滚是取消,并不是真的回滚),所以我个人并不认为这是一种事务...

  1. redis的watch

reids和zookeeper在许多的时候提供了许多的相同的功能,但是个人经验redis的实现手法是CAP理论中的AP,而zookeeper的实现手法往往是CP;对于锁的实现AP理论往往实现的都是乐观锁,CP往往实现的是悲观锁。watch在redis中可以建通一个key,当这个key开启事务的时候,事务还没有完成的时候,这个key被修改了,那么在事务中继续执行EXEC就会返回一个空值。

  1. redis的分布式锁

redis分布式锁也是老生常谈了,synchronized帮助java在单个jvm中操作一段代码具有线程的安全性,但是分布式的情况下单个jvm中安全的代码在不同的jvm中还是会有并发的问题,这个时候就需要一个单点来同一管理一个分布式的synchronized。我们可以使用redis,这里也有很多陷阱:
如何加锁,使用setnx(新版本的redisTemplate提供了setAbsent方法)或者是lua脚本(本质上是保证加锁和设置过期时间在一条命令完成保证原子性);
设计可重入,value设置一个唯一id并且向下传递id以便重入, 当然想要不可重入也是可以的;
如何解锁,解锁的时候最好判断一下解锁的对象是不是加锁的对象,同样我们可以根据value来判断;
锁的重试,redis实现的是乐观锁,在特定的场景下可以自行选择是重试还是直接失败;

  1. 想要获取redis中具有相同前缀的key,如何找出他们

redis提供了基于key的一系列操作,想要找出有相同前缀的key,使用keys xxx就可以了,但是,这往往是个陷阱。接下来就会问,如果在线上系统执行 keys 命令会有什么问题吗?
首先应该能向到的是效率问题,如果redis中的key过多,并且使用这个前缀的key也较多,那么使用这个命令会造成redis短暂的阻塞,直到这条命令执行完毕;
这时候应该就能想到redis是单线程的,需要等待这条指令执行完成才能执行下一条;
那么我们如何避免这个呢?这个时候我们可以使用scan命令来提取想要的key, 这是无阻塞的获取key方式,使用游标进行分页迭代;

  1. redis如何做异步队列使用

redis提供了多种数据结构,对于队列我们就可以使用list作为队列,rpush产生消息,lpop消费消息(或者使用blpop消费,此种情况当没有消息在队列中的时候会阻塞到消息到来),如果数据保证不重复的话使用set也是可以的。
如果要进行广播消费,那么可以使用redis的发布订阅,此种方式可以在简单场景下替代mq,但是他的缺点是没有堆积能力,在消费者下线的情况下,生产的消息会丢失,所以要堆积消息削峰填谷的时候还是要用类似rocketmq、kafka这样的专业mq;
如果想实现延时队列,可以使用Zset,score使用时间戳,消费者使用rangebyscore来消费消息,然后按时间戳做定时任务处理;

  1. redis中的key为什么不要大量的设置相同过期时间

如果有大量的key在同一时间过期,一个是redis本身清理这些key可能会有短暂的卡顿,其次,这些key大量的过期,造成业务访问大量直接访问数据库,造成缓存雪崩,严重影响整个系统的性能。
此时我们应该在设置过期时间的时候加一个随机值,让key在不同的时间过期。

  1. 使用redis如何处理缓存穿透

缓存穿透出现在当业务数据的key没有命中缓存,查询数据库,但是数据库中确实没有数据,就永远不能存入缓存,那么每次这个key的查询都直接查询数据库,对应用系统造成影响。我们应当在redis的key多次未命中的时候将这个key存入缓存,设置一个较短的失效时间,或者在应用层面过滤掉无效的key;
还有一种方式是使用布隆过滤器,redis有现成的布隆过滤器的实现;

  1. 使用reids如何处理缓存击穿

缓存击穿指的是在系统压力比较大的时候,其中的key到了失效的时间,此时大量的请求都会直接打到数据库(还没来的及缓存到redis),这个时候数据库就会由很大的压力,虽然比较短暂。对于这些可能比较大并发的key,我们可以不设置其过期时间,高并发并不会一直持续,这是互联网的特点,等到并发峰值过了之后,在设置清除策略;或者是key命中达到一定次数的时候,更新key的过期时间;

  1. 什么是redis的pipleline

简单来说pipleline就是批量操作,这样的好处是可以减少io次数,如果分10次来设置key、value,那么系统应用和redis之间就有10次的io,而将者10次操作使用pipleline做一次操作,可以提高redis的性能。当然,如果本身请求不多的话,这也是不必要的,一般来说在高并发的时候可以使用pipleline;

  1. redis的同步机制

redis可以使用主从同步,也可以使用从从同步。第一次同步的时候,主节点做一次bgsave,同时将bgsave之后的操作记录到内存buffer中,完成bgsave后将rdb文件同步到复制节点,复制节点加载完rdb文件,再通知主节点将之后的操作记录同步到复制节点,由复制节点一直重放之后的操作。

  1. redis的集群

redis的sentinal集群方式,由sentinal服务来监控redis的主从节点,进行选主操作,适用于需要提供高可用,数据较小的服务;
redis的cluster集群方式, 将需要存在redis中的数据按slot切分到不同的redis节点中(就是数据分片类似mongodb、es),其中分配到数据的都是主节点,每个主节点再可以有几个从节点,从节点从主节点同步数据,如果一个分片上的所有节点都不可用,则集群不可用,这种方式适用于相对较大的数据分片存储;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350