一、简介
Redis是速度非常快的非关系型(NoSQL)内存键值数据库。可以存储键和5种不同类型的值之间的映射。
key的类型只能为字符串,value支持6中类型:String,Hash,List,Set,zset,HyperLogLog
Redis支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能,使用分片来扩展写性能。
二、数据类型
数据类型 | 可以存储的值 | 操作 |
---|---|---|
String | 字符串,整数和浮点数 | 对整个字符串或者字符串的其中一部分执行操作,对整数和浮点数执行自增或者自减操作。 |
List | 列表 | 从两端压入或者弹出元素,对单个或者多个元素进行修剪,只保留一个范围内的元素。 |
Set | 无序集合 | 添加,获取,移除单个元素,检查一个元素是否存在于集合中,计算交集,并集,差集,从集合里面随机获取元素,去重。 |
Hash | 包含键值对的无序散列表 | 添加,获取,移除单个键值对,获取素有键值对,检查某个键是否存在。 |
Zset | 有序集合 | 添加,获取,删除元素,根据分值范围或者成员来获取元素计算一个键的排名 |
有点类似公司用的Wtable,每次用col key去获取数据。获取的数据里,有数据的,有字符串的,有对象的。
三、数据结构
1、字典
dictht是一个散列表结构,使用拉链法解决哈希冲突。
1 | typedef struct dictht{ |
Redis的字典dict中包含两个哈希表dictht,只是为了方便进行rehash操作。在扩容的时候,将其中一个dictht上的键值对rehash到另一个dictht上面,完成之后释放空间并交换两个dictht的角色。
rehash操作不是一次性完成,而是采用渐进方式,这是为了避免一次性执行过多的rehash操作给服务器带来过大的负担。
渐进式rehash通过记录dict的rehashidx完成,他从0开始,然后每执行一次rehash都会递增。
2、跳跃表
是有序集合的底层实现之一。
跳跃表是基于多指针有序链表实现的,可以看成多个有序链表。
在查找时候,从上层指针开始查找,找到对应的区间之后再到下一层去查找。
与红黑树等平衡树相比,跳跃表具有以下优点:
- 插入速度非常快,因为不需要进行旋转等操作来维护平衡性。
- 更容易实现
- 支持无锁操作。
四、Redis使用场景
1、计数器
可以对String进行自增自减运算,从而实现计数器功能。
Redis这种内存型数据库的读写性能非常高,很适合存储频繁读写的及数量。
2、缓存
将热点数据存放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。
3、查找表
例如DNS的记录就很适合使用Redis进行存储。
查找表和缓存类似,也是利用Redis快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效,因为缓存不作为可靠地数据来源。
4、消息队列
List是一个双向链表,可以通过lpush和rpop写入和读取消息
不过最好使用kafka,RabbitMQ等消息中间件。
5、Session缓存
可以使用Redis来同一个存储多台应用服务器的Session信息。
当应用服务器不在存储用户的会话信息,也就不再具有状态。一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。
6、分布式锁实现
在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。
可以使用Redis子代的SETNX命令实现分布式锁,除此之外,还可以使用官方提供的RedLock分布式锁实现。
7、其他
Set可以实现交集,并集等操作,从而实现共同好友等功能 。
Zset可以shixi9an有序性操作,从而实现排行榜等功能。
五、Redis与Memcached
两个都是非关系型内存键值数据库。主要区别如下:
1、数据类型
Memcached只支持string类型,而Redis支持5种不同的数据类型,可更灵活的解决问题。
2、数据持久化
Redis支持3种持久化策略:RDB快照和AOF日志,RDB和AOF混合型,而Memcached不支持持久化。
3、分布式
Memcached不支持分布式,只能通过咋客户端使用一致性哈希来实现分布式存储,这种方式在存储和查询时都需要现在客户端计算一次数据所在的节点。
Redis Cluster实现了分布式的支持。
4、内存管理机制
- 在Redis中,并不是所有数据都是一直存在内存里,可以将一些很久没用的value交换到磁盘,而Memcached的数据则会一直在内存中。
- Memcached将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题,但是这种方式会使得内存的利用率不高。比如块代销为128b,只存储100b的数据,那么剩下的28b就浪费掉了。
六、Redis的key过期时间
Redis可以为每个key设置过期时间,当key过期时,会自动删除该key。
对于散列表这种容器,只能为整个key设置过期时间(整个散列表),而不能为key里面的单个元素设置过期时间。
七、数据淘汰策略
Redis可以设置内存最大使用量,当内存使用量超出时,会施行数据淘汰策略。
Redis具有6种淘汰策略:
策略 | 描述 |
---|---|
volatile-LRU | 当内存使用量超出时,此种策略,从已经设置过期时间的数据集中选出最近最少使用的数据淘汰 |
volatile-TTL | 当内存使用量超出时,此种策略,从已经设置过期时间的数据集中选出将要过期的数据淘汰 |
volatile-Random | 当内存使用量超出时,此种策略,从已经设置过期时间的数据中任意选择数据淘汰 |
allkeys-LRU | 当内存使用量超出时,此种策略,从所有数据中挑选最近最少使用的数据淘汰。 |
allkeys-Random | 当内存使用量超出时,此种策略,从所有数据中选任意数据进行淘汰 |
noeviction | 禁止驱逐数据 |
作为内存数据库,处于对性能和内存消耗的考虑,Redis的淘汰算法实际实现上并非针对素有key,而是抽样一小部分并且从中选出被淘汰的key。
使用Redis缓存数据时,为了提高缓存命中率,需要保证缓存数据都是热点数据。可以将内存最大使用量设置为热点数据占用的内存量,然后启用allkeys-LRU淘汰策略,将最近最少使用的数据淘汰。
Redis4.0引入了volatile-LFU,allkeys-LFU淘汰策略,LFU策略通过统计访问频率,将访问频率最少的键值对淘汰。
八、持久化
Redis是内存型数据库,为了保证数据在断电后不会丢失,需要将内存中的数据持久化到硬盘上。
1、RDB持久化
- 将某个时间点的所有数据都存到硬盘上
- 可以将快照复制到其他服务器从而创建具有相同数据的服务器副本。
- 如果系统发生故障,将会丢失最后一次创建快照之后的数据。
- 如果数据量很大,保存快照的时间会很长。
2、AOF持久化
将写命令添加到AOF文件(Append Only File)的末尾。
使用AOF持久化需要设置同步选项,从而确保写命令同步到磁盘文件上的时机。这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘。有以下同步选项:
选项 | 同步频率 |
---|---|
always | 每个写命令都同步 |
everysec | 每秒同步一次 |
no | 让操作系统决定何时同步 |
- always选项会严重降低服务器的性能。
- everysec选项比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且Redis每秒执行一次同步对服务器性能几乎没有任何影响。
- no选项并不能给服务器性能带来多大的提升,而且也会增加系统崩溃时数据丢失的数量。
随着服务器写请求的增多,AOF文件也会越来越大。Redis提供了一种将AOF重写特性,能够去除AOF文件中的冗余写命令。
九、事务
一个事务包含了多个命令,服务器在执行事务期间,不会改去执行其他客户端的命令请求。也就是事务的ACID。
事务中的多个命令被一次性发给服务器,而不是一条一条的发送,这种方式叫流水线,它可以减少客户端和服务器之间的网络通信次数从而提升性能。
Redis最简单的事务实现方式是使用MULTI和EXEC命令来将事务操作包围起来。
十、事件
Redis服务器是一个事件驱动程序。
1、文件事件
- 本文作者: Victor Dan
- 本文链接: https://anonymousdq.github.io/victor.github.io/2019/11/01/一、Redis简介/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!