Redis介绍
数据分类
结构化数据: 通过统一的格式进行存储管理(RDBMS)
非结构化数据:无法通过统一格式进行存储管理(nosql)
半结构化:介于两者之间(xml)
NoSQL介绍
- NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题
- 而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
- 不是替代关系型数据库,补充关系型数据库性能瓶颈。
为什么需要NoSQL
- High performance - 高并发读写
- Huge Storange - 海量数据的高效存储和访问
- High Scalability && High Availability - 高扩展性和高可用性
NoSQL 的特点
- 易扩展
- 灵活的数据模型
- 大量数据,高性能
- 高可用
NoSQL数据库的四大分类
键值(Key-Value)存储数据库
- 相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
- 典型应用: 内容缓存,主要用于处理大量数据的高访问负载。
- 数据模型: 一系列键值对
- 优势: 快速查询
- 劣势: 存储的数据缺少结构化
列存储数据库
- 相关产品:Cassandra, HBase, Riak
- 典型应用:分布式的文件系统
- 数据模型:以列簇式存储,将同一列数据存在一起
- 优势:查找速度快,可扩展性强,更容易进行分布式扩展
- 劣势:功能相对局限
文档型数据库
- 相关产品:CouchDB、MongoDB
- 典型应用:Web应用(与Key-Value类似,Value是结构化的)
- 数据模型: 一系列键值对
- 优势:数据结构要求不严格
- 劣势: 查询性能不高,而且缺乏统一的查询语法
图形(Graph)数据库(图)
- 相关数据库:Neo4J、InfoGrid、Infinite Graph
- 典型应用:社交网络
- 数据模型:图结构
- 优势:利用图结构相关算法。
- 劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。
NoSQL数据库适用情况
- 数据模型比较简单;
- 需要灵活性更强的IT系统
- 对数据库性能要求较高
- 不需要高度的数据一致性
- 对于给定key,比较容易映射复杂值的环境
Redis
Redis作者
- redis的作者,他叫Salvatore Sanfilippo,来自意大利的西西里岛,现在居住在卡塔尼亚。目前供职于Pivotal公司。
- 地址是antirez.com,当然也可以去follow他的github,地址是http://github.com/antirez。
什么是redis
- Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,遵守BSD协议,并提供多种语言的API。
- Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。
- Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
- 从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。(Vmware在资助着redis项目的开发和维护)
- BSD是”Berkeley Software Distribution”的缩写,意思是”伯克利软件发行版”。BSD开源协议是一个给于使用者很大自由的协议。可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。
- BSD代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对商业集成很友好的协议。
- 在线测试:http://try.redis.io/
- 使用文档:http://doc.redisfans.com/
为什么会出现Redis
形如MYSQL,ORACLE这样的关系型数据库是把数据存储在磁盘中,而Redis这样的非关系型数据库会把数据存储在内存中。
首先磁盘的寻址时间为ms,而内存的寻址时间为ns,磁盘比内存在寻址上慢了10W倍;
其次在建表时关系型数据库需要给出schema(数据类型和结构),存储时为行级存储,当数据大量增加时,如果表存在索引,增删改除了维护本身数据还要维护索引,查询速度在并发大的时候会受磁盘的带宽影响速度;而内存的带宽很大,不存在这个问题;
最后就是关系型数据库存在一个数据从磁盘取出放到内存中的IO的成本问题;
所以就诞生了redis这样类型的数据库,除此之外还有memcached,ehcache等等。
memcached 和 redis的区别
memcached也是key-value为数据结构存储的数据库,早在2003年就发布了,那为什么还会出现redis呢。主要是因为memcached是不存在value类型的概念
Redis中的value类型主要存在五种,分别是 string,hashes,lists,sets ,sorted sets。string类型除了字符类型还可以存储数值类型,还延伸出了位图(bitmaps),更重要的是redis对各种类型提供了相应的API。
举个例子,假设你要操作某个key下对应value的部分元素,则可以通过相应的api直接操作value;而不存在则没有办法做到,只能取value值然后再操作,有可能还要放回去,这样就又增加了一次IO。所以redis的效率是会比memcached来的高。
redis应用场景
缓存(数据查询、短连接、新闻内容、商品内容等等)。(最多使用)
分布式集群架构中的session分离。
聊天室的在线好友列表。
任务队列。(秒杀、抢购、12306等等)
应用排行榜。
网站访问统计。
数据过期处理(可以精确到毫秒)
Redis特点
与其他 key - value 缓存产品有以下三个特点
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,集群等高可用功能。
- 在
Redis2.6
以后提供了一个Sentinel
(哨兵机制)。监控所有节点数据库是否正常运行,主数据库出现故障时,可以通过自动投票机制,在从数据库选举出新的主数据库,实现将从数据库转为主数据库的自动切换。 - 在3.0版本正式引入了
Redis-Cluster
集群这个特征。采用无中心架构,每个节点保存完整的数据和整个集群的状态,每个节点都和其他所有节点连接。
- 在
特点
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
- 高速读写,redis使用自己实现的分离器,代码量很短,没有使用lock(MySQL),因此效率非常高。
- 丰富的数据类型 – Redis支持的类型 String, List, Hash, Set 及 Ordered Set 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期、Lua脚本等等特性。
缺点:
- 持久化。Redis直接将数据存储到内存中,要将数据保存到磁盘上,Redis可以使用两种方式实现持久化过程。
- 定时快照(snapshot):每隔一段时间将整个数据库写到磁盘上,每次均是写全部数据,代价非常高。
- 基于语句追加(aof):只追踪变化的数据,但是追加的log可能过大,同时所有的操作均重新执行一遍,回复速度慢。
- 耗内存,占用内存过高。
- 持久化。Redis直接将数据存储到内存中,要将数据保存到磁盘上,Redis可以使用两种方式实现持久化过程。
其他特点
- redis单个key 存入512M大小
- redis支持多种类型的数据结构(string,list,hash.set.zset)
- redis 是单线程 原子性 , 6.0后支持多线程
- redis可以持久化 因为使用了 RDB和AOF机制
- redis支持集群 而且redis 支持库(0-15) 16个库
- redis 还可以做消息队列 比如聊天室 IM
- 企业级开发中:可以用作数据库、缓存热点数据(经常会被查询,但是不经常被修改或者删除的数据)和消息中间件等大部分功能。
Redis为什么那么快
- Redis为什么那么多块呢,其实上文中 为什么会出现redis已给出了部分答案。
基于内存
- Redis完全基于内存,绝大部分请求都是纯粹的内存操作,执行效率高;数据存储在内存中,不受到硬盘IO的限制。
单线程模型
Redis 的网络 IO 和键值对读写是由一个线程来完成的;其次单线程也避免了多线程面临的共享资源并发访问控制问题。
Redis的其他功能,如持久化,异步删除,集群数据同步等,还是由额外的线程执行的。
高效的数据结构
- Redis中的每一种数据类型都使用了高效的数据结构,在一定程度上也提高了效率。具体可参考 Redis为何这么快–数据存储角度 这篇文章。
IO多路复用模型
Redis网络框架基于Linux的IO多路复用机制(select/epoll机制)实现一个Redis线程处理多个IO流的效果,提升了其并发性。
该机制允许内核中同时存在多个监听套接字和已连接套接字。Redis不会一直阻塞在某一个特定的监听或连接套接字上,而是内核会一直监听连接请求或数据请求,一旦请求到达就会基于select/epoll提供的事件回调机制交给Redis线程处理。
即一旦检测到有请求就会触发事件,把这些事件放到一个事件队列,Redis对该事件队列进行不断处理,处理的同时调用相应的处理函数进行回调。
若对Epoll模型不了解可参考此文 此文若说不清Epoll原理,那就过来掐死我!
Redis的单线程
从客户端接收请求,到执行Redis命令。
Redis处理网络请时候的求单线程可以抽象成这样,通向Redis的路只有一条,且这条路是个单车道,只容的下一辆车同时使用,而我们使用的Redis命令即为这些车辆,当我们执行多个命令的时候,只有等第一个命令执行完成了后面的命令才会执行,否则会一直处于等待状态。
注意点
一次只运行一条命令
拒绝长(慢)命令(keys、flushall、flushdb、slow lua script、mutil/exec、operate、big value)
至于为什么单线程还这么快,这里有个原因,
- Redis客户端的到Redis服务器的网络请求采用了多路I/O复用模型(非阻塞I/O),
- 利用
select
、poll
、epoll
可以同时监听多个流的I/O(客户端到服务器的网络请求)事件的能力, - 在空闲的时候,会把当前线程阻塞掉,当有一个或者多个流有
I/O
事件时,就从阻塞态中唤醒,轮训一遍所有的流并且依次处理就绪的流。这样就算出现有的流的I/O
因为网络原因很慢,也不会影响别的流的I/O
(非阻塞),因为是轮训所有的流的I/O
。 - 这里的“多路”指的是多个网络连接,“复用”指的是复用同一个线程。