1.redis简介
1. redis是什么
Redis是一个开源的使用ANSI C语言编写、支持网络、单进程单线程、可基于内存亦可持久化的日志型、一个高性能的key-value数据库。
2. Redis与其他key-value存储有什么不同
- 多样的数据结构和原子性操作
++Redis有着更为复杂的数据结构并且提供对他们的原子性操作++,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
- 运行于内存+持久化于磁盘
Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,应为数据量不能大于硬件内存。在内存数据库方面的另一个优点是, ++相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。 同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问++。
3. redis特点
速度快:基于内存,这是快的最主要原因。
持久化:异步保存到磁盘中
多种数据结构:除了五种基本数据类型,还支持位图、HyperLogLog,GEO等
支持多种编程语言:java,python,ruby,php,Lua,nodejs…
功能丰富:可以实现发布-订阅,支持事务、Lua脚本
简单:不依赖与外部库、单线程模型
主从复制:主服务器同步数据到从服务器,是高可用的基础
高可用、分布式:高可用:redis-Sentinel(v2.8版本);分布式:redis-cluster(v3.0版本)
4. redis典型应用场景
缓存系统:这个就不多说了,redis作为高速缓存是其主要存在价值。
计数器:因为是原子操作+单线程,作为计数器永远不会出错
消息队列系统:数据结构可以实现这种生产者-消费者模式的消息队列。
排行榜:有序集合sorted set就可以实现
社交网络:redis与社交网络就是一家,非常方便就能实现诸如共同好友这些功能。
实时系统:如垃圾邮件处理系统
5. redis优势
缓存管理:可以在必要时将无效的旧数据从内存中删除,为新数据腾出新的空间
提供更大的灵活性:redis支持多种类型,并且采用key-value 的形式存储,key和value的大小限制都是512Mb,与编码无关,所以数据安全。但是memcached限制key最大为250字节,value为1MB,况且只支持String类型。
redis提供主从复制:实现高可用的cache系统,支持集群中多个服务器之间的数据同步。
数据持久化:redis可以通过两种方式将数据进行持久化,一定程度上规避缓存中的数据不稳定的问题,也可以在重启服务器时最快的恢复缓存中所需的数据,提高了效率的同事减轻了主数据库系统的开销。
与传统的Memcached相比,优势还是很大的,++但是Memcached也有不可替代的适用场景++:
存储一些粒度比较小的静态数据,比如一些html片段,Memcached便是我们更好的选择。相对于redis而言,Memcached的元数据metadata更小些,所以相对来讲对于数据存储管理的性能更高,额外开销更小。
Memcached的特点:Memcached唯一支持的数据类型是String,所以更适合存储只读数据,因为字符串并不会因为额外的处理造成额外的开销。毕竟Memcached每次更新一个对象时,都需要重复执行下面的操作:获取整个字符串->反序列化为对象->修改其中的值->再次序列化该对象->在缓存中将整个字符串替换为新字符串。这样一来,更新存储数据就会有更高的消耗,可能就不是我们的最佳选择了。
6. redis快的原因总结
完全基于内存
Redis是纯内存数据库,相对于读写磁盘,读写内存的速度就不是几倍几十倍了,一般,hash查找可以达到每秒百万次的数量级。
多路复用IO
“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗)。可以直接理解为:单线程的原子操作,避免上下文切换的时间和性能消耗;加上对内存中数据的处理速度,很自然的提高redis的吞吐量。
6.1 Redis为什么是单线程的?
因为CPU不是Redis的瓶颈。Redis的瓶颈最有可能是机器内存或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。
6.2 为什么 Redis 中要使用 I/O 多路复用这种技术呢?
首先,Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导致整个进程无法对其它客户提供服务,而 I/O 多路复用就是为了解决这个问题而出现的。
假设你是一个老师,让30个学生解答一道题目,然后检查学生做的是否正确,你有下面几个选择:
1. 第一种选择:按顺序逐个检查,先检查A,然后是B,之后是C、D。。。这中间如果有一个学生卡主,全班都会被耽误。这种模式就好比,你用循环挨个处理socket,根本不具有并发能力。
第二种选择:你创建30个分身,每个分身检查一个学生的答案是否正确。 这种类似于为每一个用户创建一个进程或者线程处理连接。
第三种选择,你站在讲台上等,谁解答完谁举手。这时C、D举手,表示他们解答问题完毕,你下去依次检查C、D的答案,然后继续回到讲台上等。此时E、A又举手,然后去处理E和A。。。
第三种就是IO复用模型,Linux下的select、poll和epoll就是干这个的。++将用户socket对应的fd注册进epoll,然后epoll帮你监听哪些socket上有消息到达++,这样就避免了大量的无用操作。此时的socket应该采用非阻塞模式。这样,整个过程只在调用select、poll、epoll这些调用的时候才会阻塞,收发客户消息是不会阻塞的,整个进程或者线程就被充分利用起来,这就是事件驱动,所谓的++reactor模式++。
6.3 redis的线程模型?
Redis 服务采用 Reactor 的方式来实现文件事件处理器(++每一个网络连接其实都对应一个文件描述符++)
文件事件处理器使用 I/O 多路复用模块同时监听多个 FD,当 accept、read、write 和 close 文件事件产生时,文件事件处理器就会回调 FD 绑定的事件处理器。
虽然整个文件事件处理器是在单线程上运行的,但是通过 I/O 多路复用模块的引入,实现了同时对多个 FD 读写的监控,提高了网络通信模型的性能,同时也可以保证整个 Redis 服务实现的简单。
上面简单理解就是:多个网络连接并发读写redis的时候,先将对应的fd注册到epoll上,I/O多路复用模块会监听这些网络请求的情况,一旦有一个网络连接产生了accept、read、write 和 close 文件事件,I/O多路复用模块就会向文件事件分派器传送那些产生了事件的网络连接。
当然了,上面的文件事件可能会并发产生,这时的策略是,将所有产生事件的套接字(对应上面的网络连接)都入队到一个队列里面, 然后通过这个队列, 以有序(sequentially)、同步(synchronously)、每次一个套接字的方式向文件事件分派器传送套接字: 当上一个套接字产生的事件被处理完毕之后(该套接字为事件所关联的事件处理器执行完毕), I/O 多路复用程序才会继续向文件事件分派器传送下一个套接字。
文件事件分派器接收 I/O 多路复用程序传来的套接字, 并根据套接字产生的事件的类型, 调用相应的事件处理器。
服务器会为执行不同任务的套接字关联不同的事件处理器, 这些处理器是一个个函数, 它们定义了某个事件发生时, 服务器应该执行的动作。
++整个模块使 Redis 能以单进程运行的同时服务成千上万个文件描述符,避免了由于多进程应用的引入导致代码实现复杂度的提升,减少了出错的可能性。++
最后,为什么redis比较快大概思路通俗的说就是:Redis是纯内存数据库,读取快,瓶颈在于IO上,如果使用阻塞式IO,因为是单线程的缘故,就会停止等待。所以采用IO多路复用监听文件描述符的状态,将对redis的开关读写换成事件,加入队列进行相应的事件处理,采用非阻塞IO,吞吐量比较大。
7. reids在linux下的安装
Redis对于Linux是官方支持的,安装起来也非常地简单,直接编译源码然后进行安装即可。
这里以centos为例,大概说一下步骤:
下载redis编译工具:yum install gcc和yum install g++
解压redis.tar.gz文件,进去之后进行编译:make
然后安装:make install PREFIX=/usr/local/redis
安装成功之后进入/usr/local/redis/bin下启动redis
./redis-server
8. redis在windows环境下的安装
解压就能使用。下载地址为:https://github.com/MicrosoftArchive/redis/releases