Redis基础
Redis支持的键值数据类型 (1) String:字符串类型 (2) hash:散列类型 (3) list:列表类型 (4) set:集合类型 (5) zset:有序集合类型 注意:Redis的key永远都是string,数据类型指的是value的类型。
默认一共是16个数据库,每个数据库之间是相互隔离。数据库的数量是在redis.conf中配置的 一个数据最大的存储量是512M 数值的最大范围:Long.MAX_VALUE
Redis通用命令
命令 作用 select [db] 切换(0~15)数据库 ping 测试服务器是否连通 echo [message] 打印message到控制台 move [key] [db] 把key移动到指定数据库 flushall 清空当前服务的所有16个数据库 dbsize 查看当前数据库有多少key flushdb 清空当前数据库 quit 退出当前数据库 keys * 查看当前数据库所有key
key常用命令
命令 作用 set [key] [value] 新建 mset [key] [value] [key] [value]… 新建多组 getset [key] [value] 先取出然后赋值 get [key] 获取key的值 exists [key] 判断key是否存在 type [key] 获取key的类型 del [key] 删除key expire [key] [seconds] 设置key的生存时间(单位:秒)key 在多少秒后会自动删除 ttl [key] 查看key剩余的生存时间, 返回-2代表不存在 返回-1代表永久存在。 persist [key] 清除生存时间即设置为永久存在
String常用命令
命令 作用 append [key] [value] 追加 strlen [key] 长度 incr/decr [key] +/- 1 必须为数字 incrby/decrby [key] [number] +/- [number] 必须为数字
命令 作用 getrange [key] [index1] [index2] 类似String.substring() setrange [key] [index] [value] 修改一定范围的值
127.0.0.1:6379[ 1] > GETRANGE k1 0 3
"abcd"
127.0.0.1:6379[ 1] > SETRANGE k1 0 lyc
( integer) 7
127.0.0.1:6379[ 1] > get k1
"lycdefg"
127.0.0.1:6379[ 1] >
命令 作用 setex [key] [s] [value] 插入kv并设置存活时间 setnx [key] [value] 如果不存在key则插入kv
127.0.0.1:6379[ 1] > keys *
1) "k2"
2) "k1"
127.0.0.1:6379[ 1] > setex lyc 10 nb
OK
127.0.0.1:6379[ 1] > ttl lyc
( integer) 5
127.0.0.1:6379[ 1] > ttl lyc
( integer) -2
127.0.0.1:6379[ 1] > get lyc
( nil)
127.0.0.1:6379[ 1] > keys *
1) "k2"
2) "k1"
127.0.0.1:6379[ 1] > setnx k1 merry
( integer) 0
127.0.0.1:6379[ 1] >
命令 作用 mset [k1] [v1] [k2] [v2]… 插入多个值 mget [k1] [k2]… 获取多个值 msetnx [k1] [v1] [k2] [v2]… 插入多个值 如果存在任何一个key 此次插入失效
127.0.0.1:6379[ 1] > mset k3 v3 k4 v4 k5 v5
OK
127.0.0.1:6379[ 1] > mget k1 k2 k3 k4 k5
1) "lycdefg"
2) "hijklmn"
3) "v3"
4) "v4"
5) "v5"
127.0.0.1:6379[ 1] >
list常用命令
命令 作用 LPUSH [list] [v1] [v2] [v3] … 从左边插入 RPUSH [list] [v1] [v2] [v3] … 从右边插入
127.0.0.1:6379[ 2] > LPUSH list1 1 2 3 4 5 6
( integer) 6
127.0.0.1:6379[ 2] > RPUSH list2 1 2 3 4 5 6
( integer) 6
127.0.0.1:6379[ 2] > LRANGE list1 0 -1
1) "6"
2) "5"
3) "4"
4) "3"
5) "2"
6) "1"
127.0.0.1:6379[ 2] > LRANGE list2 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
命令 作用 LPOP [list] 从左边弹出 RPOP [list] 从右边弹出
127.0.0.1:6379[ 2] > LPOP list1
"6"
127.0.0.1:6379[ 2] > RPOP list1
"1"
127.0.0.1:6379[ 2] > lrange list1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
127.0.0.1:6379[ 2] >
命令 作用 LINDEX [list] [index] 根据索引获取值
127.0.0.1:6379[ 2] > LINDEX list1 0
"5"
127.0.0.1:6379[ 2] > LLEN list1
( integer) 4
命令 作用 LREM [list] [amout] [value] 删除N个value
127.0.0.1:6379[ 2] > lpush list3 0 0 0 1 1 2 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6 6
( integer) 27
127.0.0.1:6379[ 2] > LREM list3 3 5
( integer) 3
127.0.0.1:6379[ 2] > LRANGE list3 0 -1
8) "5"
9) "5"
命令 作用 LTRIM [list] [index_start] [index_end] 截取指定范围的值重新赋值给当前key
127.0.0.1:6379[ 2] > LTRIM list3 0 4
OK
127.0.0.1:6379[ 2] > LRANGE list3 0 -1
1) "6"
2) "6"
3) "6"
4) "6"
5) "6"
命令 作用 RPOPLPUSH [list_orgin] [list_target] 将左边list的最右边的值push给右边list的左边
127.0.0.1:6379[ 2] > RPOPLPUSH list1 list2
"2"
127.0.0.1:6379[ 2] > LRANGE list1 0 -1
1) "5"
2) "4"
3) "3"
127.0.0.1:6379[ 2] > LRANGE list2 0 -1
1) "2"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
7) "6"
127.0.0.1:6379[ 2] >
127.0.0.1:6379[ 2] > LSET list2 1 x
OK
127.0.0.1:6379[ 2] > LRANGE list2 0 -1
1) "2"
2) "x"
3) "2"
4) "3"
5) "4"
6) "5"
7) "6"
127.0.0.1:6379[ 2] >
命令 作用 LINSERT key BEFORE/AFTER 在list的某个值(只在下标最小的位置插入 )之前或之后插入值
127.0.0.1:6379[ 2] > LINSERT list2 before x wo_jiu_shi
( integer) 8
127.0.0.1:6379[ 2] > LINSERT list2 after x xiao_feng_qing_yang
( integer) 9
127.0.0.1:6379[ 2] > LRANGE list2 0 -1
1) "2"
2) "wo_jiu_shi"
3) "x"
4) "xiao_feng_qing_yang"
5) "2"
6) "3"
7) "4"
8) "5"
9) "6"
127.0.0.1:6379[ 2] >
set常用命令
命令 作用 SADD 添加数据 重复数据不添加且不报错 SMEMBERS 获取set的元素值 SISMEMBER 是否存在该元素
127.0.0.1:6379[ 3] > SADD set1 1 1 2 3 6 6
( integer) 4
127.0.0.1:6379[ 3] > SMEMBERS set1
1) "1"
2) "2"
3) "3"
4) "6"
127.0.0.1:6379[ 3] > SISMEMBER set1 1
( integer) 1
127.0.0.1:6379[ 3] > SISMEMBER set1 4
( integer) 0
127.0.0.1:6379[ 3] > SCARD set1
( integer) 4
127.0.0.1:6379[ 3] > SREM set1 3
( integer) 1
127.0.0.1:6379[ 3] > SMEMBERS set1
1) "1"
2) "2"
3) "6"
127.0.0.1:6379[ 3] >
127.0.0.1:6379[ 3] > SRANDMEMBER set2 4
1) "6"
2) "4"
3) "5"
4) "7"
127.0.0.1:6379[ 3] > SRANDMEMBER set2 4
1) "6"
2) "64"
3) "7"
4) "9"
127.0.0.1:6379[ 3] > SPOP set2
"6"
127.0.0.1:6379[ 3] > SPOP set2
"5"
127.0.0.1:6379[ 3] > SMEMBERS set2
1) "3"
2) "4"
3) "7"
4) "9"
5) "21"
6) "59"
7) "64"
命令 作用 SMOVE 将一个set的值剪切到另一个set中
127.0.0.1:6379[ 3] > SMOVE set2 set1 64
( integer) 1
127.0.0.1:6379[ 3] > SMEMBERS set1
1) "1"
2) "2"
3) "6"
4) "64"
127.0.0.1:6379[ 3] > SMEMBERS set2
1) "3"
2) "4"
3) "7"
4) "9"
5) "21"
6) "59"
命令 作用 SDIFF 差集 SINTER 交集 SUNION 并集
127.0.0.1:6379[ 3] > sdiff set1 set2
1) "1"
2) "6"
127.0.0.1:6379[ 3] > sdiff set2 set1
1) "7"
2) "9"
127.0.0.1:6379[ 3] > SINTER set1 set2
1) "2"
2) "3"
3) "5"
127.0.0.1:6379[ 3] > SUNION set1 set2
1) "1"
2) "2"
3) "3"
4) "5"
5) "6"
6) "7"
7) "9"
Hash常用命令
命令 作用 HSET/HMSET/HSETNX 插入/批量插入/若不存在则插入 HSETNX 若不存在则插入 HGET/HMGET/HGETALL 查找/批量查找/查找全部 HDEL 删除 HLEN 长度
127.0.0.1:6379[ 4] > hset user id 1
( integer) 1
127.0.0.1:6379[ 4] > hmset user name lyc qq 835834117 age 20
OK
127.0.0.1:6379[ 4] > hget user id
"1"
127.0.0.1:6379[ 4] > hmget user id name
1) "1"
2) "lyc"
127.0.0.1:6379[ 4] > HGETALL user
1) "id"
2) "1"
3) "name"
4) "lyc"
5) "qq"
6) "835834117"
7) "age"
8) "20"
127.0.0.1:6379[ 4] > HDEL user qq
( integer) 1
127.0.0.1:6379[ 4] > HGETALL user
1) "id"
2) "1"
3) "name"
4) "lyc"
5) "age"
6) "20"
127.0.0.1:6379[ 4] > HLEN user
( integer) 3
127.0.0.1:6379[ 4] > HSETNX user id 2
( integer) 0
127.0.0.1:6379[ 4] > HSETNX user email 1807099649@qq.com
( integer) 1
127.0.0.1:6379[ 4] > HGETALL user
1) "id"
2) "1"
3) "name"
4) "lyc"
5) "age"
6) "20"
7) "email"
8) "1807099649@qq.com"
命令 作用 HEXISTS 这个HASH结构中是否存在名为某个值的key HKEYS 获取全部key HVALS 获取全部value
127.0.0.1:6379[ 4] > HGETALL user
1) "id"
2) "1"
3) "name"
4) "lyc"
5) "age"
6) "20"
127.0.0.1:6379[ 4] > HEXISTS user id
( integer) 1
127.0.0.1:6379[ 4] > HEXISTS user ib
( integer) 0
127.0.0.1:6379[ 4] > HVALS user
1) "1"
2) "lyc"
3) "20"
127.0.0.1:6379[ 4] > HKEYS user
1) "id"
2) "name"
3) "age"
命令 作用 HINCRBY 值自增一个整数(值必须为整数 浮点数也不行) HINCRBYFLOAT 值自增一个浮点数
127.0.0.1:6379[4]> HINCRBY user age 2
(integer) 26
127.0.0.1:6379[4]> HINCRBY user age 2
(integer) 28
127.0.0.1:6379[4]> HINCRBYFLOAT user age 2.2
"30.199999999999999"
127.0.0.1:6379[4]> HINCRBYFLOAT user age 2.2
"32.399999999999999"
zset常用命令
命令 作用 ZADD [zset] [key] [score] [value]… 插入, score用于排序 ZRANGE [zset] [index_start] [index_end] 从小到大排序 ZREVRANGE [zset] [index_start] [index_target] 大到小排序
排序时withscores可选,使结果带上score数值
127.0.0.1:6379[5]> zadd zset1 10 k1 20 k2 30 k3 40 k4 50 k5
(integer) 5
127.0.0.1:6379[5]> ZRANGE zset1 0 -1
1) "k1"
2) "k2"
3) "k3"
4) "k4"
5) "k5"
127.0.0.1:6379[5]> ZREVRANGE zset1 0 -1
1) "k5"
2) "k4"
3) "k3"
4) "k2"
5) "k1"
127.0.0.1:6379[5]> ZRANGE zset1 0 -1 WITHSCORES
1) "k1"
2) "10"
3) "k2"
4) "20"
5) "k3"
6) "30"
7) "k4"
8) "40"
9) "k5"
10) "50"
命令 作用 ZRANGEBYSCORE [zset] [score1] [score2] 小到大排序 数值带上括号表示不包含该score 可使用limit 类似mysql
127.0.0.1:6379[5]> ZRANGEBYSCORE zset1 10 30
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379[5]> ZRANGEBYSCORE zset1 (10 30
1) "k2"
2) "k3"
127.0.0.1:6379[5]> ZRANGEBYSCORE zset1 (10 (30
1) "k2"
命令 作用 ZREM [zset] [value] 移除某个元素 ZCARD [zset] 查看个数
127.0.0.1:6379[5]> ZREM zset1 k3
(integer) 1
127.0.0.1:6379[5]> ZRANGE zset1 0 -1
1) "k1"
2) "k2"
3) "k4"
4) "k5"
127.0.0.1:6379[5]> ZCARD zset1
(integer) 4
命令 作用 ZCOUNT [zset] [index] [index] 获取范围内总数 ZRANK [zset] [key] 获取排名 ZSCORE [zset] [key] 获取分数
127.0.0.1:6379[5]> ZRANGE zset1 0 -1
1) "k1"
2) "k2"
3) "k4"
4) "k5"
127.0.0.1:6379[5]> ZCOUNT zset1 10 50
(integer) 4
127.0.0.1:6379[5]> ZRANK zset1 k1
(integer) 0
127.0.0.1:6379[5]> ZRANK zset1 k4
(integer) 2
127.0.0.1:6379[5]> ZSCORE zset1 k2
"20"
D [zset]|查看个数
127.0.0.1:6379[5]> ZREM zset1 k3
(integer) 1
127.0.0.1:6379[5]> ZRANGE zset1 0 -1
1) "k1"
2) "k2"
3) "k4"
4) "k5"
127.0.0.1:6379[5]> ZCARD zset1
(integer) 4
命令 作用 ZCOUNT [zset] [index] [index] 获取范围内总数 ZRANK [zset] [key] 获取排名 ZSCORE [zset] [key] 获取分数
127.0.0.1:6379[ 5] > ZRANGE zset1 0 -1
1) "k1"
2) "k2"
3) "k4"
4) "k5"
127.0.0.1:6379[ 5] > ZCOUNT zset1 10 50
( integer) 4
127.0.0.1:6379[ 5] > ZRANK zset1 k1
( integer) 0
127.0.0.1:6379[ 5] > ZRANK zset1 k4
( integer) 2
127.0.0.1:6379[ 5] > ZSCORE zset1 k2
"20"
事务
Redis事务本质:一组命令的集合! 在事务执行过程中, 会按照顺序执行,且不会被其他客户端发来的命令请求打断 Redis事务没有隔离级别的概念!!! Redis单个命令保证原子性 事务不保证 原子性!!! 命令在事务中不会直接执行 一直等到exec
命令才执行
异常
编译型异常 命令不合法 事务失效 运行时异常 (e.g. incr “str”) 不影响事务的其他命令
乐观锁
命令:watch
命令
命令 作用 MULTI 开始事务 EXEC 执行事务 DISCARD 中断事务 WATCH 监视键值对(乐观锁)
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> exec
1) OK
2) ( error) ERR value is not an integer or out of range
3) OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> keys *
1) "aa"
2) "k2"
3) "k1"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> DISCARD
OK
redis持久化
持久化方式 RDB AOF 优点 适合大规模的数据恢复 数据安全性较高(每次修改/每秒 触发) 缺点 容易丢失部分数据 .aof文件巨大、恢复速度慢
RDB (Redis Database)
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里 Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。 rdb 保存的是dump.rdb文件 相关配置在配置文件的位置 - 在redis.conf搜寻### SNAPSHOTTING ###
如何触发RDB快照
配置文件中默认的快照配置dbfilename dump.rdb
冷拷贝后重新使用 可以cp dump.rdb dump_new.rdb
命令save或者是bgsave
Save:save时只管保存,其它不管,全部阻塞 BGSAVE:Redis会在后台异步进行快照操作, 快照同时还可以响应客户端请求。 可以通过lastsave 命令获取最后一次成功执行快照的时间
执行flushall命令,也会产生dump.rdb文件,但里面是空的,无意义
如何恢复
将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可 CONFIG GET dir获取目录
AOF (Append only file)
以日志的形式来记录每个 写 操作(读操作不记录) 只许追加文件但不可以改写文件 redis启动之初会读取该文件重新构建数据 换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
AOF配置
相关配置在配置文件的位置 - 在redis.conf搜寻 ### APPEND ONLY MODE ### aof保存的是appendonly.aof文件(在配置文件可修改文件名)
AOF启动/修复/恢复
正常恢复
启动:设置Yes 修改默认的appendonly no,改为yes 将有数据的aof文件复制一份保存到对应目录(config get dir) 恢复:重启redis然后重新加载 异常恢复
启动:设置Yes 修改默认的appendonly no,改为yes 备份被写坏的AOF文件 修复: Redis-check-aof --fix 进行修复 恢复: 重启redis然后重新加载
rewrite
AOF采用文件追加方式,文件会越来越大。 为避免出现此种情况,新增了重写机制. 当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩 只保留可以恢复数据的最小指令集。 可以使用命令bgrewriteaof
重写原理
AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename), 遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件, 而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似
触发机制
Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发