- 什么是redis?为什么要用redis
redis是一个基于内存的k-v数据库,读写速度非常快,号称支持每秒11万次读操作或8万次写操作。我们使用redis主要是以下两方面原因。
1.速度:对于一些需要频繁读取的热点数据,以及一些需要频繁修改的统计数据。使用传统的关系型数据库时,随着数据库数据量的增长,每次操作会变得很慢,导致效率很低,因此需要把这些数据放入redis中处理。
2.并发:当并发访问量很大时,传统的关系型数据库会顶不住访问压力,这个时候需要redis顶在关系型数据库前面起一个缓冲的作用。
redis为什么那么快
1.所有操作基于内存,读写速度非常快。
2.redis的命令执行是单线程的,由于redis命令执行速度快,且没有io操作,因此单线程的效率比多线程高,节省了多线程上下文切换的时间。
3.采用io多路复用技术。
4.数据类型简单且支持多种数据结构,效率高。redis是单线程吗
严格来说redis是多线程的。redis执行客户端请求命令的时候是单线程的。其他的操作比较持久化、异步删除、集群同步都是由其他的线程来完成的redis的五大核心数据类型是什么
1.String:字符串,二进制安全的,可以存储所有转成字符串的包括序列化的对象或者图片。一个字符串最大512M。
2.Hash:哈希,类似java的map。是一个string类型的key-value的映射表。特别适合存储对象。
3.List:列表,底层是链表,可以从头部和尾部插入数据。
4.Set:集合,底层是HashTable,不重复,无序。
5.Zset:有序集合,与set类似,不过带一个分数,分数可以重复,通过分数排序。redis的过期删除策略是什么
redis中对于设置了过期时间的数据有两种过期删除策略。
1.惰性删除:每次在获取key的时候检查是否过期,过期则删除。
优点:占用较少cpu。
缺点:占用较多内存。
2.定期删除:每隔一段时间(默认100ms),抽取部分设有过期时间的数据进行一次删除操作。
优点:对内存友好。
缺点:占用较多cpu。
redis采用了两用方法结合的方式。redis的淘汰策略有哪些
当redis中的数据量达到设置的内存上限时,当有新的数据进来时,就会对已经有的数据进行淘汰。redis的淘汰策略有8种。
1.noeviction:加入新数据时,如果内存超过配置,会返回错误。不删除旧数据,也不保存新数据。(默认策略)
2.allkeys-lru:加入新数据时,如果内存超过配置,从所有数据中淘汰一些最久没有使用过的数据。
3.volatile-lru:加入新数据时,如果内存超过配置,从设置了过期时间的数据中淘汰一些最久没有使用过的数据。
4.allkeys-random:加入新数据时,如果内存超过配置,在所有数据中随机淘汰一些数据。
5.volatile-random:加入新数据时,如果内存超过配置,在设置了过期时间的数据中随机淘汰一些数据。
6.allkeys-lfu:加入新数据时,如果内存超过配置,从所有数据中淘汰一些使用频率最低的数据。
7.volatile-lfu:加入新数据时,如果内存超过配置,从设置了过期时间的数据中淘汰一些使用频率最低的数据。
8.volatile-tt:加入新数据时,如果内存超过配置,从设置了过期时间的数据中淘汰一些即将过期的数据。什么是缓存穿透、缓存击穿、缓存雪崩
缓存穿透:查询的数据在redis和数据库中都不存在,如果大量该类型请求会造成数据库崩溃。
解决方案:
1.查询返回的数据为空,仍把这个空结果进行缓存,设置较短的过期时间。
2.布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对数据库的查询。
缓存击穿:缓存失效时,大量查询该缓存的请求直接查询数据库,造成数据库崩溃。
解决方案:
1.查询数据库操作加互斥锁。
2.设置缓存永不过期。
缓存雪崩:大面积的热点缓存失效,大量请求直接查询数据库,造成数据库崩溃。
解决方案:
1.对各个缓存加随机数,使其过期时间不在同一时间点,尽可能的分布均匀。redis持有化方式有哪些
redis持久化
Redis支持两种方式的持久化,一种是RDB方式、另一种是AOF方式,两种持久化方式可以单独使用其中一种,也可以将这两种方式结合使用。
RDB方式:数据快照,将某一时刻redis中的数据以二进制的形式生成一个dump.rdb。但是两次快照生成之间,如果redis宕机,会造成一定的数据丢失。redis重启会读取RDB的数据。恢复速度较快。
RDB有两种处理方式,一种是save命令,执行过程中会阻塞客户端命令。另一种是bgsave,执行过程中不会阻塞客户端命令。
AOF方式:将redis每次执行的写操作命令记录到文件中,一般1s持久化一次,如果要求高,则每次执行命令持久化一次。redis重启会读取AOF中的命令。
混合持久化方案:可选择RDB和AOF结合的方式进行持久化,在两次RDB的间隙进行AOF持久化。redis常用场景有哪些
1.缓存/单点登录:分布式系统中,本地缓存已经不能满足需求,所有服务共享的缓存可以存放在redis中。
2.分布式锁:分布式系统中,java的synchronized锁已经不能满足需求,redis提供的setnx指令以及redis执行指令单线程的机制可以很好的作为分布式锁来使用。
3.计数器:文章的阅读量、微博点赞数每次浏览都得给+1,并发量高时如果每次都请求数据库操作无疑是种挑战和压力。Redis提供的incr命令来实现计数器功能,内存操作,性能非常好,非常适用于这些计数场景。允许一定的延迟,先写入Redis再定时同步到数据库。
4.排行榜:redis的有序集合非常适合做排行榜。
5.简单队列:提供list和set操作,这使得redis能作为一个简单的消息队列平台来使用,对list进行push/pop操作。请讲一下redis锁具体是如何使用端
在string的操作中有一个etx操作,当设置一个不存在的key时,设置成功返回1。当设置的key已经存在时,返回0。由于reds每个操作都是线程安全的,可以通过setmx来获取分布式锁,设置一个指定的key,返回1是获取锁成功,返回0则是获取锁失败,获取锁操作完成后删除释放锁。
以上锁操作存在几个问题:
1.获取锁后,在释放锁之前程序就崩溃了,这样锁就永远释放不了,死锁。
对于该问题的解决方式就是在给锁加一个超时时间,超过一定时间自动释放锁。这时还存在一个问题就是,获取锁和给锁加上超时时间不是一个原子操作,如果在两个操作中程序崩溃也会死锁。这时可以用set命令,可以在设置锁的同时设置超时时间,是一个原子操作。
2.此时锁可以超时自动释放了,但是还有一个问题就是,如果某一时刻网络异常,程序A获取锁后执行时间过长,执行完成之前锁就已经超时释放并被其他程序B获取锁,此时程序A执行完成后释放锁,释放的是B获取的锁。针对这个问题,每次获取锁的时候,把value值设置成一个唯一的值,每次释放锁之前比对一下value是否相同,相同则释放,不同则不释放。此时还有一个问题就是查看value对比和释放锁又是两个操作,如果两个操作中间网络波动,刚好锁过期被其他程序获取,则又释放错锁。此时需要查看value值比对以及删除锁是一个原子操作,可以通过lua脚本解决该问题。lua脚本可以使一组redis操作变成一个原子操作。
3.如果任务没执行完,但是锁超时了,这种情况可以使用一个看门狗机制。A获取锁后,开启一个守护线程,定期为A刷新锁的时间。这样A就是一直保持锁的情况。在redission源码中有相应的处理机制。
以上就是单节点分布式锁的使用流程。在集群情况下,该分布式锁会存在一个问题就是,主节点获得锁后,还没来得及同步到子节点就挂掉了,因此会获得多个锁。redis针对该情况,弓|入了红锁的概念。什么是redis红锁
redis锁在单机情况下使用没问题,但是现在线上基本都是主从或者集群这样多节点的情况。如果是主从情况下,客户端A在主节点获得锁,此时主节点还未来得及将锁同步给其他从节点,就挂掉了。这时哨兵将另外一个从节点选举为主节点,选举完成后客户端B在新选举的从节点上又获得了锁,这个时候就会出现同时获得两把相同的锁的情况。针对该问题,redis提出了一种红锁(RedLock)来解决该问题。
假设有5个redis节点(建议是单数节点),这些节点之间既没有主从,也没有集群关系。客户端用相同的key和随机值在5个节点上请求锁,请求锁的超时时间应小于锁自动释放时间。当在3个(超过半数)redis上请求到锁的时候,才算是真正获取到了锁。如果没有获取到锁,则把部分已锁的redis释放掉。
红锁可以解决redis分布式情况下获取多个锁的问题,但是红锁也不是完美的,如果有节点挂掉,节点数变为偶数,AB两个客户端去获取同一把锁,获取的节点数量相同,则都获取锁失败。不过相对而言redlock还是可靠的。什么redis主从复制
当我们部署一台redis服务器时,会面临几个问题,一是单点故障问题,如果redis服务器挂了就不能提供服务了。二就是高并发访问下可能承受不住大量访问。为了解决以上问题,可以使用redis的主从复制功能。
主从复制就是将一台redis服务器的数据复制到其他的redis服务器。前者称为主节点(master),后者称为从节点(slave)。只能有一个主节点,从节点可以有多个。数据的复制是单向的,从主节点复制到从节点。写操作都在主节点进行,读操作在从节点进行,数据持久化也在主节点进行。
主从复制流程:
开启主从复制后,master服务器会开启一个后台进程用于将redis中的数据生成一个rdb文件,同时master服务器会缓存生成rdb文件过程中所有接收到的来自客户端的写命令(包含增、删、改),当rdb文件生成后,会将该rdb文件传递给slave服务器,而slave服务器会将rdb文件保存在磁盘并通过读取该文件将数据加载到内存,在此之后master服务器会将在此期间缓存的命令通过redis传输协议发送给slave服务器,然后slave服务器将这些命令依次作用于自己本地的数据集上最终达到数据的一致性。
优点:
1.数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
2.故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
3.负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载。尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
缺点:
1.主节点故障后,无法自动进行主从切换,只能读操作不能写操作。需要人工修复故障。什么是redis哨兵
redis主从复制的缺点就是主节点故障后,只能读不能写,无法自动把从节点中选举一个新的主节点出来。redis哨兵的出现就是为了解决这个问题的。
在主从复制中可以配置一个或多个哨兵,哨兵就是一个经过配置的特殊edis服务器,只不过不对客户端提供服务。哨兵的主要作用就是监控主节点和从节点的运行状态,如果主节点故障,哨兵就会自动从剩下的从节点中选举一个作为新的主节点,然后通知其他从节点和客户端新的mster信息。若之前故障的主节点正常后,以从节点的身份加入。什么redis cluster集群?
redis主从复制解决了读操作的负载均衡,没有解决写操作的负载均衡。而且主从复制所有节点的数据都是一样的,存储能力受到单机限制。为解决该问题,redis提供了集群redis cluster。
redis cluster是一个去中心化的集群方式。将数据根据哈希槽算法平均的分配在不同的节点上,每个节点负责存储总体数据的一部分。这样既解决了高并发下读写操作的负载均衡,又解决了单机存储能力的限制,可以水平扩容。并且redis cluster不需要哨兵,自己就具备故障切换能力。
哈希槽算法:Redis Cluster采用哈希分区规则中的虚拟槽分区,共有16384个哈希槽,每个节点负责一部分槽,读写操作时对数据的key进行取模,算出属于哪个槽,从而去哪个节点进行操作。