一.Redis 支持的数据类型有哪些?
基本数据类型
- String:存放的是k-v键值对。如:set k v;
- 使用场景:常规计数,缓存等
- List:有序,可重复。如:lpush mylist v1 v2 v3;
- Set:无序,不可重复。如:sadd myset v1 v2 v3;
- 使用场景:交集:一些共同关注,共同喜好,二度好友(共同好友)都可以使用。
- Hash:在 Redis中哈希类型是指值本身是一种键值对结构,如 value={{field1,value1},……{fieldN,valueN}}。如:hmset myhash k1 v1 k2 v2 k3 v3
- 使用场景:存储对象,存储一些复杂的k-v信息
- zSet:有序,不可重复。虽然set是无序的,但是zSet就是为了让set有序。如:zadd myset 1 v1 2 v2 3 v3
- 使用场景:排行榜。
三大特殊的数据类型
-
Geospatial:这个功能可以将用户给定的地理位置信息(经纬度)储存起来, 并对这些信息进行操作(计算两地的距离,范围等)。
- 使用场景:地图,附件的人...
-
HyperLogLog:可以存储不重复的数据,并且占用很小的内存。虽然set也可以,但是占用空间大。如:pfadd myhyper 1 3 5 6 7 4
- 每个 HyperLogLog 只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。
- 使用场景:适合浏览量一类的业务。
- BitMap位图:存放是/否的操作,如果把true/false放在数据库中,占用空间大。BitMap采用二进制01110010101001...进行存储。如:setbit mybit 7 1;//比如第7天是否打卡
二.RDB和AOF机制
它们都是redis进行持久化的方式。
- RDB:(redis database)
- AOF (append only file)
- 并存:
三.过期键删除策略
redis的过期策略是指:key过期了,redis如何在内部把它删除。
- 惰性过期:只有在使用key的时候,才判断key是否过期,过期清除。不使用的时候就算是过期了,也一直保存在内存中。
- 可以节省cpu资源,但对内存不友好。
- 定时过期:不是redis的策略,指给每一个key都配上定时器。到时间了自动清除key。
- 定期过期:每隔一段时间,会扫描一定数量的expires字典中的key,删除过期的key。
四.线程模型
线程模型:
- 多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO多路复用程序会监听多个 socket,会将产生事件的 socket 放入队列中排队,事件分派器每次从队列中取出一个 socket,根据 socket 的事件类型交给对应的事件处理器进行处理。
一次客户端与redis完整通信过程
- 建立连接
- 首先,redis 服务端进程初始化的时候,会将 server socket 的 AE_READABLE 事件与连接应答处理器关联。
- 客户端 socket01 向 redis 进程的 server socket 请求建立连接,此时 server socket 会产生一个 AE_READABLE 事件,IO 多路复用程序监听到 server socket 产生的事件后,将该 socket 压入队列中。
- 文件事件分派器从队列中获取 socket,交给连接应答处理器。
- 连接应答处理器会创建一个能与客户端通信的 socket01,并将该 socket01 的 AE_READABLE 事件与命令请求处理器关联。
- 执行一个set请求
- 客户端发送了一个 set key value 请求,此时 redis 中的 socket01 会产生 AE_READABLE 事件,IO 多路复用程序将 socket01 压入队列,
- 此时事件分派器从队列中获取到 socket01 产生的 AE_READABLE 事件,由于前面 socket01 的 AE_READABLE 事件已经与命令请求处理器关联,
- 因此事件分派器将事件交给命令请求处理器来处理。命令请求处理器读取 socket01 的 key value 并在自己内存中完成 key value 的设置。
- 操作完成后,它会将 socket01 的 AE_WRITABLE 事件与命令回复处理器关联。
- 如果此时客户端准备好接收返回结果了,那么 redis 中的 socket01 会产生一个 AE_WRITABLE 事件,同样压入队列中,
- 事件分派器找到相关联的命令回复处理器,由命令回复处理器对 socket01 输入本次操作的一个结果,比如 ok,之后解除 socket01 的 AE_WRITABLE 事件与命令回复处理器的关联。
redis单线程快的原因?
- 纯内存操作。
- 核心是基于非阻塞的 IO 多路复用机制。
- C 语言实现,语言更接近操作系统,执行速度相对会更快。
- 单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。
- 总结:就像对于一个请求来说,如果业务逻辑复杂,使用多线程效率就高,用户也可以及时得到回应.。但是请求中如果业务逻辑简单(就像redis,就仅仅是对key进行读写操作),但是请求量大的话, 单线程效率就要高。
五.缓存雪崩,缓存击穿,缓存穿透的区别?
- 缓存雪崩:指缓存(redis)同一时间,大面积的失效。所有请求都到了数据库,相当于redis整个不能用了。
- 缓存击穿:是指访问缓存中没有,但是数据库中有的数据。与缓存雪崩不同的是,它是同时访问同一条热点数据。而不是大量的数据。同时访问同一数据
- 缓存穿透:同时大量访问缓存中和数据库中都不存在的数据,一般就是被恶意攻击。
六.redis事务
既然是事务,就需要保证ACID。
- 原子性(A):事务中单条命令才保证原子性,整个事务并不保证原子性。因为事务不支持回滚
- 一致性(C):Redis舍弃了回滚的设计,基本上也就舍弃对数据一致性的有效保证。
- 隔离性(I):redis单线程天然的隔离性
- 持久性(D):采用RDB和AOF两种方式实现持久化
实现:Redis事务的三个阶段
- 开始事务 (multi)
- 命令入队 (命令),采用FIFO (先进先出)
- 执行事务 (exec)
注意:事务中如果出现命令语法错误(相当于编译时错误),所有命令就不会执行。 事务中如果出现逻辑错误(相当于运行时错误),错误语句不执行,其他命令正常执行。
事务中用到的其他命令:
七.redis集群
redis的集群方案? 四种模式各有优缺点,可根据实际场景进行选择。
哨兵模式选老大的算法?
- 哨兵通过发送命令,等待Redis服务器响应。如果主机宕机,哨兵1先检查到这个信息, 但是不会马上进行选举。这个过程称为主观下线。
- 当其他的哨兵也检查到主机宕机,那么哨兵之间会进行投票选取新的老大,选取成功之后,会通过发布订阅模式,让各个从节点切换主机,这个过程成为客观下线。
- 注意:如果已经客观下线,就算主节点已经恢复,只能作为新的主节点的从节点
Cluster如何实现故障转移
- Redis 集群节点采用
Gossip
协议来广播自己的状态以及自己对整个集群认知的改变。比如一个节点发现某个节点失联了 (PFail),它会将这条信息向整个集群广播,其它节点也就可以收到这点失联信息。 - 如果一个节点收到了某个节点失联的数量 已经达到了集群的大多数,就可以标记该节点为确定下线状态 (Fail),然后向整个集群广播,强迫其它节点也接收该节点已经下线的事实,并立即对该失联节点进行主从切换。
主从复制的原理?
- 全量复制
- 主节点进行RDB或者AOF,然后将持久化文件通过网络发送给从节点,从节点开始启动的时候进行读取,此时从节点是同步的,不能进行数据访问(因为也没有数据),需要消耗IO资源。
- 主节点进行RDB或者AOF,然后将持久化文件通过网络发送给从节点,从节点开始启动的时候进行读取,此时从节点是同步的,不能进行数据访问(因为也没有数据),需要消耗IO资源。
- 增量复制
- 每次主节点更新数据,会发送给从节点,从节点根据偏移量进行增量复制。
- 注意:因为IO非常消耗资源,每次增量进行持久化的时候,会把更新的数据放在主节点的一个叫做 复制积压缓存区的地方,发送给从节点。这样就不至于每次增量复制进行io操作。
- 每次主节点更新数据,会发送给从节点,从节点根据偏移量进行增量复制。
上图相关问题:
- runid:每一个redis实例都有一个id,区别身份。比如主节点发送给从节点就会把自己的id发送过来。主节点宕机了,这个不能使用增量复制。
- 什么时候会由增量复制变为全量复制?
- runid不匹配(比如主节点宕机了,不是之前那个了),或者复制积压缓存区放不下。
寄语:你所浪费的今天是昨天死去的人奢望的明天;你所厌恶的现在,是未来的你回不到的曾经 ---哈佛大学校训
线程模型参照文章:https://www.cnblogs.com/mrmirror/p/13587311.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。