本文是Redis系列文章的第二篇,将详细介绍Redis的相关知识,包括Redis简介,优势,以及五种数据结构使用实例等,安装和配置请查看《Redis系列(一):安装和配置》。
1. Redis简介
Redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库。它支持5种类型的数据结构,如字符串(strings),散列(hashes),列表(lists),集合(sets),有序集合(sorted sets)。除此之外,通过复制、持久化(persistence)和客户端分片(client-side sharding)等特性,用户可以很方便地将Redis扩展成一个能够包含数百GB数据、每秒处理上百万次请求的系统。
Redis的作者叫Salvatore Sanfilippo,来自意大利的西西里岛,现在居住在卡塔尼亚;目前供职于Pivotal公司。Redis开源项目的源码在GitHub的地址《Redis》,有兴趣的朋友可以看看。
2. Redis优势
- Redis是非常快的,由于Redis只使用单核,而Memcached可以使用多核,所以在比较上,平均每一个核上Redis在存储小数据时比Memcached性能更高。每秒可以执行大约110000设置操作,81000个/每秒的读取操作。
- 支持丰富的数据类型:Redis支持最大多数开发人员已经知道如列表,集合,可排序集合,哈希等数据类型。这使得在应用中很容易解决的各种问题,因为我们知道哪些问题处理使用哪种数据类型更好解决。
- 操作都是原子的:所有 Redis 的操作都是原子,从而确保当两个客户同时访问 Redis 服务器得到的是更新后的值(最新值)。
- 数据的一致性方面:Memcached提供了cas命令来保证.而Redis提供了事务的功能,可以保证一串 命令的原子性,中间不会被任何操作打断
- 数据持久化:Redis提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Append Only File);可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
3. Redis与其他数据库对比
Redis属于非关系数据库,Redis不使用表,它的数据库也不会预定义或者强制去要求用户对Redis存储的不同数据进行关联。
高性能键值缓存服务器Memcached也经常被拿来与Redis进行比较:这两者都可用于存储键值映射,彼此的性能也相差无几,但是Redis能够自动以两种不同的方式将数据写入硬盘,并且Redis除了能存储普通的字符串键之外,还可以存储其他4种数据结构,而Memcached只能存储普通的字符串键。这些不同之处使得Redis可以用于解决更为广泛的问题,并且既可以用作主数据库(primary database)使用,又可以作为其他存储系统的辅助数据库(auxiliary database)使用。
名称 | 类型 | 数据存储选项 | 查询类型 | 附加功能 |
---|---|---|---|---|
Redis | 使用内存存储(in-memory)的非关系数据库 | 字符串、列表、集合、散列表、有序集合 | 每种数据类型都有自己的专属命令,另外还有批量操作(bulk operation)和不完全(partial)的事务支持 | 发布与订阅,主从复制(master/slave replication),持久化,脚本(存储过程,stored procedure) |
memcached | 使用内存存储的键值缓存 | 键值之间的映射 | 创建命令、读取命令、更新命令、删除命令以及其他几个命令 | 为提升性能而设的多线程服务器 |
MySQL | 关系数据库 | 每个数据库可以包含多个表,每个表可以包含多个行;可以处理多个表的视图(view);支持空间(spatial)和第三方扩展 | SELECT 、 INSERT 、 UPDATE 、 DELETE 、函数、存储过程 |
支持ACID性质(需要使用InnoDB),主从复制和主主复制 (master/master replication) |
PostgreSQL | 关系数据库 | 每个数据库可以包含多个表,每个表可以包含多个行;可以处理多个表的视图;支持空间和第三方扩展;支持可定制类型 | SELECT 、 INSERT 、 UPDATE 、 DELETE 、内置函数、自定义的存储过程 |
支持ACID性质,主从复制,由第三方支持的多主复制(multi-master replication) |
MongoDB | 使用硬盘存储(on-disk)的非关系文档存储 | 每个数据库可以包含多个表,每个表可以包含多个无schema(schema-less)的BSON文档 | 创建命令、读取命令、更新命令、删除命令、条件查询命令等 | 支持map-reduce操作,主从复制,分片,空间索引(spatial index) |
4. Redis数据结构
Redis可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为STRING(字符串)、LIST(列表)、SET(集合)、HASH(散列)和ZSET(有序集合)。有一部分Redis命令对于这5种结构都是通用的,如DEL、TYPE、RENAME等;但也有一部分Redis命令只能对特定的一种或者两种结构使用。
结构类型 | 结构存储的值 | 结构的读写能力 |
---|---|---|
String |
可以是字符串、整数或者浮点数 | 对整个字符串或者字符串的其中一部分执行操作;对整数和浮点数执行自增(increment)或者自减(decrement)操作 |
List |
一个链表,链表上的每个节点都包含了一个字符串 | 从链表的两端推入或者弹出元素;根据偏移量对链表进行修剪(trim);读取单个或者多个元素;根据值查找或者移除元素 |
Set |
包含字符串的无序收集器(unordered collection),并且被包含的每个字符串都是独一无二、各不相同的 | 添加、获取、移除单个元素;检查一个元素是否存在于集合中;计算交集、并集、差集;从集合里面随机获取元素 |
Hash |
包含键值对的无序散列表 | 添加、获取、移除单个键值对;获取所有键值对 |
Zset (有序集合) |
字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定 | 添加、获取、删除单个元素;根据分值范围(range)或者成员来获取元素 |
4.1 String—字符串
String是最简单的类型,一个key对应一个value,String类型是二进制安全的;这意味着它们没有任何特殊终端字符来确定长度,所以可以存储任何长度为 512 兆的字符串;可以包含任何数据,比如jpg图片或者序列化的对象;所有常用命令的复杂度都是O(1),普通的Get/Set方法,可以用来做Cache,存Session,为了简化架构甚至可以替换掉Memcached。示例如下:
1 | 127.0.0.1:6379> set name 'MinHow' //设置name的值为MinHow |
4.2 List—列表
Redis 列表是简单的字符串列表,通过插入顺序排序;可以添加一个元素到 Redis 列表的头部或尾部;Redis列表可执行的操作和很多编程语言里面的列表操作非常相似:LPUSH
命令和RPUSH
命令分别用于将元素推入列表的左端(left end)和右端(right end);LPOP
命令和RPOP
命令分别用于从列表的左端和右端弹出元素;LINDEX
命令用于获取列表在给定位置上的一个元素;LRANGE
命令用于获取列表在给定范围上的所有元素。示例如下:
1 | 127.0.0.1:6379> lpush minhow redis //新建一个list叫minhow,并在列表头部插入元素redis |
4.3 Set—集合
Redis的集合是string类型的无序集合;集合成员是唯一的,这就意味着集合中不能出现重复的数据;集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。示例如下:
1 | 127.0.0.1:6379> sadd minhow 'redis' //向集合minhow加入redis元素 |
4.4 Zset—集合
Redis的有序集合和集合一样也是string类型元素的集合,且不允许重复的成员;不同的是每个元素都会关联一个double类型的分数;redis正是通过分数来为集合中的成员进行从小到大的排序;有序集合的成员是唯一的,但分数(score)却可以重复;也是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。示例如下:
1 | 127.0.0.1:6379> zadd minhow 1 redis //向minhow中新增序号为1的redis元素 |
4.5 Hash—哈希
Redis的hash是一个string类型的field和value的映射表;相比String类型将这整个对象持久化成JSON格式,Hash将对象的各个属性存入Map里,可以只读取/更新对象的某些属性,hash特别适合用于存储对象。示例如下:
1 | 127.0.0.1:6379> hmset minhow name minhow sex male age 24 //建立minhow哈希,并赋值 |
还有更多的hash操作方法可以查看
5. 使用合适的数据结构
不管是内存使用或者是性能,有的时候数据结构将产生很大的影响,下面是一些可以参考的最佳实践:
- 使用Hash取代将数据存储为数千(或者数百万)独立的字符串。哈希表是非常有效率的,并且可以减少你的内存使用(因为小的Hashes会被编码成一个非常小的空间);同时,Hash还更有益于细节抽象和代码可读。
- 合适时候,使用List代替Set;如果你不需要使用Set特性,List在使用更少内存的情况下可以提供比Set更快的速度。
- Zset(有序集合)是最昂贵的数据结构,不管是内存消耗还是基本操作的复杂性。如果你只是需要一个查询记录的途径,并不在意排序这样的属性,那么建议使用Hash。
6. 总结
本文主要讲解了Redis的简介,优势,与其他数据库的区别,以及五种数据结构的相关知识等;使用Redis存储数据的时候,选用合适的数据结构是非常重要的,必须结合实际情况选择,下一篇文章会介绍Redis的事务,数据持久化,主从复制等知识。
最后更新: 2017年11月19日 20:17