Redis
- C语言实现,非阻塞式IO多路复用
- 全内存数据库、单线程,没有上下文切换问题
- 支持多种数据结构,支持持久化、主从和集群模式
Redis数据类型
- String:字符串,内部可转换成对应的,数字、二进制数组
- Hash:对应着一个Map集合,这个集合中的field和value只能存储字符串
- Set:基于Hash实现,支持集合间的操作
- List:基于链表实现
- ZSet:每个元素都多存储了一个分数信息,用于排序
- GEO:基于ZSet实现,用于存储地理信息,可以计算距离和范围
- Bitmap:其实就是字符串,位图提供了一种操作字符串中单个二进制位的API
- HyperLogLog:基于HyperLogLog算法,使用极小空间,来完成数量统计的数据结构,但是有一定误差,本质还是字符串
Redis内存淘汰机制
- 默认策略:当内存使用达到阈值的时候,就会报错
- volatile/allkeys前缀,是针对设置了过期时间的key或全部key
- lru/lfu/random/ttl算法,全部时间段内最近最少未使用,一段时间内最近最少未使用,随机移除,最早过期
Redis持久化
RDB
快照方式,将数据写入到二进制文件中,恢复的时候加载这个RDB文件,相对于AOF,在数据集很大时,启动效率更高
如果有老的RDB文件,就会先创建一个临时文件,备份命令执行完毕后,再对老文件进行替换,如果持久化时Redis发生故障,就会发生数据丢失
在异步备份时,会调用Linux系统的fork()函数,来创建一个子进程,由子进程来完成备份操作后再通知主进程,有可能在调用fork()方法时阻塞,因为创建子进程也需要内存和时间的
AOF
写日志方式,将命令写在硬盘的缓冲区中,再刷新到AOF文件中,恢复时加载这个AOF文件
有三种向硬盘刷新数据的策略,单个命令刷入,IO开销大;每秒刷入,可能会丢失一秒的数据;由操作系统来决定刷入时机,不可控
相对于RDB文件更大,所以就提供了AOF重写,对数据库本身进行回溯,生成AOF文件,从而减少AOF文件的体积
选择
单独使用RDB可能会造成数据丢失,单独使用AOF恢复速度慢, 而Redis支持同时开启开启两种持久化方式,如果同时使用RDB和AOF两种持久化机制,在Redis重启的时候,会优先使用AOF恢复,因为AOF数据更加完整
缓存穿透、缓存雪崩、缓存击穿
- 缓存雪崩:一时间请求流量直接倒向数据库,数据库无法承受访问压力而崩溃
- 缓存倾斜导致的雪崩:缓存服务器宕机,导致流量直接流向数据库;可以保证缓存服务器的高可用或者做二级缓存来解决
- 缓存同时失效导致的雪崩:可以在进行缓存预热时设置随机过期时间来解决
- 缓存击穿现象导致的雪崩:热点key失效,缓存重建时间比较长,有很多线程都会去查询来重建缓存,导致流量直接流向数据库,可使用互斥锁(分布式锁)来解决,只有第一个线程进行缓存重建,将其他线性阻塞
- 缓存穿透:用户查询数据,数据库和缓存中都不存在,导致无效查询都要经过数据库,可以使用缓存空对象或布隆过滤器来解决
布隆过滤器
就是使用多个相互独立的哈希函数,也就可以得到数据的多个hash值,将二进制向量中对应的bit位置1,在查询时如果是相同的数据,得出的hash值是一样的,所以就能判断出数据是否在数据集中,因为hash碰撞,所以会有一定的错误率,但是一定能保证在数据集中的数据,一定在数据集中,因为要计算的哈希函数是不变的,只能适用于固定数据集,因为当删除数据时,无法准确将某个bit位置0,所以可以再使用一个二进制数组,存储得到该hash值的数量,在删除数据时将该值减1,当减为0时,再将对应的bit位置为0
分布式锁
使用set nx命令,如果key存在则设置失败,返回0,根据返回值判断锁是否被占用,如果没有占用再操作;否则让线程阻塞一段时间后再尝试占用,最好使用ex/px参数,同时设置失效时间,来防止因为某个线程崩溃导致无法释放锁的问题
RedisSentinel
分为哨兵节点和Redis主从节点,客户端通过连接哨兵系统,获得redis主从节点信息,之后再与主从节点进行通信
哨兵节点不存储数据,只用来做故障判断和故障转移,并通知给客户端,如果半数哨兵发现主节点无响应,会选出一个哨兵作为领导,从存活从节点中,选一个复制量最完整的从节点,作为主节点,通知其他的从节点成为新主节点的从节点,然后通知客户端,如果老的主节点复活,就会成为从节点
RedisCluster
所有节点都相互连接、监控和通信,集群节点最好有对应的从节点,否则可能会导致一个节点宕机,以至于整个集群不可用
数据分布主要采用,一致性哈希分区,约定一个长度为2^32^的哈希环(就是哈希值的范围,将范围看作一个环),将每个节点均匀分布到环上,计算出的哈希值一定落在环上,顺时针选择节点对应的数据进行操作,能解决添加一个节点时,所带来的全部数据迁移,因为会添加到环上,一定是在两个节点之间,只会影响到相邻的两个节点,不会影响其他节点,但是任然存在,少量的数据迁移,而且还会导致数据分布不均匀,可以成倍伸缩节点,达到数据分布均匀目的
RedisCluster是采用预设虚拟槽方式,每个槽都对应环上一个虚拟节点,RedisCluster采用CRC16哈希算法进行哈希值的计算,再对16383(即16383个槽)取模,来决定放入哪一个虚拟节点,再让用户决定虚拟节点到物理节点的映射,就算添加新节点,也不会立刻数据迁移,只有用户将虚拟槽分配给新节点时,才会发生数据迁移,从而减少数据迁移过程中,丢数据的可能
Comments NOTHING