Redis
Redis是一个基于内存
的高性能key-value
数据库
特点
- Redis本质上是一个Key-Value类型的
内存数据库
,很像memcached,整个数据库统统加载在内存当中进行操作
,定期通过异步操作
把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过10万
次读写操作,是已知性能最快的Key-Value DB
。 - Redis是支持
保存多种数据结构
,此外单个value的最大限制是1GB
,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性能消息队列服务
,用他的Set可以做高性能的tag系统等等。另外Redis也可以对存入的Key-Value设置expire时间
,因此也可以被当作一 个功能加强版的memcached来用。 - 主要缺点是
数据库容量受到物理内存的限制
,不能用作海量数据的高性能读写
,因此Redis适合的场景主要局限在较小数据量
的高性能操作和运算上。
支持的数据类型
- Strings
- Lists
- Sets
- Sorted Set
- hashes
为什么redis需要把所有数据放到内存中?
Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能
单进程,单线程
- redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销
分布式
- redis支持主从的模式。原则:Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来同步数据。
- 这是一个典型的分布式读写分离模型。我们可以利用master来插入数据,slave提供检索服务。这样可以有效减少单个机器的并发访问数量
读写分离
- 通过增加Slave DB的数量,读的性能可以线性增长。为了避免Master DB的单点故障,集群一般都会采用两台Master DB做双机热备,所以整个集群的读和写的可用性都非常高。
- 读写分离架构的缺陷在于,不管是Master还是Slave,每个节点都必须保存完整的数据,如果在数据量很大的情况下,集群的扩展能力还是受限于单个节点的存储能力,而且对于Write-intensive类型的应用,读写分离架构并不适合。
数据分片
- 为了解决读写分离模型的缺陷
- 将每个节点看成都是独立的master,然后通过业务实现数据分片
使用redis好处
- 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
- 支持丰富数据类型,支持string,list,set,sorted set,hash
- 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
- 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
redis相比memcached有哪些优势
- memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
- redis的速度比memcached快很多
- redis可以持久化其数据
Redis回收策略
- volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
- allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
- no-enviction(驱逐):禁止驱逐数据
缓存穿透
一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。如果key对应的value是一定不存在的,并且对该key并发请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透
- 如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,
缓存雪崩
缓存服务器重启或者大量缓存到期时间一致,集中在某个时间段失效,这样在失效的时候给后台带来很大的压力
- 并发量不大的时候可以选择加锁,多个线程同时只允许一个线程请求数据库
- 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存
- 二级缓存,两个缓存过期时间设置不一致,缓存A失效后去缓存B查找
缓存淘汰的策略有两种: (1) 定时去清理过期的缓存。 (2)当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。
两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂,具体用哪种方案,大家可以根据自己的应用场景来权衡。
- 预估失效时间 2. 版本号(必须单调递增,时间戳是最好的选择)3. 提供手动清理缓存的接口。
Redis哨兵(Redis Sentinel)
Redis 的
主从复制
模式下,一旦主节点
由于故障不能提供服务,需要手动将从节点
晋升为主节点
,同时还要通知客户端
更新主节点
地址,这种故障处理方式从一定程度上是无法接受的。Redis 2.8 以后提供了 Redis Sentinel哨兵机制
来解决这个问题
Redis哨兵是用来管理多个redis实例的工具,可以实现对redis的监控、通知和自动故障转移
基本名词说明:
基本名词 | 逻辑结构 | 物理结构 |
---|---|---|
Redis数据节点 | 主节点和从节点 | 主节点和从节点的进程 |
主节点(master) | Redis主数据库 | 一个独立的Redis进程 |
从节点(slave) | Redis从数据库 | 一个独立的Redis进程 |
Sentinel节点 | 监控Redis数据节点 | 一个独立的Sentinel进程 |
Sentinel节点集合 | 若干Sentinel节点的抽象组合 | 若干Sentinel节点进程 |
Redis Sentinel | Redis高可用实现方案 | Sentinel节点集合和Redis数据节点进程 |
应用客户端 | 泛指一个或多个客户端 | 一个或者多个客户端进程或者线程 |
Redis主从复制的问题
Redis 主从复制 可将 主节点 数据同步给 从节点,从节点此时有两个作用:
1、一旦主节点宕机,从节点作为主节点的备份可以随时顶上来。
2、扩展主节点的读能力
,分担主节点读压力
主从复制 同时存在以下几个问题:
- 一旦主节点宕机,从节点晋升成主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制 新的主节点,整个过程需要人工干预。
- 主节点的写能力受到单机的限制。
- 主节点 的存储能力受到单机的限制。
- 原生复制的弊端在早期的版本中也会比较突出,比如:Redis 复制中断后,从节点会发起 psync。此时如果同步不成功,则会进行全量同步,主库执行全量备份的同时,可能会造成毫秒或秒级的卡顿。
Redis集群
Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施
Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
Redis 集群提供了以下两个好处:
- 将数据自动切分(split)到多个节点的能力。
- 当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。
数据分片
Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。
集群中的每个节点负责处理一部分哈希槽
redis集群投票机制
redis集群中有多台redis服务器不可避免会有服务器挂掉。redis集群服务器之间通过互相的ping-pong判断是否节点可以连接上。如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机了
网友评论