1
.Redis
简介,2
.快速安装Redis
与Python
,3
.Redis
数据结构简介。
Redis
是一个速度非常快的非关系型数据库(non-relational database
),它可以存储键(key
)和五种不同类型的值(value
)之间的映射(mapping
),可基于内存存储亦可持久化到硬盘的日志型,Key-Value
数据库。
如果你使用过关系型数据库,例如:Mysql
,那么你肯定写过关联两张表数据的查询语句。而 Redis
属于 NoSQL
,它不使用表,也不会预定义数据模式或强制用户对 Redis
的各种数据进行关联。
NoSQL
(Not Only SQL
)
意指“不仅仅是
SQL
”,其泛指非关系型数据库,主要分为四类:键值(Key-Value
)存储数据库,列存储数据库,文档型数据库,图形(Graph
)数据库。
Redis
也经常与高性能键值缓存服务器 memcached
做比较:两者均可用于存储键值映射,性能相差也甚少,但 Redis
能存储除普通字符串值之外的四种数据结构,而 memcached
只能存储普通的字符串值。这些不同使得 Redis
能够解决更为广泛的问题,而且既能作为主数据库使用,也可以作为辅助数据库使用。
我们通过一张表来对比常用的数据库与缓存服务器:
名称 | 类型 | 数据存储选项 | 查询类型 | 附加功能 |
---|---|---|---|---|
Redis |
基于内存的非关系型数据库 | 字符串、列表、集合、哈希、有序集合 | 针对数据类型有专属命令,另有批量操作和不完全的事务支持 | 发布与订阅、复制、持久化、脚本扩展 |
memcached |
基于内存的键值缓存 | 键值映射 | 创建、读取、更新、删除等 | 多线程支持 |
MySQL |
关系型数据库 | 数据表、视图等 | 查询、插入、更新、删除、内置函数、自定义存储过程等 | 支持 ACID 性质、复制等 |
MongoDB |
基于硬盘的非关系型文档存储数据库 | 无 schema 的 BSON 文档 |
创建、读取、更新、删除、条件查询等 | 复制、分片、空间索引等 |
由于 Redis
是内存型数据库,在使用之前就要考虑当服务器被关闭时,服务器存储的数据是否能保留。Redis 拥有两种不同形式的持久化方法,都可以用紧凑的格式将数据写入硬盘:
RDB
持久化
AOF
持久化
除此之外,为了扩展 Redis
的读性能,并为 Redis
提供故障转移支持,Redis
实现了主从复制特性:
为了避免安装到旧版 Redis
的问题,我们直接使用源码编译安装 Redis
,首先你需要获取并安装 make
等一系列构建工具:
$ sudo apt-get update
$ sudo apt-get install make gcc python-dev
构建工具安装完毕后,你需要执行以下操作:
https://redis.io/download
下载最新的稳定版本 Redis
源码Redis
Python
语言的 Redis
客户端库其中,安装 Redis
的过程如下:
~:$ wget -q http://download.redis.io/releases/redis-5.0.0.tar.gz
~:$ tar -xzf redis-5.0.0.tar.gz
~:$ cd redis-5.0.0
# 注意观察编译消息,最后不应该产生任何错误(`Error`)
~/redis-5.0.0:$ make
# 注意观察安装消息,最后不应该产生任何错误(`Error`)
~/redis-5.0.0:$ sudo make install
# 启动 Redis 服务器,注意通过日志确认 Redis 顺利启动
~/redis-5.0.0:$ redis-server redis.conf
除了上述的启动 Redis 服务器方式,你还可以通过 Redis 默认的配置在后台启动它(常用启动方式):
$ redis-server &
因为近几年发布的 Ubuntu
和 Debian
都预装了 Python 2.6
或 Python 2.7
,所以你不再需要花时间去安装 Python
。你可以通过一个名为 setuptools
的辅助包更方便的下载和安装 Redis
客户端:
~:$ sudo python -m easy_install redis hiredis
这里的 redis
包为 Python
提供了连接 Redis
的接口,hiredis
包则是可选的,它是一个使用 C
语言编写的高性能 Redis
客户端。
Redis
的五种数据结构分别是:
STRING
)LIST
)SET
)HASH
)ZSET
)ZSET
可以说是 Redis
特有的数据结构,我们会在之后的实训中详细介绍它,在本实训中,我们只简要介绍他们的功能和小部分命令。他们的存储的值如下:
结构类型 | 存储的值 |
---|---|
STRING |
字符串、整数或浮点数 |
LIST |
一个链表,上面的每个节点都是一个字符串 |
SET |
包含若干个字符串的无序集合,且集合中的元素都是唯一的 |
HASH |
包含键值对的无序散列表 |
ZSET |
成员中的字符串与分值的有序映射,其排序由分值决定 |
在安装完 Redis
并启动了 redis-server
后,我们可以使用 redis-cli
控制台与 Redis
进行交互,其启动方式是在终端中输入:
$ redis-cli
其会默认连接本机 6379
端口启动的 Redis
服务器,接下俩你可以使用它来体验 Redis
各种数据结构和其命令的使用。
STRING
拥有一些和其他键值存储相似的命令,比如 GET
(获取值),SET
(设置值),DEL
(删除值)等,例如:
$ redis-cli
redis-cli 127.0.0.1:6379> set hello redis
OK
redis-cli 127.0.0.1:6379> get hello
"redis"
redis-cli 127.0.0.1:6379> del hello
(integer) 1
redis-cli 127.0.0.1:6379> get hello
(nil)
其中:
SET
命令的第一个参数是键(Key
),第二个参数是值(Value
)nil
就像前面所说的,Redis
中的列表是一个“链表”,这和大多数编程语言相似。所以他们的操作也十分相似:
LPUSH
命令可用于将元素推入列表的左侧RPUSH
命令可将元素推入列表的右侧LPOP
和 RPOP
就分别从列表的左侧和右侧弹出元素LINDEX
可以获取指定位置上的元素LRANGE
可以获取指定范围的全部元素我们通过 redis-cli
来亲自体验:
redis 127.0.0.1:6379> rpush testlist item
(integer) 1
redis 127.0.0.1:6379> rpush testlist item2
(integer) 2
redis 127.0.0.1:6379> rpush testlist item
(integer) 3
redis 127.0.0.1:6379> lrange testlist 0 -1
1) "item"
2) "item2"
3) "item"
redis 127.0.0.1:6379> lindex testlist 1
"item2"
redis 127.0.0.1:6379> lpop testlist
"item"
redis 127.0.0.1:6379> lrange testlist 0 -1
1) "item2"
2) "item"
我们可以看出,在列表中,元素可以重复出现。在后续的实训中,我们还会介绍更多列表命令,现在我们先来了解以下 Redis
中的集合。
集合和列表的区别就在于:列表可以存储多个相同的字符串,而集合通过散列表来保证存储的字符串都是各不相同的(这些散列表只有键,而没有对应的值)。
由于集合是无序的,所以我们只能通过统一的 SADD
命令将元素添加到集合中,SREM
命令将元素从集合中移除。你还可以通过:
SMEMBERS
命令获取到集合中的所有元素SISMEMBER
命令来判断一个元素是否已存在在集合中redis 127.0.0.1:6379> sadd testset item
(integer) 1
redis 127.0.0.1:6379> sadd testset item2
(integer) 1
redis 127.0.0.1:6379> sadd testset item
(integer) 0
redis 127.0.0.1:6379> smembers testset
1) "item"
2) "item2"
redis 127.0.0.1:6379> sismember testset item3
(integer) 0
redis 127.0.0.1:6379> sismember testset item
(integer) 1
redis 127.0.0.1:6379> srem testset item2
(integer) 1
redis 127.0.0.1:6379> srem testset item2
(integer) 0
redis 127.0.0.1:6379> smembers testset
1) "item"
上面示例的集合中包含的元素少,所以执行 SMEMBERS
命令没有问题,一旦集合中包含的元素非常多时,SMEMBERS
命令的执行速度会很慢,所以要谨慎的使用这个命令。
哈希可以存储多个键值对之间的映射。和字符串一样,哈希存储的值既可以是字符串又可以是数字值,并且可以对数字值进行自增/自减操作。
哈希就像是一个缩小版的 Redis
,有一系列命令对哈希进行插入、获取、删除:
redis 127.0.0.1:6379> hset testhash key1 value1
(integer) 1
redis 127.0.0.1:6379> hset testhash key2 value2
(integer) 1
redis 127.0.0.1:6379> hset testhash key1 newvalue
(integer) 0
redis 127.0.0.1:6379> hgetall testhash
1) "key1"
2) "newvalue"
3) "key2"
4) "value2"
redis 127.0.0.1:6379> hdel testhash key2
(integer) 1
redis 127.0.0.1:6379> hget testhash key1
"newvalue"
redis 127.0.0.1:6379> hgetall testhash
1) "key1"
2) "newvalue"
其中:
hset
用于插入元素
hgetall
会获取到该哈希的所有域-值对hget
用于获取哈希中的某一个域hdel
用户删除哈希中的某一个域有序集合和哈希一样,也是存储键值对。
只是有序集合的键被称为成员(member
),每个成员都是唯一的,有序集合的值则被称为分值(score
),这个分值必须为浮点数。所以有序集合既可以通过成员访问元素,也可以通过分值来排序元素。
我们可以通过:
ZADD
命令将带有指定分值的成员添加到有序集合中ZRANGE
命令根据分值有序排列后的集合获取到指定范围的元素ZRANGEBYSCORE
命令获取指定分值范围内的元素ZREM
命令从有序集合中删除指定成员我们也可以在 redis-cli
中验证上述命令的功能:
redis 127.0.0.1:6379> zadd testzset 100 member1
(integer) 1
redis 127.0.0.1:6379> zadd testzset 200 member0
(integer) 1
redis 127.0.0.1:6379> zrange testzset 0 -1 withscores
1) "member1"
2) "100"
3) "member0"
4) "200"
redis 127.0.0.1:6379> zrangebyscore testzset 0 150 withscores
1) "member1"
2) "100"
redis 127.0.0.1:6379> zrem testzset member1
(integer) 1
redis 127.0.0.1:6379> zrange testzset 0 -1 withscores
1) "member0"
2) "200"
根据提示,打开命令行,启动 Redis
客户端并创建一些值:
redis-cli
hello
redis
educoder-list
hello
educoder
bye
educoder-set
c
python
redis
c
educoder-hash
python
,值为:language
ruby
,值为:language
redis
,值为:database
ruby
educoder-zset
jack
,分值为 200
rose
,分值为 400
lee
,分值为 100
redis-cli
set hello redis
LPUSH educoder-list hello
RPUSH educoder-list educoder
RPUSH educoder-list bye
RPOP educoder-list
sadd educoder-set c
sadd educoder-set python
sadd educoder-set redis
srem educoder-set c
hset educoder-hash python language
hset educoder-hash ruby language
hset educoder-hash redis database
hdel educoder-hash ruby
zadd educoder-zset 200 jack
zadd educoder-zset 400 rose
zadd educoder-zset 100 lee