Redis单线程原理
首先必须明确,Redis单线程指的是网络请求模块使用了一个线程(,其他模块仍用了多个线程。并不是一个线程完成了所有功能。原理上,其采用了利用epoll的多路复用特性,因此可以采用单线程处理其网络请求。
Redis数据类型
String:字符串类型,最简单的类型 Hash:类似于Map的一种结构。List:有序列表。Set:无序集合。ZSet:带权值的无序集合,即每个ZSet元素还另有一个数字代表权值,集合通过权值进行排序。
什么情况下使用redis
- 针对热点数据进行缓存
- 对于特定限时数据的存放
- 针对带热点权值数据的排序list
- 分布式锁
redis与memcache的区别
- redis处理网络请求采用单线程模型,而memcache采用多线程异步IO的方式
- redis支持数据持久化,memcache不支持
- redis支持的数据格式比memcache更多
简述缓存穿透
缓存穿透指缓存和数据库均没有需要查询的数据,攻击者不断发送这种请求,使数据库压力过大。
简述缓存穿透的解决方法
- 在数据库操作访问前进行校验,对不合法请求直接返回。
- 对于经常被访问的,并且数据库没有的键,缓存层记录键=null。
简述缓存击穿
缓存击穿指缓存中没有数据,但数据库中有该数据。一般这种情况指特定数据的缓存时间到期,但由于并发用户访问该数据特别多,因此去数据库去取数据,引起数据库访问压力过大
简述缓存击穿的解决方法
- 设置热点数据永远不过期。
- 对并发读数据设置并发锁,降低并发性
简述缓存雪崩
缓存雪崩指缓存中一大批数据到过期时间,而从缓存中删除。但该批数据查询数据量巨大,查询全部走数据库,造成数据库压力过大。
简述缓存雪崩的解决方法
- 缓存数据设置随机过期时间,防止同一时间大量数据过期。
- 设置热点数据永远不过期。
- 对于集群部署的情况,将热点数据均与分布在不同缓存中。
Redis有哪些集群部署方式
- 主从复制
- 哨兵模式
- Cluster集群模式
简述主从复制模式
在主从复制中,有主库(Master)节点和从库(Slave)节点两个角色。从节点服务启动会连接主库,并向主库发送SYNC命令。
主节点收到同步命令,启动持久化工作,工作执行完成后,主节点将传送整个数据库文件到从库,从节点接收到数据库文件数据之后将数据进行加载。此后,主节点继续将所有已经收集到的修改命令,和新的修改命令依次传送给从节点,从节点依次执行,从而达到最终的数据同步。
通过这种方式,可以使写操作作用于主库,而读操作作用于从库,从而达到读写分离。
简述哨兵模式
哨兵模式监控redis集群中Master的工作的状态。在Master主服务器宕机时,从slave中选择新机器当作master,保证系统高可用。
每个哨兵每10秒向主服务器,slave和其他哨兵发送ping。
客户端通过哨兵,由哨兵提供可供服务的redis master节点。
哨兵只需要配master节点,会自动寻找其对应的slave节点。
监控同一master节点的哨兵会自动互联,组成哨兵网络,当任一哨兵发现master连接不上,即开会投票,投票半数以上决定Master下线,并从slave节点中选取master节点。
cluster集群
cluster提出了虚拟槽的概念。
- redis cluster默认有16384个槽,在集群搭建的时候,需要给节点分配哈希槽尽可能相同数量虚拟槽。
- 如果目前redis执行set操作,redis先对这个key经过CRC16 hash运算,并把结果对16384取余,得到槽编号。
- 根据槽编号,寻找到其对应的redis节点,在节点上执行hash命令。
- 如果此时执行get操作,节点先验证该key对应的槽编号是不是归本节点管,如果是则保存数据。如果不是,则发送正确节点编号给客户端。
简述Redis的RDB
RDB即将当前数据生成快照,并保存于硬盘中。可以通过手动命令,也可以设置自动触发。
简述Redis的save命令
save命令是redis手动触发RDB过程的命令。使用该命令后,服务器阻塞,直到RDB过程完成后终止。该过程占用内存较多。
简述Redis的bgsave命令
bgsave命令不阻塞主进程(严格意义上也不是完全不阻塞,详看下面过程),该命令fork一个子进程用于执行RDB过程。其具体过程为:
- 判断此时有没有子进程用于RDB,有的话直接返回。
- redis进行fork子进程过程,此时父进程处于阻塞状态。
- 子进程创建RDB文件,完成后返回给父进程
简述Redis自动触发RDB机制
- 通过配置文件,设置一定时间后自动执行RDB
- 如采用主从复制过程,会自动执行RDB
- Redis执行shutdown时,在未开启AOF后会执行RDB
简述Redis的AOF
AOF通过日志,对数据的写入修改操作进行记录。这种持久化方式实时性更好。通过配置文件打开AOF。
简述AOF的持久化策略
- always。每执行一次数据修改命令就将其命令写入到磁盘日志文件上。
- everysec。每秒将命令写入到磁盘日志文件上。
- no。不主动设置,由操作系统决定什么时候写入到磁盘日志文件上。
简述AOF的重写
随着客户端不断进行操作,AOF对应的文件也越来越大。redis提供了bgrewriteaof函数,针对目前数据库中数据,在不读取原有AOF文件的基础上,重写了一个新的AOF文件,减少文件大小。
RDB与AOF优缺点比较
AOF占用的文件体积比RDB大。一般来说利用AOF备份对系统的消耗比RDB低。对于备份时出现系统故障,RDB数据可能会全丢,但AOF只会损失一部分。RDB恢复速度比AOF低。
Redis 专题
0 Redis是什么?
-
是一个完全开源免费的key-value内存数据库
-
通常被认为是一个数据结构服务器,主要是因为其有着丰富的数据结构 strings、map、 list、sets、 sorted sets
Redis数据库
通常局限点来说,Redis也以消息队列的形式存在,作为内嵌的List存在,满足实时的高并发需求。在使用缓存的时候,redis比memcached具有更多的优势,并且支持更多的数据类型,把redis当作一个中间存储系统,用来处理高并发的数据库操作
Redis优点
-
速度快:使用标准C写,所有数据都在内存中完成,读写速度分别达到10万/20万
-
持久化:对数据的更新采用Copy-on-write技术,可以异步地保存到磁盘上,主要有两种策略,一是根据时间,更新次数的快照(save 300 10 )二是基于语句追加方式(Append-only file,aof)
-
自动操作:对不同数据类型的操作都是自动的,很安全
-
快速的主-从复制,官方提供了一个数据,Slave在21秒即完成了对Amazon网站10G key set的复制。
-
Sharding技术: 很容易将数据分布到多个Redis实例中,数据库的扩展是个永恒的话题,在关系型数据库中,主要是以添加硬件、以分区为主要技术形式的纵向扩展解决了很多的应用场景,但随着web2.0、移动互联网、云计算等应用的兴起,这种扩展模式已经不太适合了,所以近年来,像采用主从配置、数据库复制形式的,Sharding这种技术把负载分布到多个特理节点上去的横向扩展方式用处越来越多。
Redis缺点
-
是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
-
Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。
1 五种数据类型
但是在说之前,我觉得有必要先来了解下 Redis 内部内存管理是如何描述这 5 种数据类型的。
首先 Redis 内部使用一个 redisObject
对象来表示所有的 key
和 value
。
redisObject
最主要的信息如上图所示:type
表示一个 value
对象具体是何种数据类型,encoding
是不同数据类型在 Redis 内部的存储方式。
比如:type=string
表示 value
存储的是一个普通字符串,那么 encoding
可以是 raw
或者 int
。
下面简单说下 5 种数据类型:
①String 是 Redis 最基本的类型,可以理解成与 Memcached一模一样的类型,一个 Key 对应一个 Value。Value 不仅是 String,也可以是数字。
String 类型是二进制安全的,意思是 Redis 的 String 类型可以包含任何数据,比如 jpg 图片或者序列化的对象。String 类型的值最大能存储 512M。
②Hash是一个键值(key-value)的集合。Redis 的 Hash 是一个 String 的 Key 和 Value 的映射表,Hash 特别适合存储对象。常用命令:hget
,hset
,hgetall
等。
③List列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边) 常用命令:lpush
、rpush
、lpop
、rpop
、lrange
(获取列表片段)等。
应用场景:List 应用场景非常多,也是 Redis 最重要的数据结构之一,比如 Twitter 的关注列表,粉丝列表都可以用 List 结构来实现。
数据结构:List 就是链表,可以用来当消息队列用。Redis 提供了 List 的 Push 和 Pop 操作,还提供了操作某一段的 API,可以直接查询或者删除某一段的元素。
实现方式:Redis List 的是实现是一个双向链表,既可以支持反向查找和遍历,更方便操作,不过带来了额外的内存开销。
④Set 是 String 类型的无序集合。集合是通过 hashtable 实现的。Set 中的元素是没有顺序的,而且是没有重复的。常用命令:sdd
、spop
、smembers
、sunion
等。
应用场景:Redis Set 对外提供的功能和 List 一样是一个列表,特殊之处在于 Set 是自动去重的,而且 Set 提供了判断某个成员是否在一个 Set 集合中。
⑤Zset 和 Set 一样是 String 类型元素的集合,且不允许重复的元素。常用命令:zadd
、zrange
、zrem
、zcard
等。
使用场景:Sorted Set 可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。
当你需要一个有序的并且不重复的集合列表,那么可以选择 Sorted Set 结构。
和 Set 相比,Sorted Set关联了一个 Double 类型权重的参数 Score,使得集合中的元素能够按照 Score 进行有序排列,Redis 正是通过分数来为集合中的成员进行从小到大的排序。
实现方式:Redis Sorted Set 的内部使用 HashMap 和跳跃表(skipList)来保证数据的存储和有序,HashMap 里放的是成员到 Score 的映射。
而跳跃表里存放的是所有的成员,排序依据是 HashMap 里存的 Score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
数据类型应用场景总结:
| 类型 | 简介 | 特性 | 场景 |
| - | - | - | - |
|string(字符串)|二进制安全|可以包含任何数据,比如jpg图片或者序列化对象| … |
|Hash(字典)|键值对集合,(dict in Python)|适合存储对象,并且可以像数据库中的update一个属性一样只修改某项属性值| 存储、读取、修改用户属性 |
|List(列表)|链表(双向链表)|增删快,提供了操作某一元素的api| 最新消息排行;消息队列 |
|Set(集合)|hash表实现,元素不重复|添加、删除、查找的复杂度都是O(1),提供了求交集、并集、差集的操作| 共同好友;利用唯一性,统计访问网站的ip |
|Zset(有序集合)|将set中的元素增加一个权重参数score,元素按score有序排列|数据插入集合时,已经进行了天然排序| 排行榜;带权重的消息队列 |
2 Redis 持久化
-
RDB(Redis DataBase):快照形式是直接把内存中的数据保存到一个 dump 的文件中,定时保存,保存策略。
-
AOF(Append Only File):把所有的对 Redis 的服务器进行修改的命令都存到一个文件里,命令的集合。Redis 默认是快照 RDB 的持久化方式。
RDB 是怎么工作的
默认 Redis 是会以快照"RDB"的形式将数据持久化到磁盘的一个二进制文件 dump.rdb。
工作原理简单说一下:当 Redis 需要做持久化时,Redis 会 fork 一个子进程,子进程将数据写到磁盘上一个临时 RDB 文件中。当子进程完成写临时文件后,将原来的 RDB 替换掉,这样的好处是可以 copy-on-write。
-
RDB 的优点是:这种文件非常适合用于备份:比如,你可以在最近的 24 小时内,每小时备份一次,并且在每个月的每一天也备份一个 RDB 文件。这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。RDB 非常适合灾难恢复。
-
RDB 的缺点是:如果你需要尽量避免在服务器故障时丢失数据,那么RDB不合适你。
AOF 是怎么工作的
使用 AOF 做持久化,每一个写命令都通过 write 函数追加到 appendonly.aof 中,配置方式如下:
|
|
AOF 可以做到全程持久化,只需要在配置中开启 appendonly yes。这样 Redis 每执行一个修改数据的命令,都会把它添加到 AOF 文件中,当 Redis 重启时,将会读取 AOF 文件进行重放,恢复到 Redis 关闭前的最后时刻。
-
优点是会让 Redis 变得非常耐久。可以设置不同的 Fsync 策略,AOF的默认策略是每秒钟 Fsync 一次,在这种配置下,就算发生故障停机,也最多丢失一秒钟的数据。
-
缺点是对于相同的数据集来说,AOF 的文件体积通常要大于 RDB 文件的体积。根据所使用的 Fsync 策略,AOF 的速度可能会慢于 RDB。
AOF和RDB选择
-
如果你非常关心你的数据,但仍然可以承受数分钟内的数据丢失,那么可以只使用 RDB 持久。
-
AOF 将 Redis 执行的每一条命令追加到磁盘中,处理巨大的写入会降低Redis的性能
-
数据库备份和灾难恢复:定时生成 RDB 快照非常便于进行数据库备份,并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度快。
当然了,Redis 支持同时开启 RDB 和 AOF,系统重启后,Redis 会优先使用 AOF 来恢复数据,这样丢失的数据会最少。
redis的持久化开启了RDB和AOF下重启服务是如何加载的
1) AOF持久化开启且存在AOF文件时,优先加载AOF文件,
2) AOF关闭或者AOF文件不存在时,加载RDB文件,
3) 加载AOF/RDB文件成功后,Redis启动成功。
4) AOF/RDB文件存在错误时,Redis启动失败并打印错误信息
3 Redis 应用
bitmap 简介及相关应用
1 统计某用户登录天数
2 查看活跃用户总数
https://blog.csdn.net/ctwctw/article/details/105013817
4 Redis为什么这么快
-
Redis 完全基于内存,绝大部分请求是纯粹的内存操作,非常迅速,数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度是 O(1)。
-
数据结构简单,对数据操作也简单。
-
采用单线程,避免了不必要的上下文切换和竞争条件,不存在多线程导致的 CPU 切换,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有死锁问题导致的性能消耗。
-
使用多路复用 IO模型,非阻塞 IO。
-
使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
多路 I/O 复用模型
多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。
采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。
5 Redis 和 Memcached 的区别
-
存储方式上:Memcache 会把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。Redis 有部分数据存在硬盘上,这样能保证数据的持久性。
-
数据支持类型上:Memcache 对数据类型的支持简单,只支持简单的 key-value,,而 Redis 支持五种数据类型。
-
使用底层模型不同:它们之间底层实现方式以及与客户端之间通信的应用协议不一样。Redis 直接自己构建了 VM 机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
-
Value 的大小:Redis 可以达到 1GB,而 Memcache 只有 1MB。
6 Redis 的淘汰策略
-
volatile-lru:从设置过期时间的数据集(
server.db[i].expires
)中挑选出最近最少使用的数据淘汰。没有设置过期时间的key不会被淘汰,这样就可以在增加内存空间的同时保证需要持久化的数据不会丢失。 -
volatile-ttl:除了淘汰机制采用LRU,策略基本上与volatile-lru相似,从设置过期时间的数据集(
server.db[i].expires
)中挑选将要过期的数据淘汰,ttl值越大越优先被淘汰。 -
volatile-random:从已设置过期时间的数据集(
server.db[i].expires
)中任意选择数据淘汰。当内存达到限制无法写入非过期时间的数据集时,可以通过该淘汰策略在主键空间中随机移除某个key。 -
allkeys-lru:从数据集(
server.db[i].dict
)中挑选最近最少使用的数据淘汰,该策略要淘汰的key面向的是全体key集合,而非过期的key集合。 -
allkeys-random:从数据集(
server.db[i].dict
)中选择任意数据淘汰。 -
no-enviction:禁止驱逐数据,也就是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失,这也是系统默认的一种淘汰策略。
- Redis 4.0 加入了
LFU
(least frequency use)淘汰策略,包括 volatile-lfu 和 allkeys-lfu,通过统计访问频率,将访问频率最少,即最不经常使用的 KV 淘汰。
7 Redis部署
-
redis单例
-
主从模式
-
sentinel
-
集群
详见:https://cloud.tencent.com/developer/article/1440480