Redis的优势和特点

📅 发布时间:2026/7/5 7:21:22 👁️ 浏览次数:
Redis的优势和特点
什么是redisRemote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统是跨平台的非关系型数据库。Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库并提供多种语言的 API。Redis 通常被称为数据结构服务器因为值value可以是字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets)等类型。Redis的特点内存数据库速度快也支持数据的持久化可以将内存中的数据保存在磁盘中重启的时候可以再次加载进行使用。Redis不仅仅支持简单的key-value类型的数据同时还提供listsetzsethash等数据结构的存储。Redis支持数据的备份即master-slave模式的数据备份。支持事务Redis的优势性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。原子 – Redis的所有操作都是原子性的同时Redis还支持对几个操作合并后的原子性执行。事务丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。Redis与其他key-value存储有什么不同Redis有着更为复杂的数据结构并且提供对他们的原子性操作这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明无需进行额外的抽象。Redis运行在内存中但是可以持久化到磁盘所以在对不同数据集进行高速读写时需要权衡内存因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是相比在磁盘上相同的复杂的数据结构在内存中操作起来非常简单这样Redis可以做很多内部复杂性很强的事情。同时在磁盘格式方面他们是紧凑的以追加的方式产生的因为他们并不需要进行随机访问。Memcache与Redis的区别都有哪些存储方式 Memecache把数据全部存在内存之中断电后会挂掉数据不能超过内存大小。 Redis有部份存在硬盘上redis可以持久化其数据数据支持类型 memcached所有的值均是简单的字符串redis作为其替代者支持更为丰富的数据类型 提供listsetzsethash等数据结构的存储使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis直接自己构建了VM 机制 因为一般的系统调用系统函数的话会浪费一定的时间去移动和请求。value 值大小不同Redis 最大可以达到 512Mmemcache 只有 1mb。redis的速度比memcached快很多Redis支持数据的备份即master-slave模式的数据备份。Redis为什么这么快1、完全基于内存绝大部分请求是纯粹的内存操作非常快速。数据存在内存中类似于HashMapHashMap的优势就是查找和操作的时间复杂度都是O(1)2、数据结构简单对数据操作也简单Redis中的数据结构是专门进行设计的3、采用单线程避免了不必要的上下文切换和竞争条件也不存在多进程或者多线程导致的切换而消耗 CPU不用去考虑各种锁的问题不存在加锁释放锁操作没有因为可能出现死锁而导致的性能消耗4、使用多路I/O复用模型非阻塞IO5、使用底层模型不同它们之间底层实现方式以及与客户端之间通信的应用协议不一样Redis直接自己构建了VM 机制 因为一般的系统调用系统函数的话会浪费一定的时间去移动和请求6.多路 I/O 复用模型多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力在空闲的时候会把当前线程阻塞掉当有一个或多个流有 I/O 事件时就从阻塞态中唤醒于是程序就会轮询一遍所有的流epoll 是只轮询那些真正发出了事件的流并且只依次顺序的处理就绪的流这种做法就避免了大量的无用操作。**这里“多路”指的是多个网络连接“复用”指的是复用同一个线程。**采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求尽量减少网络 IO 的时间消耗且 Redis 在内存中操作数据的速度非常快也就是说内存内的操作不会成为影响Redis性能的瓶颈主要由以上几点造就了 Redis 具有很高的吞吐量。那么为什么Redis是单线程的我们首先要明白上边的种种分析都是为了营造一个Redis很快的氛围官方FAQ表示因为Redis是基于内存的操作CPU不是Redis的瓶颈Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现而且CPU不会成为瓶颈那就顺理成章地采用单线程的方案了毕竟采用多线程会有很多麻烦。Redis 数据类型及命令1.字符串(String)redis 127.0.0.1:6379 SET rediskey redis OK redis 127.0.0.1:6379 GET rediskey redis2. 哈希(Hash)Redis hash 是一个 string 类型的 field字段 和 value值 的映射表hash 特别适合用于存储对象。Redis 中每个 hash 可以存储 232 - 1 键值对40多亿3. 列表(List)Redis列表是简单的字符串列表按照插入顺序排序。你可以添加一个元素到列表的头部左边或者尾部右边一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。redis 127.0.0.1:6379 LPUSH rediskey redis (integer) 1 redis 127.0.0.1:6379 LPUSH rediskey mongodb (integer) 2 redis 127.0.0.1:6379 LPUSH rediskey mysql (integer) 3 redis 127.0.0.1:6379 LRANGE rediskey 0 10 1) mysql 2) mongodb 3) redis4. 集合(Set)Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的这就意味着集合中不能出现重复的数据。集合对象的编码可以是 intset 或者 hashtable。Redis 中集合是通过哈希表实现的所以添加删除查找的复杂度都是 O(1)。集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。redis 127.0.0.1:6379 SADD rediskey redis (integer) 1 redis 127.0.0.1:6379 SADD rediskey mongodb (integer) 1 redis 127.0.0.1:6379 SADD rediskey mysql (integer) 1 redis 127.0.0.1:6379 SADD rediskey mysql (integer) 0 redis 127.0.0.1:6379 SMEMBERS rediskey 1) mysql 2) mongodb 3) redis5. 有序集合(sorted set)Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是通过哈希表实现的所以添加删除查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。6. HyperLogLogRedis 在 2.8.9 版本添加了 HyperLogLog 结构。Redis HyperLogLog 是用来做基数统计的算法HyperLogLog 的优点是在输入元素的数量或者体积非常非常大时计算基数所需的空间总是固定 的、并且是很小的。在 Redis 里面每个 HyperLogLog 键只需要花费 12 KB 内存就可以计算接近 2^64 个不同元素的基 数。这和计算基数时元素越多耗费内存就越多的集合形成鲜明对比。但是因为 HyperLogLog 只会根据输入元素来计算基数而不会储存输入元素本身所以 HyperLogLog 不能像集合那样返回输入的各个元素。什么是基数比如数据集 {1, 3, 5, 7, 5, 7, 8} 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内快速计算基数。实例以下实例演示了 HyperLogLog 的工作过程//添加指定元素到 HyperLogLog 中。 redis 127.0.0.1:6379 PFADD rediskey redis 1) (integer) 1 redis 127.0.0.1:6379 PFADD rediskey mongodb 1) (integer) 1 redis 127.0.0.1:6379 PFADD rediskey mysql 1) (integer) 1 //添加指定元素到 HyperLogLog 中。 redis 127.0.0.1:6379 PFCOUNT rediskey (integer) 37. 发布订阅Redis 发布订阅 (pub/sub) 是一种消息通信模式发送者 (pub) 发送消息订阅者 (sub) 接收消息。Redis 客户端可以订阅任意数量的频道。下图展示了频道 channel1 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系实例以下实例演示了发布订阅是如何工作的需要开启两个 redis-cli 客户端。在我们实例中我们创建了订阅频道名为runoobChat:第一个 redis-cli 客户端redis 127.0.0.1:6379 SUBSCRIBE runoobChat Reading messages... (press Ctrl-C to quit) 1) subscribe 2) runoobChat 3) (integer) 1现在我们先重新开启个 redis 客户端然后在同一个频道 runoobChat 发布两次消息订阅者就能接收到消息。第二个 redis-cli 客户端redis 127.0.0.1:6379 PUBLISH runoobChat Redis PUBLISH test (integer) 1 redis 127.0.0.1:6379 PUBLISH runoobChat Learn redis by runoob.com (integer) 1 # 订阅者的客户端会显示如下消息 1) message 2) runoobChat 3) Redis PUBLISH test 1) message 2) runoobChat 3) Learn redis by runoob.comgif 演示如下开启本地 Redis 服务开启两个 redis-cli 客户端。在第一个 redis-cli 客户端输入SUBSCRIBE runoobChat意思是订阅runoobChat频道。在第二个 redis-cli 客户端输入PUBLISH runoobChat “Redis PUBLISH test”往 runoobChat 频道发送消息这个时候在第一个 redis-cli 客户端就会看到由第二个 redis-cli 客户端发送的测试消息。8. 事务Redis 事务可以一次执行多个命令 并且带有以下三个重要的保证批量操作在发送 EXEC 命令前被放入队列缓存。收到 EXEC 命令后进入事务执行事务中任意命令执行失败其余的命令依然被执行。在事务执行过程其他客户端提交的命令请求不会插入到事务执行命令序列中。一个事务从开始到执行会经历以下三个阶段开始事务。命令入队。执行事务。实例以下是一个事务的例子 它先以MULTI开始一个事务 然后将多个命令入队到事务中 最后由EXEC命令触发事务 一并执行事务中的所有命令redis 127.0.0.1:6379 MULTI OK redis 127.0.0.1:6379 SET book-name Mastering C in 21 days QUEUED redis 127.0.0.1:6379 GET book-name QUEUED redis 127.0.0.1:6379 SADD tag C Programming Mastering Series QUEUED redis 127.0.0.1:6379 SMEMBERS tag QUEUED redis 127.0.0.1:6379 EXEC 1) OK 2) Mastering C in 21 days 3) (integer) 3 4) 1) Mastering Series 2) C 3) Programming单个 Redis 命令的执行是原子性的但 Redis 没有在事务上增加任何维持原子性的机制所以 Redis 事务的执行并不是原子性的。事务可以理解为一个打包的批量执行脚本但批量指令并非原子化的操作中间某条指令的失败不会导致前面已做指令的回滚也不会造成后续的指令不做。这是官网上的说明 From redis docs on transactions:It’s important to note that even when a command fails, all the other commands in the queue are processed – Redis will not stop the processing of commands.比如redis 127.0.0.1:7000 multi OK redis 127.0.0.1:7000 set a aaa QUEUED redis 127.0.0.1:7000 set b bbb QUEUED redis 127.0.0.1:7000 set c ccc QUEUED redis 127.0.0.1:7000 exec 1) OK 2) OK 3) OK如果在 set b bbb 处失败set a 已成功不会回滚set c 还会继续执行。9. 脚本Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为EVAL。redis 127.0.0.1:6379 EVAL return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]} 2 key1 key2 first second 1) key1 2) key2 3) first 4) second10 GEORedis GEO 主要用于存储地理位置信息并对存储的信息进行操作该功能在 Redis 3.2 版本新增。Redis GEO 操作方法有geoadd添加地理位置的坐标。geopos获取地理位置的坐标。geodist计算两个位置之间的距离。georadius根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。georadiusbymember根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。geohash返回一个或多个位置对象的 geohash 值。redis GEOADD Sicily 13.361389 38.115556 “Palermo” 15.087269 37.502669 “Catania”(integer) 2redis GEODIST Sicily Palermo Catania“166274.1516”redis GEORADIUS Sicily 15 37 100 km“Catania”redis GEORADIUS Sicily 15 37 200 km“Palermo”“Catania”redis11 Redis StreamRedis Stream 是 Redis 5.0 版本新增加的数据结构。Redis Stream 主要用于消息队列MQMessage QueueRedis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能但它有个缺点就是消息无法持久化如果出现网络断开、Redis 宕机等消息就会被丢弃。简单来说发布订阅 (pub/sub) 可以分发消息但无法记录历史消息。而 Redis Stream 提供了消息的持久化和主备复制功能可以让任何客户端访问任何时刻的数据并且能记住每一个客户端的访问位置还能保证消息不丢失。Redis Stream 的结构如下所示它有一个消息链表将所有加入的消息都串起来每个消息都有一个唯一的 ID 和对应的内容每个 Stream 都有唯一的名称它就是 Redis 的 key在我们首次使用 xadd 指令追加消息时自动创建。上图解析Consumer Group消费组使用 XGROUP CREATE 命令创建一个消费组有多个消费者(Consumer)。last_delivered_id游标每个消费组会有个游标 last_delivered_id任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。pending_ids消费者(Consumer)的状态变量作用是维护消费者的未确认的 id。 pending_ids 记录了当前已经被客户端读取的消息但是还没有 ack (Acknowledge character确认字符。Redis 管道技术Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤客户端向服务端发送一个查询请求并监听Socket返回通常是以阻塞模式等待服务端响应。服务端处理命令并将结果返回给客户端。Redis 管道技术Redis 管道技术可以在服务端未响应时客户端可以继续向服务端发送请求并最终一次性读取所有服务端的响应。