一,前言
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。
Redis中数据存储模式有2种:
cache-only即只做为“缓存”服务,不持久数据,数据在服务终止后将消失,此模式下也将不存在“数据恢复”的手段,是一种安全性低/效率高/容易扩展的方式;
persistence即为内存中的数据持久备份到磁盘文件,在服务重启后可以恢复,此模式下数据相对安全。
对于persistence持久化存储,Redis提供了两种持久化方法:
- Redis DataBase(简称RDB)-snapshots-快照持久化
- Append-only file
RDB概述
RDB是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。
优点:使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了redis的高性能
缺点:RDB是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候
这里说的这个执行数据写入到临时文件的时间点是可以通过配置来自己确定的,通过配置redis在n秒内如果超过m个key被修改这执行一次RDB操作。这个操作就类似于在这个时间点来保存一次Redis的所有数据,一次快照数据。所有这个持久化方法也通常叫做snapshots——快照持久化。
RDB默认开启,redis.conf中的具体配置参数如下;
#dbfilename:持久化数据存储在本地的文件
dbfilename dump.rdb
#dir:持久化数据存储在本地的路径,如果是在/redis/redis-3.0.6/src下启动的redis-cli,则数据会存储在当前src目录下
dir ./
##snapshot触发的时机,save <seconds> <changes>
##如下为900秒后,至少有一个变更操作,才会snapshot
##对于此值的设置,需要谨慎,评估系统的变更操作密集程度
##可以通过“save “””来关闭snapshot功能
#save时间,以下分别表示更改了1个key时间隔900s进行持久化存储;更改了10个key300s进行存储;更改10000个key60s进行存储。
save 900 1
save 300 10
save 60 10000
##当snapshot时出现错误无法继续时,是否阻塞客户端“变更操作”,“错误”可能因为磁盘已满/磁盘故障/OS级别异常等
stop-writes-on-bgsave-error yes
##是否启用rdb文件压缩,默认为“yes”,压缩往往意味着“额外的cpu消耗”,同时也意味这较小的文件尺寸以及较短的网络传输时间
rdbcompression yes
snapshot触发的时机,是有“间隔时间”和“变更次数”共同决定,同时符合2个条件才会触发snapshot,否则“变更次数”会被继续累加到下一个“间隔时间”上。snapshot过程中并不阻塞客户端请求。snapshot首先将数据写入临时文件,当成功结束后,将临时文件重名为dump.rdb。
使用RDB恢复数据:
如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。获取 redis 目录可以使用 CONFIG 命令,如下所示:
redis 127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/usr/local/redis/bin"
客户端使用命令进行持久化save存储:
./redis-cli -h ip -p port save
./redis-cli -h ip -p port bgsave
一个是在前台进行存储,一个是在后台进行存储。另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。
AOF概述
Append-only file,将“操作 + 数据”以格式化指令的方式追加到操作日志文件的尾部,在append操作返回后(已经写入到文件或者即将写入),才进行实际的数据变更,“日志文件”保存了历史所有的操作过程;当server需要数据恢复时,可以直接replay此日志文件,即可还原所有的操作过程。AOF相对可靠,它和mysql中bin.log、apache.log、zookeeper中txn-log简直异曲同工。AOF文件内容是字符串,非常容易阅读和解析。
优点:可以保持更高的数据完整性,如果设置追加file的时间是1s,如果redis发生故障,最多会丢失1s的数据;且如果日志写入不完整支持redis-check-aof来进行日志修复;AOF文件没被rewrite之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的flushall)。
缺点:AOF文件比RDB文件大,且恢复速度慢。
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
AOF默认关闭,开启方法,修改配置文件reds.conf:appendonly yes
##此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能
##只有在“yes”下,aof重写/文件同步等特性才会生效
appendonly yes
##指定aof文件名称
appendfilename appendonly.aof
##指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec
appendfsync everysec
##在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no”
no-appendfsync-on-rewrite no
##aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建议“512mb”
auto-aof-rewrite-min-size 64mb
##相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比。
##每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A),那么当aof文件增长到A*(1 + p)之后
##触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。
auto-aof-rewrite-percentage 100
AOF是文件操作,对于变更操作比较密集的server,那么必将造成磁盘IO的负荷加重;此外linux对文件操作采取了“延迟写入”手段,即并非每次write操作都会触发实际磁盘操作,而是进入了buffer中,当buffer数据达到阀值时触发实际写入(也有其他时机),这是linux对文件系统的优化,但是这却有可能带来隐患,如果buffer没有刷新到磁盘,此时物理机器失效(比如断电),那么有可能导致最后一条或者多条aof记录的丢失。通过上述配置文件,可以得知redis提供了3中aof记录同步选项:
appendfsync always #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec #每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no #从不同步。高效但是数据不会被持久化。
总结:
AOF和RDB各有优缺点,这是有它们各自的特点所决定:
1) AOF更加安全,可以将数据更加及时的同步到文件中,但是AOF需要较多的磁盘IO开支,AOF文件尺寸较大,文件内容恢复数度相对较慢。
2) snapshot,安全性较差,它是“正常时期”数据备份以及master-slave数据同步的最佳手段,文件尺寸较小,恢复数度较快。
字符串
命令格式 | 说明 |
SET key value | 设置指定 key 的值 |
GET key | 获取指定 key 的值 |
SETNX key value | (Set if Not Exist)只有在 key 不存在时设置 key 的值 |
SETRANGE key offset value | 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始 |
GETRANGE key start end | 返回 key 中字符串值的子字符 |
GETSET key value | 将给定 key 的值设为 value ,并返回 key 的旧值 |
MSET key value [key value ...] | (Multi Set)同时设置一个或多个 key-value 对 |
MGET key1 [key2..] | 获取所有(一个或多个)给定 key 的值 |
APPEND key value | 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾 |
SETEX key seconds value | (Set Expire)将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位) |
PSETEX key milliseconds value | (Precise Set Expire)这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位 |
STRLEN key | 返回 key 所储存的字符串值的长度 |
INCR key | 将 key 中储存的数字值增一,前提是value是一个数字 |
INCRBY key increment | 将 key 所储存的值加上给定的增量值,前提是value是一个数字 |
INCRBYFLOAT key increment | 将 key 所储存的值加上给定的浮点增量值,前提是value是一个数字 |
DECR key | 将 key 中储存的数字值减一,前提是value是一个数字 |
DECRBY key decrement | key 所储存的值减去给定的减量值,前提是value是一个数字 |
哈希
命令格式 | 说明 |
HMSET key field1 value1 [field2 value2... ] | (Hash Multi Set)同时将多个 field-value 对设置到哈希表 key 中 |
HMGET key field1 [field2...] | 获取所有给定字段的值 |
HSET key field value | 将哈希表 key 中的字段 field 的值设为 value |
HGET key field | 获取存储在哈希表中指定字段的值 |
HGETALL key | 获取在哈希表中指定 key 的所有字段和值 |
HDEL key field2 [field2] | 删除一个或多个哈希表字段 |
HSETNX key field value | 只有在字段 field 不存在时,设置哈希表字段的值 |
HKEYS key | 获取所有哈希表中的字段 |
HVALS key | 获取哈希表中所有值 |
HEXISTS key field | 查看哈希表 key 中,指定的字段是否存在 |
HLEN key | 获取哈希表中字段的数量 |
HINCRBY key field increment | 为哈希表 key 中的指定字段的整数值加上增量 |
HINCRBYFLOAT key field increment | 为哈希表 key 中的指定字段的浮点数值加上增量
|
列表
命令格式 | 说明 |
LPUSH key value1 [value2...] | 将一个或多个值插入到列表头部 |
LPOP key | 移出并获取列表的第一个元素 |
LPUSHX key value | (List Push if exist)将一个或多个值插入到已存在的列表头部 |
LINDEX key index | 通过索引获取列表中的元素 |
LRANGE key start stop | 获取列表指定范围内的元素 |
LSET key index value | 通过索引设置列表元素的值 |
LTRIM key start stop | 只保留指定区间内的元素,不在指定区间之内的元素都将被删除 |
RPOP key | (Rear Pop)移除并获取列表最后一个元素 |
RPUSH key value1 [value2...] | 将一个或多个值插入到列表尾部 |
RPUSHX key value | 将一个或多个值插入到已存在的列表尾部 |
LREM key count value | 从列表中删除字段值为value的元素,删除count的绝对值个value后结束,count > 0 从表头删除;count < 0 从表尾删除;count=0 全部删除 |
RPOPLPUSH source destination | 移除列表的最后一个元素,并将该元素添加到另一个列表并返回 |
BLPOP key1 [key2... ] timeout | 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止,如果timeout为0则一直等待下去
|
BRPOP key1 [key2... ] timeout | 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止,如果timeout为0则一直等待下去 |
LINSERT key BEFORE | AFTERpivot value | 在key 列表中寻找pivot,并在pivot值之前|之后插入value |
LLEN key | 获取列表长度
|
集合
命令格式 | 说明 |
SADD key member1 [member2…] | 向集合添加一个或多个成员 |
SREM key member1 [member2…] | 移除集合中一个或多个成员 |
SPOP key | 移除并返回集合中的一个随机元素 |
SMEMBERS key | 返回集合中的所有成员 |
SRANDMEMBER key [count] | 返回集合中count个随机元素,如count为空,则只返回一个 |
SCARD key | (Set Cardinality)返回集合中的元素总数 |
SISMEMBER key member | 判membe元素是否是集key 的成员 |
SMOVE source destination member | 将member元素从source集合移动到destination集合 |
SDIFF key1 [key2…] | 返回给定所有集合的差集,即以key1为基准,返回key1有且[key2...]没有的元素 |
SDIFFSTORE destination key1 [key2…] | 返回给定所有集合的差集并存储在destination中 |
SINTER key1 [key2…] | 返回给定所有集合的交集 |
SINTERSTORE destination key1 [key2…] | 返回给定所有集合的交集并存储在destination中 |
SUNION key1 [key2…] | 返回所有给定集合的并集 |
SUNIONSTORE destination key1 [key2…] | 所有给定集合的并集存储在destination集合中
|
有序列表
命令格式 | 说明 |
ZADD key score1 member1 [score2 member2 ...] | 添加一个或多个成员到有序集合,或者如果它已经存在更新其分数 |
ZRANGE key start stop [WITHSCORES] | 把集合排序后,返回名次在[start,stop]之间的元素。 WITHSCORES是把score也打印出来 |
ZREVRANGE key start stop [WITHSCORES] | 倒序排列(分数越大排名越靠前),返回名次在[start,stop]之间的元素 |
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset n] | 集合(升序)排序后取score在[min, max]内的元素,并跳过offset个,取出n个 |
ZREM key member [member ...] | 从有序集合中删除一个或多个成员 |
ZRANK key member | 确定member在集合中的升序名次 |
ZREVRANK key member | 确定member在集合中的降序名次 |
ZSCORE key member | 获取member的分数 |
ZCARD key | 获取有序集合中成员的数量 |
ZCOUNT key min max | 计算分数在min与max之间的元素总数 |
ZINCRBY key increment member | 给member的分数增加increment |
ZREMRANGEBYRANK key start stop | 移除名次在start与stop之间的元素 |
ZREMRANGEBYSCORE key min max | 移除分数在min与max之间的元素 |
Redis 安全
我们可以通过 redis 的配置文件设置密码参数,这样客户端连接到 redis 服务就需要密码验证,这样可以让你的 redis 服务更安全。
我们可以通过以下命令查看是否设置了密码验证:
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) ""
默认情况下 requirepass 参数是空的,这就意味着你无需通过密码验证就可以连接到 redis 服务。
你可以通过以下命令来修改该参数:
127.0.0.1:6379> CONFIG set requirepass "123456"
OK
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) "123456"
设置密码后,客户端连接 redis 服务就需要密码验证,否则无法执行命令。
语法
AUTH 命令基本语法格式如下:
127.0.0.1:6379> AUTH password
实例
127.0.0.1:6379> AUTH "123456"
OK
127.0.0.1:6379> SET mykey "Test value"
OK
127.0.0.1:6379> GET mykey
"Test value"