一、安装并启动Redis
# yum -y install gcc gcc-c++ libstdc++-devel
# wget http://download.redis.io/releases/redis-3.0.6.tar.gz
# tar -zxvf redis-3.0.6.tar.gz
# cd redis-3.0.6
# make MALLOC=libc
# redis-server ##启动redis123456
# redis-cli ##启动客户端
127.0.0.1:6379> ping
PONG123
二、Redis数据类型
Redis支持5种类型的数据类型
①string(字符串)
Redis字符串是字节序列,是一种最基本的Redis值类型。Redis字符串是二进制安全的,这意味着一个Redis字符串能包含任意类型的数据,比如jpg图片或者序列化的对象。一个字符串类型的值最多能存储512M字节的内容。
127.0.0.1:6379> set city boston ##设置字符串类型
OK
127.0.0.1:6379> get city ##读取字符串类型
"boston"1234
②lists(链表)
Redis列表是简单的字符串列表,按照插入顺序排序.你可以添加一个元素导列表的头部(左边)或者尾部(右边)。LPUSH 命令插入一个新的元素导头部, 而 RPUSH插入一个新元素导尾部,LRANGE命令从lists中指定一个范围来提取元素。
127.0.0.1:6379> LPUSH mylist 1 ##新建叫mylist的表,并在表头插入元素"1"
(integer) 1 ##返回当前mylist中的元素个数
127.0.0.1:6379> RPUSH mylist 2 ##在mylist右侧插入元素"2"
(integer) 2
127.0.0.1:6379> LPUSH mylist 0 ##在mylist左侧插入元素"0"
(integer) 3
127.0.0.1:6379> LRANGE mylist 0 1 ##列出mylist中从编号"0"到编号"1"的元素
1) "0"
2) "1"
127.0.0.1:6379> LRANGE mylist 0 -1 ##列出mylist中从编号"0"到倒数第一个元素
1) "0"
2) "1"
3) "2"12345678910111213
③sets(集合)
Redis 集合(Set)是一个无序的字符串集合. 集合中的元素没有先后顺序,你可以以O(1)的时间复杂度 (无论集合中有多少元素时间复杂度都是常量)完成添加,删除,以及测试元素是否存在。 Redis 集合拥有令人满意的不允许包含相同成员的属性。
多次添加相同的元素,最终在集合里只会有一个元素。集合相关操作也很丰富,如添加新元素、删除已有元素、取交集、取并集、取差集等。
127.0.0.1:6379> sadd myset one ##向集合myset中加入新元素"one"
(integer) 1
127.0.0.1:6379> sadd myset two
(integer) 1
127.0.0.1:6379> SMEMBERS myset ##列出集合myset中的所有元素
1) "two"
2) "one"
127.0.0.1:6379> SISMEMBER myset one ##判断元素"1"是否在集合中,返回1表示存在
(integer) 1
127.0.0.1:6379> SISMEMBER myset three ##判断元素3是否在集合中,0表示不存在
(integer) 0
127.0.0.1:6379> sadd yourset 1
(integer) 1
127.0.0.1:6379> sadd yourset 2
(integer) 1
127.0.0.1:6379> SMEMBERS yourset
1) "1"
2) "2"
127.0.0.1:6379> SUNION myset yourset ##对两个集合求并集
1) "2"
2) "1"
3) "one"
4) "two"
127.0.0.1:6379> sadd myset 3
(integer) 1
127.0.0.1:6379> sadd yourset 3
(integer) 1
127.0.0.1:6379> SUNION myset yourset
1) "one"
2) "two"
3) "3"
4) "2"
5) "1"123456789101112131415161718192021222324252627282930313233
④zsets(sorted sets)(有序集合)
Redis的有序集合类似于Redis的集合,字符串不重复的集合。不同之处是有序集合的没有成员都关联了一个评分,这个评分被用来按照从最低分到最高分的方式排序集合中的成员。虽然成员具有唯一性,但分数可以重复。
使用有序集合你可以以非常快的速度(O(log(N)))添加,删除和更新元素。因为元素是有序的, 所以可以很快的根据评分(score)或次序(position)获取一个范围的元素。访问有序集合的中间元素也非常快,因此你能够使用有序集合作为一个没有重复成员的智能列表。
有序集合中的每个元素都关联一个序号(score),这便是排序的依据。很多时候,我们都将redis中的有序集合叫做zsets,这是因为在redis中,有序集合相关的操作指令都是以z开头的,比如zrange、zadd、zrevrange、zrangebyscore等等。
127.0.0.1:6379> zadd myzset 1 google.com ##向myzset中新添元素并赋予序号1
(integer) 1
127.0.0.1:6379> zadd myzset 3 baidu.com
(integer) 1
127.0.0.1:6379> zadd myzset 2 360.com
(integer) 1
127.0.0.1:6379> ZRANGE myzset 0 -1 ##正序列出myzset的元素
1) "google.com"
2) "360.com"
3) "baidu.com"
127.0.0.1:6379> ZREVRANGE myzset 0 -1 ##反序列出myzset的元素
1) "baidu.com"
2) "360.com"
3) "google.com"1234567891011121314
⑤hashes(哈希)
哈希是键值对的集合。 Redis的哈希值是字符串字段和字符串值之间的映射,因此它们被用来表示对象。比如一个用户要存储其全名、姓氏、年龄等等,就很适合使用哈希。
127.0.0.1:6379> HMSET user:1 username zhi password 12345 age 18 points 99
OK ##建立哈希并赋值
127.0.0.1:6379> HGETALL user:1 ##列出哈希的内容
1) "username"
2) "zhi"
3) "password"
4) "12345"
5) "age"
6) "18"
7) "points"
8) "99"
127.0.0.1:6379> HSET user:1 points 89 ##更改哈希中的值
(integer) 0
127.0.0.1:6379> HGETALL user:1 ##再次列出哈希内容
1) "username"
2) "zhi"
3) "password"
4) "12345"
5) "age"
6) "18"
7) "points"
8) "89"12345678910111213141516171819202122
三、Redis 配置
Redis 的配置文件位于 Redis 安装目录下,默认文件名为 redis.conf。
可以通过 CONFIG 命令查看或设置配置项。
Redis CONFIG 命令格式如下:
CONFIG GET CONFIG_SETTING_NAME
127.0.0.1:6379> CONFIG GET loglevel
1) "loglevel"
2) "notice"
使用 * 号获取所有配置项
127.0.0.1:6379> CONFIG GET *123456
编辑配置
可以通过修改 redis.conf 文件或使用 CONFIG set 命令来修改配置。
语法
CONFIG SET 命令基本语法:
CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE
127.0.0.1:6379> CONFIG SET loglevel "notice"
OK
127.0.0.1:6379> config get loglevel
1) "loglevel"
2) "notice"12345
参数说明
redis.conf 配置项说明如下:
Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
daemonize no
当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile /var/run/redis.pid
指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
绑定的主机地址
bind 127.0.0.1
当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 300
指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
loglevel verbose
日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
logfile stdout
设置数据库的数量,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id
databases 16
指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
save
Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。
指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes
指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
指定本地数据库存放目录
dir ./
设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
slaveof
当master服务设置了密码保护时,slav服务连接master的密码
masterauth
设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH 命令提供密码,默认关闭
requirepass foobared
设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
maxclients 128
指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区
maxmemory
指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
appendonly no
指定更新日志文件名,默认为appendonly.aof
appendfilename appendonly.aof
指定更新日志条件,共有3个可选值:
no:表示等操作系统进行数据缓存同步到磁盘(快)
always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)
vm-enabled no
虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-swap-file /tmp/redis.swap
将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
vm-max-memory 0
Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值
vm-page-size 32
设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。
vm-pages 134217728
设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
vm-max-threads 4
设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
glueoutputbuf yes
指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)
activerehashing yes
指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
include /path/to/local.conf
三、Redis服务器命令
1 BGREWRITEAOF ##异步改写仅追加文件
2 BGSAVE ##异步保存数据集到磁盘
3 CLIENT KILL [ip:port] [ID client-id] ##杀死一个客户端的连接
4 CLIENT LIST ##获取客户端连接到服务器的连接列表
5 CLIENT GETNAME ##获取当前连接的名称
6 CLIENT PAUSE timeout ##停止指定的时间处理来自客户端的命令
7 CLIENT SETNAME connection-name ##设置当前连接名称
8 CLUSTER SLOTS ##获取集群插槽数组节点的映射
9 COMMAND ##获取Redis的命令的详细信息数组
10 COMMAND COUNT ##得到的Redis命令的总数
11 COMMAND GETKEYS ##给予充分的Redis命令提取键
12 BGSAVE ##异步保存数据集到磁盘
13 COMMAND INFO command-name [command-name ...]
##获取具体的Redis命令的详细信息数组
14 CONFIG GET parameter ##获取配置参数的值
15 CONFIG REWRITE ##重写的存储器配置的配置文件
16 CONFIG SET parameter value ##配置参数设置为给定值
17 CONFIG RESETSTAT ##复位信息返回的统计
18 DBSIZE ##返回所选数据库中的键的数目
19 DEBUG OBJECT key ##获取有关的一个关键的调试信息
20 DEBUG SEGFAULT ##使服务器崩溃
21 FLUSHALL ##从所有数据库中删除所有项
22 FLUSHDB ##从当前数据库中删除所有项
23 INFO [section] ##获取有关服务器的信息和统计数据
24 LASTSAVE ##获得最后成功的UNIX时间时间戳保存到磁盘
25 MONITOR ##监听由实时服务器接收到的所有请求
26 ROLE ##返回在复制的情况下实例的角色
27 SAVE ##同步保存数据集到磁盘
28 SHUTDOWN [NOSAVE] [SAVE] ##同步的数据集保存到磁盘,然后关闭服务器
29 SLAVEOF host port ##使服务器为另一个实例的从站或者促进其作为主
30 SLOWLOG subcommand [argument] ##管理Redis的慢查询日志
31 SYNC ##命令用于复制
32 TIME ##返回当前服务器时间123456789101112131415161718192021222324252627282930313233
四、Redis持久化
Redis提供了RDB(Redis DataBase)和AOF(Append Only File)两种持久化方式。
RDB:在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上。
AOF:将redis执行过的所有写指令记录下来,在下次redis重新启动时,将这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。
RDB和AOF两种方式可以同时使用,在这种情况下,如果redis重启的话,则会优先采用AOF方式来进行数据恢复,因为AOF方式的数据恢复完整度更高。如果没有数据持久化的需求,也可以关闭RDB和AOF方式,这样,redis将变成一个纯内存数据库,就像memcache一样。
①Redis持久化 – RDB
RDB方式是将redis某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。
Redis在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,我们可以随时进行备份 ,因为快照文件总是完整可用的。
对于RDB方式,redis会单独创建(fork)一个子进程进行持久化,而主进程不会进行任何IO操作,这样就确保了redis极高的性能。如对大规模数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
②Redis持久化 – AOF
AOF(Append Only File)即只允许追加不允许改写的文件。
AOF将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍。如在追加日志时,磁盘空间满、inode满或断电等情况导致日志写入不完整,redis提供了redis-check-aof工具,用来进行日志修复。
因为采用了追加方式,如不做任何处理,AOF文件会变得越来越大,为此,redis提供了AOF文件重写(rewrite)机制,即当AOF文件的大小超过所设定的阈值时,redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。在进行AOF重写时,仍然采用先写临时文件,全部完成后再替换的流程,所以断电、磁盘满等问题都不会影响AOF文件的可用性。
修复出错的AOF文件方法:
1.备份被写坏的AOF文件
2.运行redis-check-aof –fix进行修复
3.用diff -u来看下两个文件的差异,确认问题点
4.重启redis,加载修复后的AOF文件
③Redis持久化 – AOF重写
在重写即将开始时,redis会创建(fork)一个“重写子进程”,这个子进程会首先读取现有的AOF文件,并将其包含的指令进行分析、压缩并写入到一个临时文件中。同时,主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。当”重写子进程”完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新AOF文件中。当追加结束后,redis就会用新AOF文件来代替旧AOF文件,之后再有新的写指令,就都会追加到新的AOF文件中。
五、Redis主从及原理
Redis支持主从同步,也支持一主多从及多级从结构。主从结构,一是为了纯粹的冗余备份,二是为了提升读性能。redis主从同步是异步进行的,主从架构中,从服务器通常被设置为只读模式。
从服务器会向主服务器发出SYNC指令,当主服务器接到此命令后,就会调用BGSAVE指令来创建一个子进程专门进行数据持久化工作,也就是将主服务器的数据写入RDB文件中。在数据持久化期间,主服务器将执行的写指令都缓存在内存中。在BGSAVE指令执行完成后,主服务器会将持久化好的RDB文件发送给从服务器,从服务器接到此文件后会将其存储到磁盘上,然后再将其读取到内存中。这个动作完成后,主服务器会将这段时间缓存的写指令再以redis协议的格式发送给从服务器。
注:即使有多个从服务器同时发来SYNC指令,主服务器也只会执行一次BGSAVE,然后把持久化好的RDB文件发给多个下游。
六、Redis的事务处理
MULTI、EXEC、DISCARD、WATCH这四个指令构成了redis事务处理的基础:
1.MULTI用来组装一个事务;
2.EXEC用来执行一个事务;
3.DISCARD用来取消一个事务;
4.WATCH用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行。
例:
127.0.0.1:6379> MULTI ##标记事务开始
OK
127.0.0.1:6379> INCR one ##多条命令按顺序入队
QUEUED ##成功插入缓存队列
127.0.0.1:6379> INCR two
QUEUED
127.0.0.1:6379> PING
QUEUED
127.0.0.1:6379> EXEC ##执行
1) (integer) 1
2) (integer) 1
3) PONG123456789101112
有关事务经常会遇到的两类错误:
1.调用EXEC之前的错误
2.调用EXEC之后的错误
①”调用EXEC之前的错误”:可能是由于语法有误导致的,也可能时由于内存不足导致的。只要出现某个命令无法成功写入缓冲队列的情况,redi都会进行记录,在客户端调用EXEC时,redis会拒绝执行这一事务。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> hhh ##输入错误指令
(error) ERR unknown command 'hhh'
127.0.0.1:6379> ping
QUEUED
127.0.0.1:6379> exec ##redis拒绝事务执行,原因是“之前出现了错误”
(error) EXECABORT Transaction discarded because of previous errors.12345678
②”调用EXEC之后的错误”:redis不会理睬这些错误,而是继续向下执行事务中的其他命令。因为对于应用层面的错误,并不是redis自身需要考虑和处理的问题,所以一个事务中如果某一条命令执行失败,并不会影响接下来的其他命令的执行。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set age 18
QUEUED
127.0.0.1:6379> sadd age 12 ##age不是集合,所以该命令是一条明显错误的指令
QUEUED
127.0.0.1:6379> set age 24
QUEUED
127.0.0.1:6379> exec ##执行事务时,redis不会理睬第2条指令执行错误
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK
127.0.0.1:6379> get age ##第3条指令成功执行
"24"1234567891011121314
WATCH的作用是“监视key是否被改动过”,而且支持同时监视多个key,只要还没真正触发事务,WATCH都会尽职尽责的监视,一旦发现某个key被修改了,在执行EXEC时就会返回nil,表示事务无法触发。
127.0.0.1:6379> set age 23
OK
127.0.0.1:6379> watch age ##开始监视age
OK
127.0.0.1:6379> set age 24 ##在EXEC之前,age的值被修改了
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set age 25
QUEUED
127.0.0.1:6379> get age
QUEUED
127.0.0.1:6379> exec ##触发EXEC
(nil) ##事务无法被执行1234567891011121314
七、Redis数据过期
127.0.0.1:6379> SET name zhi ##设置键值
OK
127.0.0.1:6379> TTL name ##查看过期时间
(integer) -1 ##TTL值w为-1表示永不过期
127.0.0.1:6379> EXPIRE name 3 ##设置该值3秒过期
(integer) 1
127.0.0.1:6379> GET name ##3秒后进行查看,数据已为空
(nil)