Redis(1)

Introduction

Key-value数据库

Redis是一个key-value数据库,区别与传统的关系型数据库。
比如一篇文章在redis存储如下:

1
2
3
4
# var["key"] = "value"
doc["title"] = "hello, , world"
doc["author"] = "chen"
doc["tags"] = ["blog", "hello"]
  • 这样存储也与实际doc结构相一致,更加容易操作,而在mysql存储则需要建立一个表存储doc的基本信息,为了表示tags,需要建立第二表存储tags,还需要第三个表连接doc和tags。
  • 并且key-value数据库可以随时给doc增加属性,且每篇doc属性可以不同,而mysql中需要预先定义好doc的属性,每篇doc都必须有相同的属性,在属性非常稀疏或者经常需要添加之前无法预定义的属性时,mysql等关系型数据库将难以处理。
  • 另外当存在海量的docs时,在关系型数据库中将表示为一张巨大的表,会给索引和检索都带来很大的负担,效率会降低,同时单台机器无法存下过大的表,而垂直增加单台机器的性能是一种很不经济的方式,通过水平扩展增加机器数量是一种更好的解决方案,然而mysql传统关系型数据库对于partition的支持是很差的,难以容易scale。而key-value数据库对于水平扩展具有先天的优势,只需将增加机器,然后将单个单个的文档重新划分到这些机器上,非常容易扩展。

这些都是key-value数据库的优势,在处理互联网上海量但是非结构化的数据具有很大的优势。key-value数据库对于不同应用和需求也有很多种,如MongoDB,Cassandra,Dynamo等。

内存存储与持久化

Redis数据库种所有数据都存储在内存种,所以速度非常快,另外redis同时也提供了对持久化的支持,可以将内存的数据异步写到磁盘中。

另外redis虽然是作为数据库开发的,但是由于其基于内存且提供了很多强大的功能,可以很容易将其用于缓存,队列系统等。

安装和启动

Installation

  • 官网下载当前版本。
  • 解压并编译
1
2
3
$ tar xzf redis-3.0.7.tar.gz
$ cd redis-3.0.7
$ make

启动redis server。

$ src/redis-server
也可以将redis-server命令直接加入到系统路径里,或者将redis-server复制到/usr/bin/下,这样后面启动redis server就不需要切换到redis目录中。

1
2
3
4
5
6
# /usr/local/redis-3.0.7 redis安装目录
vi ~/.bash_profile #或者其他系统环境文件
# 添加:
PATH="$PATH":/usr/local/redis-3.0.7/src

source ~/.bash_profile

redis默认使用6379端口监听,可以通过--port参数设置。

redis-server --port 6000

另外一种方式是使用初始化脚本启动redis。redis目录下utils目录下有一个redis_init_script的默认初始化脚本,我们可以对其修改以满足我们的需要。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.

REDISPORT=6379
EXEC=/usr/local/bin/redis-server
CLIEXEC=/usr/local/bin/redis-cli

PIDFILE=/var/run/redis_${REDISPORT}.pid # pid文件位置
CONF="/etc/redis/${REDISPORT}.conf" # 即是这个脚本文件文件名,可以复制到不同位置以进行启动,但是/etc/redis/目录下必须要要有一份
# /var/redis/端口号 持久化文件存放位置

case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac

之后可以启动如下:

redis_6000 start # redis_6000 即是上面脚本文件的文件名

另外如果需要更多的配置,如端口号,持久化文件存放地址等,最好的方式是启动时指定配置文件。

1
redis-server /path/to/redis/conf

通过启动参数传递同名的配置选项会覆盖配置文件中相应的参数。

server交互

之后可以通过命令行终端或者编程语言接口与server交互。

1
2
3
4
5
6
7
8
9
$ redis-cli
# redis-cli -h 127.0.0.1 -p 6000 如果需要指定服务所在地址和端口

# PING 测试连接是否正常

redis> set foo bar
OK
redis> get foo
"bar"

停止redis

redis-cli SHUTDOWN

基本使用(命令行终端)

redis实例与数据库

一个redis实例以默认的配置启动后,提供了多个字典(数据库),客户端可以指定将数据存在哪个数据库中。每个数据库使用一个数字来表示(不支持数据库命名,不同数据库没有不同的访问密码,另外数据库并不是完全隔离的,所以redis里的数据库更像是一种命名空间,所以一个redis实例不适合存储不同应用程序的数据),默认有16个数据库,可以通过配置参数databases来修改。默认会直接进入0号数据库,可以通过SELECT更换数据库。

1
SELECT 1

键操作命令

  • 获得符合规则的键名列表
    KEYS pattern # 不区分大小写,可以使用正则表达式

一些简单的通配符规则:

sign meaning
? 任意一个字符
任意个字符
[] 匹配括号内的任意一个字符,可以使用”-“表示区间,如[a-zA-z]
\x 转义通配符
  • 判断键是否存在
    EXISTS key
    如果存在则返回整数类型1,否则返回0

  • 删除键
    DEL key1 key2 key3 ... # 可以一次删除多个键

del命令参数不支持通配符,但是可以结合linux管道和xargs命令实现删除所有符合规则的键,如:
redis-cli KEYS "*" | xargs redis-cli DEL
或者以符合规则的键作为参数:
redis-cli DEL `redis-cli’ KEYS “*” ` # 注意这个一个linux嵌入命令,不是单引号。

  • 获得键值的数据类型
    TYPE key
    返回值可能为string, hash, list, set, zset(有序集合类型)

基本操作命令

  • 赋值与取值
1
2
SET key value
GET key
  • 递增递减数字
1
2
3
4
5
6
7
8
9
INCR key # 必须为整数类型

INCRBY key increment
INCRBY bar 2

DECR key
DECYBY key decrement

INCRBYFLOAT key increment # 双精度浮点数增加
  • 追加
1
2
SET key hello
APPEND key " world" # 如果不存在就相当于SET
  • 字符串长度

STRLEN key

  • 同时获取/设置多个键值
1
2
MGET key1 key2 ... 
MSET key1 value1 key2 value2 ...
  • 位操作
1
2
3
4
GETBIT key offset # 可以对字符串操作
SETBIT key offset value
BITCOUNT key [start] [end] # 1的个数
BITOP operation destkey key1 key2 ...

散列类型

散列类型适合存储对象,使用对象类别和ID构成键名,使用字段表示对象的属性,而字段值则存储属性值(除了散列类型,redis的其他数据类型同样不支持数据类型嵌套,如集合类型的每个元素都只能是字符串,不能是另一个集合或散列)。

  • 赋值与取值
1
2
3
4
5
6
7
8
9
HSET key field value
HGET key field

HMSET key field1 value1 field2 value2
HMGET key field1 field2
HGETALL key

HSET car price 500
HSET car name BMW

redis中每个键都属于一个明确的数据类型,如通过HSET命令建立的键是散列类型,通过SET命令建立的键是字符串类型等。

  • 判断字段是否存在
1
2
3
HEXISTS key field

HEXISTS car name
  • 当字段不存在时赋值
1
HSETNX key field value
  • 增减数字
1
2
3
HINCRBY key field increment

HINCRBY car price 100 # 如果键不存在,则会建立
  • 删除字段
1
HDEL key field1 field2 ...
  • 获取字段名或字段值(属性值),字段数量
1
2
3
HKEYS key
HVALS key
HLEN key

列表类型

列表类型list可以存储一个有序的字符串列表,常用操作是向列表两段添加元素,或者获得列表的一个片段。redis中列表是使用双向链表实现,头尾添加删除很快,注意索引访问速度会比较慢,特别是访问中间的元素。

  • 向两端加入元素
1
2
3
4
5
6
7
8
LPUSH key value1 value2 ...
RPUSH key value1 value2 ...

LPUSH nums 1
LPUSH nums 2 3
# 3 2 1
RPUSH nums 0 -1
# 3 2 1 0 -1
  • 从列表两端弹出元素
1
2
LPOP key
RPOP key
  • 获取列表中元素的个数

LLEN key # O(1)

  • 获取片段
1
2
3
LRANGE key start stop # first element 0

LRANGE nums -2 -1 # -1, 最右边的第一个元素...
  • 删除指定值
1
2
LREM key count value # 删除列表中前count个值为value的元素
# count<0从右边开始删除,count=0删除所有

集合类型

集合使用hashset实现。

  • 增加/删除元素
1
2
SADD key member1 member2 ... # 返回新增成功的个数
SREM key member1 member2 ... # 返回删除成功的个数
  • 获得所有元素
    SMEMBERS key

  • 判断是否存在
    SISMEMBER key member

  • 集合间运算

1
2
3
4
5
6
7
SDIFF key1 key2 ...
SINTER key1 key2 ...
SUNION key1 key2 ...

SDIFFSTORE destination key1 key2...
SINTERSTORE destination key1 key2...
SUNIONSTORE destination key1 key2...
  • 元素个数
    SCARD key

  • 随机获得集合元素
    SRANDMEMBER key [count]

  • 随机弹出一个元素
    SPOP key

有序集合类型

sorted set,每个元素具有分数(权值)的set,如果将当分数设为index大小,则可以实现list的功能。

  • 增加元素
    ZADD key score1 member1 score2 ...

  • 获得元素的分数
    ZSCORE key member

  • 获得排名在某个范围内的元素列表
    ZRANGE key start stop [WITHSCORES] # 分数从小到大
    Zrevrange key start stop [WITHSCORES] # 分数从大到小

  • 获得指定分数范围

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

  • 增加某个元素的分数

ZINCRBY key increment member