1.介绍
REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
2.数据类型
- String:字符串
- Hash:哈希
- List:列表
- Set:集合
- ZSet(Sorted Sets): 有序集合
3. 下载安装
最新版下载地址:http://redis.io/download
以下是在Ubuntu环境下进行安装
$ sudo apt-get update
$ sudo apt-get install redis-server
// 启动redis
$ redis-server
// 连接redis
$ redis-cli
127.0.0.1:6039> ping
PONG
注: 配置文件位于 /etc/redis.conf
4. 基本操作
- String: 字符串
Redis 最基本的数据类型,string 类型是二进制安全的,string可以是任何数据的序列化,最大能存储 512MB。
语法:
SET key value [EX seconds] [PX milliseconds] [NX|xx]
EX: 过期时间 秒
PX: 过期时间 毫秒
NX: 不过期
GET key : 获取
DEL key : 删除
实例:
127.0.0.1:6039> SET test "hello world"
OK
127.0.0.1:6379> GET test
"hello world"
127.0.0.1:6379> DEL test
(integer) 0
127.0.0.1:6379> GET test
(nil)
- Hash: 散列表
Redis hash 是一组键值(key=>value)对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
语法:
HSET key field value
HGET key field
HMSET key field value [field value ...]
HMGET key field [field ...]
HDEL key filed [field ...]
HLEN key:获取hash表的数量
HKEYS key: 获取hash表中所有的字段
HVALS key: 获取hash表中所有的值
HEXISTS key field:判断字段是否存在
实例:
127.0.0.1:6379> HSET myobj name "redis"
(integer) 0
127.0.0.1:6379> HGET myobj name
"redis"
127.0.0.1:6379> HMSET myobj name "redis1" message "hello world redis1" count 1
OK
1) "redis1"
2) "hello world redis1"
3) "1"
127.0.0.1:6379> HDEL myobj name count
(integer) 2
127.0.0.1:6379> HMGET myobj name message count
1) (nil)
2) "hello world redis1"
3) (nil)
127.0.0.1:6379> HLEN myobj
(integer) 2
127.0.0.1:6379> HKEYS myobj
1) "message"
2) "type"
127.0.0.1:6379> HVALS myobj
1) "hello world redis1"
2) "test"
127.0.0.1:6379> HGETALL myobj
1) "message"
2) "hello world redis1"
3) "type"
4) "test"
127.0.0.1:6379> HEXISTS myobj name
(integer) 0
127.0.0.1:6379> HEXISTS myobj message
(integer) 1
- List: 列表
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
语法:
LPUSH key value [value ...]: 添加到头部
LPOP key : 从头部取数据
RPOP key : 从尾部取数据
RPUSH key value [value ...]: 添加到尾部
LRANGE key start stop: 读取
LLEN key: 读取list长度
实例:
127.0.0.1:6379> LPUSH list_left 1 2 3 5 7
(integer) 5
127.0.0.1:6379> LRANGE list_left 0 5
1) "7"
2) "5"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> LPOP list_left
"7"
127.0.0.1:6379> LRANGE list_left 0 4
1) "5"
2) "3"
3) "2"
4) "1"
127.0.0.1:6379> RPOP list_left
"1"
127.0.0.1:6379> LRANGE list_left 0 3
1) "5"
2) "3"
3) "2"
127.0.0.1:6379> LLEN list_left
(integer) 3
127.0.0.1:6379> RPUSH list_right 1 2 3 5 7
(integer) 5
127.0.0.1:6379> LRANGE list_right 0 5
1) "1"
2) "2"
3) "3"
4) "5"
5) "7"
- Set: 集合
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
语法:
SADD key value [value ...]: 添加
SMEMBERS key : 读取所有字段
SCARD key: 获取集合长度
SINTER key1 [key ...] : 获取集合的交集
SDIFF key1 [key ...]: 获取key1 与其他集合的差集
SREM key member [member ...] : 移除集合中的元素
实例:
127.0.0.1:6379> SADD set_test redis rabbitmq redis
(integer) 2
127.0.0.1:6379> SMEMBERS set_test
1) "redis"
2) "rabbitmq"
127.0.0.1:6379> SADD set_test ABB
(integer) 1
127.0.0.1:6379> SMEMBERS set_test
1) "redis"
2) "ABB"
3) "rabbitmq"
127.0.0.1:6379> SCARD set_test
(integer) 3
127.0.0.1:6379> SADD set_test1 redis rocketmq ABB
(integer) 3
127.0.0.1:6379> SINTER set_test set_test1
1) "redis"
2) "ABB"
127.0.0.1:6379> SDIFF set_test set_test1
1) "rabbitmq"
127.0.0.1:6379> SDIFF set_test1 set_test
1) "rocketmq"
127.0.0.1:6379> SREM set_test redis
(integer) 1
127.0.0.1:6379> SMEMBERS set_test
1) "ABB"
2) "rabbitmq"
- ZSet: 有序集合
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
当items内容大于64的时候同时使用了hash和skiplist两种设计实现,这是为排序和查找性能做的优化。
这里的score可以认为是权重,可用来处理优先级的问题。
语法:
ZADD key score1 member1 [score2 member2 ...]
ZCARD key
ZCOUNT key min max
ZRANGE key start stop [WITHSCORES]
ZREM key member [member ...]
ZSCORE key member
实例:
127.0.0.1:6379> ZADD zset_test 1 redis 2 mysql 2 mongodb 3 rabbitmq
(integer) 4
127.0.0.1:6379> ZRANGE zset_test 0 4 WITHSCORES
1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "2"
7) "rabbitmq"
8) "3"
127.0.0.1:6379> ZSCORE zset_test mysql
"2"
5. 发布订阅
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
1. 暂定channel的名称为 redisChat
2. 打开一个客户端,订阅redisChat
127.0.0.1:6379> SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
# 订阅客户端收到的消息
1) "message"
2) "redisChat"
3) "Hello Redis"
1) "message"
2) "redisChat"
3) "Hello everyone, I am new"
3. 打开另外一个客户端,往redisChat这个channel上发布消息
127.0.0.1:6379> PUBLISH redisChat "Hello Redis"
(integer) 1
4. 再打开一个客户端,继续往redisChat这个channel上发布消息
127.0.0.1:6379> PUBLISH redisChat "Hello everyone, I am new"
(integer) 1
6. Redis事务
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的,目前仅是任务队列,队列中的某条指令失败,不会回滚 Transactions doc
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set m1 I
QUEUED
127.0.0.1:6379> SADD mset I am a new person
QUEUED
127.0.0.1:6379> get m1
QUEUED
127.0.0.1:6379> SMEMBERS mset
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (integer) 5
3) "I"
4) 1) "new"
2) "a"
3) "I"
4) "am"
5) "person"
7. 数据备份与恢复
语法:
CONFIG GET dir : 获取默认备份位置
SAVE: 当前数据库的备份
BGSAVE: 当前数据库的后台备份
127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/usr/local/var/db/redis"
127.0.0.1:6379> keys *
1) "zset_test"
2) "m1"
3) "myobj"
4) "set_test"
5) "list_left"
6) "mset"
7) "list_test"
8) "list_right"
9) "set_test1"
127.0.0.1:6379> SAVE
OK
将会在redis安装目录下生成 dump.rdb,备份时只需要将该文件移动到 /usr/local/var/db/redis,重启服务即可。
注: 还有一种策略叫做 AOF,即将发送到Redis服务端的每一条命令都记录下来,并且保存到硬盘中的AOF文件中,类似打日志文件,来一条命令就记录一条。
RDB:
优点:适合备份,文件小,速度快(大量数据时)
缺点:每隔一段时间保存一次,所以当系统宕机时,可能会损失几分钟的数据
AOF:
优点:数据不会丢失
缺点:文件大,速度慢(大量数据时)
8. 安全
redis默认是免密,非常不安全,我们可以设置密码进行保护
语法:
CONFIG set requirepass "password"
实例:
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) ""
127.0.0.1:6379> CONFIG set requirepass password
OK
127.0.0.1:6379> CONFIG get requirepass
(error) NOAUTH Authentication required.
127.0.0.1:6379> AUTH password
OK
// 或者重新登录或者
➜ ~ redis-cli -a password
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) "password"
9. 性能测试
语法:
redis-benchmark [option] [option value]
实例:
➜ ~ redis-benchmark -n 10000 -q
PING_INLINE: 84033.61 requests per second
PING_BULK: 85470.09 requests per second
SET: 85470.09 requests per second
GET: 85470.09 requests per second
INCR: 86956.52 requests per second
LPUSH: 86956.52 requests per second
RPUSH: 86956.52 requests per second
LPOP: 85470.09 requests per second
RPOP: 86206.90 requests per second
SADD: 86956.52 requests per second
SPOP: 87719.30 requests per second
LPUSH (needed to benchmark LRANGE): 86956.52 requests per second
LRANGE_100 (first 100 elements): 26737.97 requests per second
LRANGE_300 (first 300 elements): 11235.96 requests per second
LRANGE_500 (first 450 elements): 7824.73 requests per second
LRANGE_600 (first 600 elements): 5959.48 requests per second
MSET (10 keys): 81300.81 requests per second
10. 管道技术
Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:
- 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
- 服务端处理命令,并将结果返回给客户端。
Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应,极大的提高了Redis的性能。
➜ ~ (echo -en "PING\r\n SET runoobkey redis\r\nGET runoobkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | redis-cli -a password
PONG
OK
"redis"
(integer) 4
(integer) 5
(integer) 6
注:参考runoob.com