redis笔记
redis笔记
redis笔记见REDIS6_分布式存储极致性能目录
尚未完成,待续...
Redlcok算法
Redlock算法是redis作者提出的一种分布式锁算法,它的思想是由多个redis(这些redis是相互独立的,不存在主从复制或集群协调机制)实现。在加锁时,客户端首先要设置一个锁的失效时间,然后对每个redis实例进行加锁,如果从大多数的redis节点都取到锁且时间不超过锁的失效时间,那么就视为成功获取了锁;如果未能成功获取锁,那么就在所有redis实例上解锁(即便是没有成功加锁的节点也要再解锁,这是为了防止某些节点获取到锁但是客户端没有得到响应而导致接下来的一段时间不能被重新加锁)。
info
官方推荐Redlock的节点个数为5个,但是也可以是3个或者7个(一般情况都是奇数),只要大多数节点都能成功加锁就可以了。
最低保证分布式锁有效性以及安全性的要求
- 互斥:任何时刻只有一个客户端能持有锁
- 释放死锁:即使锁定资源的服务崩溃或者分区,仍然能释放锁
- 容错性:只要多数redis节点(一半以上)在使用,client就可以获取和释放锁
redis的底层数据结构
redis6相关的底层模型和结构
- String = SDS
- Set = intset + hashtable
- ZSet = skiplist + zipList
- List = quicklist + zipList
- Hash = zipList + hashtable
redis7相关的底层模型和结构
info
在redis7中zipList被listpack紧凑列表替代,有关zipList的配置参数也被listpack替代,但是为了向下兼容,在配置文件中关于zipList的配置参数仍然存在,只不过不再使用,当你修改listpack的参数时,zipList的参数也会跟着改变;修改ziplist的参数时,listpack的参数也会改变,这两个参数是同步的,而实际上使用的都是listpack。
- String = SDS
- Set = intset + hashtable
- ZSet = skiplist + listpack紧凑列表
- List = quicklist + zipList
- Hash = listpack + hashtable
为什么有了ziplist还要有listpack
ziplist在更新数据后可能会出现连锁更新的问题,所以设计出了listpack来替代ziplist,listpack通过每个节点记录自己的长度且放在节点的尾部,来彻底解决掉ziplist存在的连锁更新的问题。
quicklist
redis6中的quicklist
redis6中的quicklist是一个双向链表,双向链表的每个节点都是一个ziplist,redis7中的quicklist也是一个双向链表,但是不同的是它的每个节点都是listpack。
info
在早期的quicklist是有两种的,当列表对象的长度比较小或者数量比较少的时候,采用压缩列表ziplist来存储。当列表对象中元素的长度比较大的或者数量比较多的时候,则会转向双向链表linkedlist来存储。
这两者各有优缺点:
- ziplist的优点是内存紧凑,访问效率高,缺点是插入和删除效率低,并且数据量较大的时候,可能会出现连锁更新的问题。
- linkedlist的优点是插入和删除效率高,缺点是内存不紧凑,并且节点较多的时候,会产生大量的内存碎片。
网络模型-Redis是单线程的吗?为什么使用单线程?
redis到底是单线程还是多线程?
- 如果仅仅看Redis的核心业务部分(命令处理),答案是单线程
- 如果是看整个Redis,那么答案就是多线程
在Redis版本迭代过程中,在两个重要的时间节点上引入了多线程的支持:
- Redis v4.0:引入多线程异步处理一些耗时较旧的任务,例如异步删除命令unlink
- Redis v6.0:在核心网络模型中引入 多线程,进一步提高对于多核CPU的利用率
因此,对于Redis的核心网络模型,在Redis 6.0之前确实都是单线程。
为什么Redis要选择单线程?
- 抛开持久化不谈,Redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度,因此多线程并不会带来巨大的性能提升。
- 多线程会导致过多的上下文切换,带来不必要的开销
- 引入多线程会面临线程安全问题,必然要引入线程锁这样的安全手段,实现复杂度增高,而且性能也会大打折扣