Redis作为内存型数据,为了高可用,必须有数据备份,这里采取主从的模式。
用户可以通过执行 SLAVEOF 命令或者设置 slaveof 选项,让一个服务器去复制 (replicate) 另一个服务器。
Redis持久化:RDB与AOF
Redis是内存型数据库,所有数据都存储在内存中。而内存是易失型存储,一旦进程退出所有数据都会丢失。
所谓持久化,就是将Redis在内存中的数据库状态以某次格式保存到磁盘里面,避免数据意外丢失。
Redis有两种持久化方式:RDB (Redis Database)、AOF (Append Only File)
缓存淘汰算法之LFU
Least Frequently Used (LFU) 是一种常见的缓存淘汰算法,译为“最近最不经常使用”,也就是将缓存中使用次数最少的数据淘汰掉。
有两种常见的实现方法
- 小顶堆 + hashmap,插入和删除的复杂度为O(logN), 但淘汰相同访问次数的节点是不稳定的,因为堆排序不稳定。
- 数组存储数据项 + hashmap记录数据项index, 淘汰缓存的复杂度为O(N)
缓存淘汰算法之LRU
说到缓存,就必须先了解下计算机的存储器层次结构。
存储器层次结构的主要思想是上一层的存储器作为低一层存储器的高速缓存。
计算机系统中的存储设备都被组织成了一个存储器层次结构,从上至下,设备的访问速度越来越慢、容量越来越大,并且越便宜。
一致性哈希原理及实现
一致性哈希是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位(slots)数的改变平均只需要对 K/n 个key需要重新映射,其中K是key的数量,n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。
谈到一致性哈希(Consistent hashing),就得先讲一下分布式存储。
比如我们有2000w条数据,一台机器存不下,那么我们可以把分成10份每份200w条存到10台机器上。
这样存储就不成问题,但是查询效率很低,查一条数据要每台机器都查一遍。
如果这些数据能够分类,每一类存到一台机器上,查询前先知道数据的类别,就可以直接定位到某台机器,效率就高了。
布隆过滤器原理及实现
布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。
它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
Bitmap 原理及实现
所谓的 Bitmap 其实就是二进制位数组,由于元素是二进制位,每一个元素只占用1个bit,十分节省内存空间。
每一个bit有0、1两种状态,所以 Bitmap 适合应用于判断是否存在、桶排序(不含重复元素),具体来说可以用bitmap记录ip信息,实现布隆过滤器等等。
限流算法之漏桶与令牌桶
后端一个常见且比较让人头疼的问题是服务限流,没有做好限流开始导致单个服务耗时增加,进而影响上下游服务,最终可能导致整个系统被拖垮。
限流的目的是通过对并发请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队 或等待、降级。
Redis原理 —— ziplist 压缩列表
压缩列表(ziplist)是列表和哈希的底层实现之一,是为尽可能地节约内存而设计的特殊编码双端链表。 当一个列表只包含少量列表项,并且每个列表项要么就是小整数值,要么就是长度比较短的字符串,那么Redis就会使用压缩列表来做列表键的底层实现。
压缩列表的优点是节省内存,缺点是插入元素的复杂度较高平均O(N)最坏O(N^2)
, 但是在小数据量的情况下,这种复杂度也是可以接受的。
Redis原理 —— SDS 简单动态字符串
Redis没有直接使用C语言传统的字符串表示,而是自己构建了一种名为简单动态字符串SD S(simple dynamic string)的数据结构 ,并将SDS用作Redis的默认字符串表示。
Redis内部所有字符串都由SDS来表示,其本质就是动态字节数组,和python的bytearray
类似。
Redis原理 —— zskiplist 跳跃表
跳跃表 (skiplist) 是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的 指针,从而达到快速访问节点的目的。
跳跃表优点
- 表支持平均
O(logN)
, 最坏O(N)
复杂度的节点查找,效率可以和平衡树相当 - 通过顺序性操作来批量处理节点
- 实现比平衡树要来得更为简单
因为ziplist
内存占用较小,所以Redis使用作为有序集合的初始底层结构。
如果一个有序集合包含的元素数量比较多(大于zset-max-ziplist-entries
),又或者有序集合中元素的成员是比较长的字符串时(大于zset-max-ziplist-value
),Redis就会将其底层结构转换为跳跃表。