单线程Redis性能为何如此之高?
文章原创于公众号:程序猿周先森。本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号。
实际项目开发中现在无法逃避的一个问题就是缓存问题,而缓存问题也是面试必问知识点之一,如果面试官好一点可能会简单的问你二八定律或者热数据和冷数据,但是如果问的深入一点可能就会问到缓存更新、降级、预热、雪崩、穿透等问题,而这些问题可能会拦下大部分平时不怎么关注缓存的朋友,这些问题实际上都和缓存服务器息息相关,我们日常中经常使用的缓存服务器一般有两种:Redis和Memcached。本篇开始正式进入Redis系列文章,本篇主要讲讲Redis使用单线程为何速度还能如此之快?
既然谈到缓存服务器有两种,那我们为何要选择Redis呢?Redis与Memcached两者之间有何区别呢?
Redis 和 Memcached 的区别
Redis支持常见数据类型:Redis 不仅仅支持简单的 key/value 类型的数据,同时还提供string(字符串)、list(链表)、set(集合)、zset(有序集合)和hash(哈希类型)等数据结构的存储。而Memcache 只支持简单的数据类型 String。
Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而 Memecache 把数据全部存在内存之中。
集群模式:Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 Redis 目前是原生支持 Cluster 模式的。
Memcached 是多线程,非阻塞 IO 复用的网络模型;Redis 使用单线程的多路 IO 复用模型。
Redis是一个key-value存储系统。它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了主从同步。简单来说 Redis 就是一个数据库,不过与传统数据库不同的是 Redis 的数据是存在内存中的,所以存写速度非常快,因此 Redis 被广泛应用于缓存方向。Redis 也经常用来做分布式锁。Redis 提供了多种数据类型来支持不同的业务场景。除此之外,Redis 支持事务 、持久化、LUA 脚本、LRU 驱动事件、多种集群方案。Redis中常用的数据类型实际上只有5种:String、Hash、List、Set、ZSet,我们可以先看下这五种基本数据类型的用法:
String
- 常用命令:set、get、decr、incr、mget 等。
String 数据结构是简单的 Key-Value 类型,Value 可以是string或者数字。常规 Key-Value 缓存应用;常规计数:博客数,阅读数等。
Hash
- 常用命令:hget、hset、hgetall 等。
Hash 特别适合用于存储对象。
List
- 常用命令:lpush、rpush、lpop、rpop、lrange 等。
链表是 Redis 最重要的数据结构之一,Redis List 为一个双向链表,支持反向查找和遍历,更方便操作,不过带来了额外的内存开销。
Set
- 常用命令:sadd、spop、smembers、sunion 等。
Set 其实和List都是列表的选项,Set 是可以自动去重的。当需要存储一个不出现重复数据的列表数据,Set 是一个最好的选择。你可以基于 Set 轻易实现交集、并集、差集的操作。
Sorted Set
- 常用命令:zadd、zrange、zrem、zcard 等。
Sorted Set 相比Set增加了一个权重参数 Score,使得集合中的元素能够按 Score 进行有序排列。
数据库工作模式如果按照存储方式进行划分可以分成两种:硬盘数据库和内存数据库。Redis读写数据之所以如此之快实际上就是由于Redis将数据存储在内存中,所以在读写数据时不会受到硬盘I/O速度限制,所以读写速度自然很快。而硬盘数据库则是在内存中储存一个索引,然后根据索引去硬盘中查询对应的值,所以效率肯定会相对更慢。
Redis基于内存采用单线程单进程模型的Key-Value数据库,经过官方测试每秒查询次数可以高达100000+,那为什么Redis如此快呢?最关键的一点其实刚才已经提到过,因为Redis完全基于内存,Redis接收到的大部分请求都是直接操作内存就可以完成的,所以处理请求非常迅速,而且Redis中使用单线程,避免了不必要的上下文切换和竞争锁机制,也不会出现频繁切换线程导致CPU消耗,不会存在多线程的死锁等一系列问题。在Redis中使用多路复用I/O模型,而不是非阻塞I/O,非阻塞I/O之前在Nginx提到过,所以我们不重复介绍,我们重点看看多路I/O复用模型。
多路I/O复用模型实际上是使用select、poll、epoll同时监听多个流的I/O事件,在无I/O事件时也就是空闲状态下会将线程阻塞,当有I/O事件需要处理时,线程就是从阻塞状态下唤醒,然后使用epoll轮询一遍所有发生I/O事件的流。多路复用实际上还就是说多个网络连接复用同一个线程,采用多路I/O复用技术可以让单个进程高效的处理多个连接请求,且Redis在内存中对数据进行操作,所以数据操作速度非常快,所以速度不会受到瓶颈,所以Redis才可以具有很高的吞吐量及性能。Redis的瓶颈主要来源于机器内存或网络带宽,CPU不是Redis的瓶颈所在,再加上单线程更易于实现,所以顺理成章Redis采用单线程的方式,但是使用单线程的方式是无法发挥多核CPU的优势的,比如在进行比较耗时的操作时会使得Redis并发量下降,因为单线程所以某一时刻只能处理一个操作,所以执行耗时操作会导致并发量的下降,有一个简单的解决方案就是在多核CPU下可以单机开多个Redis实例来解决这个问题。
欢迎关注公众号:程序猿周先森。
单线程Redis性能为何如此之高?的更多相关文章
- 【转载】单线程Redis性能为何如此之高?
Redis的优势 性能高不仅跟线程模型有关,它有很多原因,主要有如下3点: 基于内存: 单线程,但IO多路复用的利用率高: 数据结构为高性能优化. 下面分别阐述. Redis的优势:基于内存 性能高低 ...
- redis和memcached有什么区别?redis的线程模型是什么?为什么单线程的redis比多线程的memcached效率要高得多(为什么redis是单线程的但是还可以支撑高并发)?
1.redis和memcached有什么区别? 这个事儿吧,你可以比较出N多个区别来,但是我还是采取redis作者给出的几个比较吧 1)Redis支持服务器端的数据操作:Redis相比Memcache ...
- Redis性能问题排查解决手册(七)
阅读目录: 性能相关的数据指标 内存使用率used_memory 命令处理总数total_commands_processed 延迟时间 内存碎片率 回收key 总结 性能相关的数据指标 通过Red ...
- Redis性能问题排查解决手册
转自:http://www.cnblogs.com/mushroom/p/4738170.html 阅读目录: 性能相关的数据指标 内存使用率used_memory 命令处理总数total_comma ...
- redis性能调优笔记(can not get Resource from jedis pool和jedis connect time out)
对这段时间redis性能调优做一个记录. 1.单进程单线程 redis是单进程单线程实现的,如果你没有特殊的配置,redis内部默认是FIFO排队,即你对redis的访问都是要在redis进行排队,先 ...
- 关于redis性能问题分析和优化
一.如何查看Redis性能 info命令输出的数据可以分为10个分类,分别是: server,clients,memory,persistence,stats,replication,cpu,comm ...
- Redis(二十一):Redis性能问题排查解决手册(转)
性能相关的数据指标 通过Redis-cli命令行界面访问到Redis服务器,然后使用info命令获取所有与Redis服务相关的信息.通过这些信息来分析文章后面提到的一些性能指标. info命令输出的数 ...
- Redis性能调优
Redis性能调优 尽管Redis是一个非常快速的内存数据存储媒介,也并不代表Redis不会产生性能问题.前文中提到过,Redis采用单线程模型,所有的命令都是由一个线程串行执行的,所以当某个命令执行 ...
- 阅读之Redis性能
Redis作为一种KV缓存服务器,有着极高的性能,相对于memcache,Redis支持更多中数据类型,因此在业界广泛应用. Redis为什么快: 数据是存储在内存中的. Redis是单线程的. 将数 ...
随机推荐
- Spring数据库连接
1.C3P0数据库连接 2.DBCP数据库连接 3.Druid数据库连接 C3P0数据库连接: 1.先到(http://www.mvnrepository.com/)Maven网址找到C3P0的数据源 ...
- 学习整理:用webpack4.x构建基本项目
webpack4 在2018年就已经发布了, 相比webpack3,webpack4需要的配置减少了很多,对入口和出口配置都有默认设置可以不用手动设置,但还是要在webpack.config.js中配 ...
- Codeforces 1009D
题意略. 思路: 可知对于一个拥有n个点的图来说,它至少需要有n - 1条边来维持连通性,而且数字1恰好与后面的n - 1个数字互质: 至于n个点的图可以产生合法的互质边的个数的上限,我们可以通过莫比 ...
- three.js实现球体地球城市模拟迁徙
概况如下:1.SphereGeometry实现自转的地球:2.THREE.ImageUtils.loadTexture加载地图贴图材质:3.THREE.Math.degToRad,Math.sin,M ...
- 微软发布了开发社区采用.NET Standard的最新信息
最近,微软发布了开发社区当前采用.NET Standard的最新信息..NET Standard是API的正式规范,现有.NET实现在不同平台的是通用的(从而允许跨平台开发).当前规范(版本2.0)在 ...
- Git学习笔记-相关命令记录
内容来自:https://www.liaoxuefeng.com/wiki/896043488029600/896067074338496 1.Linux安装Git 首先,你可以试着输入git,看看系 ...
- 【故障公告】阿里云 RDS 数据库服务器 CPU 100% 造成全站故障
非常非常抱歉,今晚 19:34 ~ 21:16 园子所使用的阿里云 RDS 数据库服务器突然出现 CPU 100% 问题,造成全站无法正常访问,由此您带来了很大的麻烦,请您谅解. 故障经过是这样的.1 ...
- 解决npm报错:Module build failed: TypeError: this.getResolve is not a function
1.sass-loader的版本过高导致的编译错误,当前最高版本是8.x,需要退回到7.3.1 运行: npm uninstall sass-loader --save-dev(卸载当前版本) npm ...
- P1415 拆分数列 DP
传送门: 题意: 将一个数字串分成许多不同的小串,使得这些小串代表的数字严格递增,要求最后一个数字尽可能地小. 然后满足字典序尽可能大. 思路: 由于最后一个数字要尽可能地小,所以先处理出每个数的L[ ...
- HDU2767Proving Equivalences tarjan缩点,如何求入度和出度最大值
给定一个有向图,问最少增加多少条边后变成强连通图 tarjan求求强连通分量并缩点,如果强连通分量个数为1,则需要边数为0, 否则为缩点后点入度和出度的最大值, 证明:当入度或者出度不为0时 ...