redis定义:是开源、BSD许可、高级的key-value存储系统。可以用来存储字符串、哈希结构、链表、集合,因此常用来提供数据结构服务。
1 redis安装
1.1 在主机上安装
名称 | 操作 |
---|---|
下载redis源代码 | wget http://t.cn/Eqw5XJ3 |
解压 | tar -zxvf 5.0.2.tar |
进入目录 | cd redis-5.0.2 |
编译 | make |
安装指定目录 | make install PREFIX=/usr/local/redis install |
复制配置文件 | cp redis.conf /usr/local/redis/ |
(1) 修改后修改配置文件
# 打开配置文件
vim /usr/local/redis/redis.conf
# 使redis启动后在后台运行
daemonize yes
# 设置密码,默认密码为空
requirepass 123456
# 允许远程连接,取消绑定本机
#bind 127.0.0.1
(2) 设置开机启动
在自启动/etc/init.d/文件夹下新建名字为redis的启动脚本,内容如下:
#!/bin/sh
# chkconfig: 2345 90 10
# description: Redis is a persistent key-value database
PATH=/usr/local/bin:/sbin:/usr/bin:/bin
REDISPORT=6379
EXEC=/usr/local/redis/bin/redis-server
REDIS_CLI=/usr/local/redis/bin/redis-cli
PIDFILE=/var/run/redis_6379.pid
CONF="/usr/local/redis/redis.conf"
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
if [ "$?"="0" ]
then
echo "Redis is running..."
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$REDIS_CLI -p $REDISPORT SHUTDOWN
while [ -x ${PIDFILE} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
restart|force-reload)
${0} stop
${0} start
;;
*)
echo "Usage: /etc/init.d/redis {start|stop|restart|force-reload}" >&2
exit 1
esac
exit 0
# 设置脚本文件的可执行权限
chmod +x /etc/init.d/redis
# 添加服务到service,开机启动
chkconfig --add /etc/init.d/redis
#启动服务
service redis start
# 停止服务
service redis stop
(3) 将redis的bin命令添加到PATH
# 打开profile文件
vim /etc/profile
# 在文件末尾添加内容如下:
export PATH=$PATH:/usr/local/redis/bin
# 使profile生效
source /etc/profile
# 停止无密码redis服务
redis-cli shutdown
# 停止有密码redis服务
redis-cli -a 123456 shutdown
# 启动客户端
redis-cli
# 授权
auth 123456
1.2 在docker安装redis
(1) 无持久化方式
操作的数据只在内存中,容器关闭了,数据会消失。
docker-compose.yml配置内容如下:
version: "3"
services:
redis:
image: redis:latest
restart: always
container_name: "redis-app"
command: redis-server --requirepass 123456
ports:
- 6379:6379
其中参数–requirepass表示客户端连接redis服务端时需要密码。
(2) 有持久化方式
AOF模式持久化,每秒钟强制写入磁盘一次。
docker-compose.yml配置内容如下:
version: "3"
services:
redis:
image: redis:latest
restart: always
container_name: "redis-app"
command: redis-server --requirepass 123456 --appendonly yes --appendfsync everysec
ports:
- 6379:6379
volumes:
- /data/redis:/data
其中–requirepass 表示客户端连接redis服务端时需要密码; –appendonly表hi是使用AOF模式持久化, –appendfsync表示多长时间把数据写入硬盘
(3) 自定义redis配置
docker-compose.yml配置内容如下:
version: "3"
services:
redis:
image: redis:latest
restart: always
container_name: "redis-app"
command: redis-server /usr/local/etc/redis/redis.conf
ports:
- 6379:6379
volumes:
- ./redis.conf:/usr/local/etc/redis/redis.conf
- /data/redis:/data
自定义配置文件,为了支持远程连接,在默认的配置修改了以下信息:
- bind:默认绑定本机,已取消
- protected-mode:默认开启,已取消
- requirepass:默认密码为空,已开启和设置密码
2 key操作命令
set 设置key的值
set key value
# 示例
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> set age 25
OK
get 获取key的值
get key
# 示例
127.0.0.1:6379> get name
"zhangsan"
del 删除key
del key
# 示例
127.0.0.1:6379> del name
(integer) 1
exists 判断key是否存在
exists key
# 判断key是否存在,存在返回1,不存在返回0
# 示例
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists title
(integer) 0
type 获取key类型
type key
# 获取key存储的值的类型
# 示例
127.0.0.1:6379> type name
string
127.0.0.1:6379> type age
string
expire 设置key有效期
expire key
# 设置key的生命周期
# pexpire key 表示以毫秒为单位设置声明周期
# 示例
127.0.0.1:6379[1]> expire login 60
(integer) 1
127.0.0.1:6379[1]> ttl login
(integer) 47
tll 查看key有效期
ttl key
# 查询key的生命周期
# 大于0 :生命周期单位为秒,
# 等于-1:永久有效
# 等于-2:该key不存在
# pttl key表示毫秒为单位
# 示例
127.0.0.1:6379> ttl name
(integer) -1
127.0.0.1:6379> ttl title
(integer) -2
rename 重命名key
rename key newkey
# 重命名key,如果newkey已经存在,修改后则替换新key的值
# 示例
127.0.0.1:6379> set title "redis test"
OK
127.0.0.1:6379> exists title
(integer) 1
127.0.0.1:6379> rename title biaoti
OK
127.0.0.1:6379> get biaoti
"redis test"
renamenx 重命名不存在的key
renamenx key newkey
# 重命名key,如果newkey已经存在则不修改。
# nx表示not exists
# 示例
127.0.0.1:6379> keys *
1) "biaoti"
2) "age"
3) "name"
127.0.0.1:6379> renamenx biaoti name
(integer) 0
persist 设置key永久有效
persist key
# 设置key永久有效
# 示例
127.0.0.1:6379> set login on
OK
127.0.0.1:6379> expire login 60
(integer) 1
127.0.0.1:6379> ttl login
(integer) 55
127.0.0.1:6379> persist login
(integer) 1
127.0.0.1:6379> ttl login
(integer) -1
move 把key移动到其他库
move key db
# 把key移动到另一个数据库,db为整数
# 示例
127.0.0.1:6379> keys *
1) "biaoti"
2) "age"
3) "name"
127.0.0.1:6379> move biaoti 1
(integer) 1
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "biaoti"
3 库操作命令
dbsize 查看当前有多少个key
dbsize
# 查看当前有多少个key
# 示例
127.0.0.1:6379> dbsize
12
select 选择库
select db
# 选择使用哪个数据库,db为整数
# 默认有16个数据库0~15,如果想修改数据库数量,修改redis.conf配置文件的databases值
# 示例
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[2]> select 15
OK
flushdb 删除选中数据库中的key
flushdb
# 删除当前选择数据库中的所有key
# 示例
127.0.0.1:6379[1]> keys *
1) "biaoti"
127.0.0.1:6379[1]> flushdb
OK
127.0.0.1:6379[1]> keys *
(empty list or set)
flushall 删除所有库的key
flushall
# 删除所有数据库中的key
# 示例
127.0.0.1:6379[1]> flushall
OK
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> keys *
(empty list or set)
4 字符串类型操作
set 设置kv、效期、判断key是否存在
set key value [ex 秒数]|[px 毫秒数] [nx]|[xx]
# 设置kv时也可以设置有效期和判断key是否存在
# ex和px不要同时写,否则以后面有效期为准
# nx表示key不存在时执行操作
# xx表示key存在时执行操作
# 示例
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> set name zhangsan ex 100
OK
127.0.0.1:6379> ttl name
(integer) 78
127.0.0.1:6379> set name lisi nx
(nil)
127.0.0.1:6379> get name
"zhangsan"
mset 一次性输入多个kv
mset key1 value1 key2 value2......
# 一次性输入多个key-value
# 示例
127.0.0.1:6379> mset x 1 y 2 z 3
OK
127.0.0.1:6379> keys *
1) "y"
2) "z"
3) "x"
setrange 修改偏移字节值为valuev
setrange key offset value
# 把字符串的偏移字节改为value
# 如果偏移量大于字符长度,中间字符自动补0x00
# 示例
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> setrange name 5 ***
(integer) 8
127.0.0.1:6379> get name
"zhang***"
append 在key的值后面追加字符串
append key value
# 在key的值后面追加value字符串
# 示例
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> append name "@126.com"
(integer) 16
127.0.0.1:6379> get name
"zhangsan@126.com"
getrange 获取key值的部分内容
getrange key start stop
# 获取key值的一部分内容
# start表示起始位置
# stop表示结束位置,可以为为负数,表示从最后数起
# start>length 空字符串
# stop>length 截取到结尾
# 示例
127.0.0.1:6379> set title "hello world"
OK
127.0.0.1:6379> getrange title 6 11
"world"
127.0.0.1:6379> getrange title 0 -7
"hello"
getset 设置新值返回旧值
getset key newvalue
# 设置新值,并返回旧值
# 示例
127.0.0.1:6379> set login on
OK
127.0.0.1:6379> get login
"on"
127.0.0.1:6379> getset login off
"on"
127.0.0.1:6379> get login
"off"
incr/decr 指定key的值加/减1
incr/decr key
# 指定key的值加/减1,返回结果
# key不存在时,自动创建并加减1
# key的值为字符串时无效
# 示例
127.0.0.1:6379> set num 100
OK
127.0.0.1:6379> incr num
(integer) 101
127.0.0.1:6379> decr num
(integer) 100
incrby/decrby 指定key的值加/减number
incrby/decrby key number
# 指定key的值加减number大小
# 示例
127.0.0.1:6379> set num 100
OK
127.0.0.1:6379> incrby num 50
(integer) 150
127.0.0.1:6379> decrby num 100
(integer) 50
incrbyfloat 指定key的值加浮点数
incrbyfloat key floatnumber
# 指定key的值加浮点数
# 示例
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> incrbyfloat num 0.5
"10.5"
127.0.0.1:6379> incrbyfloat num -1.5
"9"
setbit 设置二进制位上的值
setbit key offset value
# 设置offset对应二进制位上的值
# 返回改位的旧值
# 如果offset过大则会在中间填充0
# offset最大为2^32-1,即512M
# 示例
127.0.0.1:6379> set letter A
OK
127.0.0.1:6379> setbit letter 2 1
(integer) 0
127.0.0.1:6379> get letter
"a"
# 把0100 0001(65)改为0110 0001(97)即把大写A改为了小写a
getbit 获取二进制位上的值
getbit key offset
# 获取二进制offset对应位的值
# 示例
127.0.0.1:6379> set letter A
OK
127.0.0.1:6379> getbit letter 0
(integer) 0
127.0.0.1:6379> getbit letter 1
(integer) 1
127.0.0.1:6379> getbit letter 7
(integer) 1
bitop 对多个key逻辑操作
bitop operation destkey key1 [key2 ......]
# 对key1 key2 keyN做operation,并把结果保存到destkey 上
# operation有AND、OR、NOT、XOR
# 示例
127.0.0.1:6379> setbit lower 2 1
(integer) 0
127.0.0.1:6379> setbit upper 2 0
(integer) 0
127.0.0.1:6379> set letter A
OK
127.0.0.1:6379> bitop or letter letter lower
(integer) 1
127.0.0.1:6379> get letter
"a"
5 链表类型操作
lpush/rpush 在链表头/尾增加一个成员
lpush/rpush key value
# 在链表头/尾增加一个成员,返回链表成员的个数
# 示例
127.0.0.1:6379> lpush letters A
(integer) 1
127.0.0.1:6379> rpush letters B
(integer) 2
127.0.0.1:6379> rpush letters C
(integer) 3
127.0.0.1:6379> rpush letters D
(integer) 4
lrange 获取链表成员
lrange key start stop
# 返回链表中[start,stop]范围的成员
# 规律: 左数从0开始,右数从-1开始
# 示例
127.0.0.1:6379> lrange letters 0 -1
1) "A"
2) "B"
3) "C"
4) "D"
127.0.0.1:6379> lrange letters 1 2
1) "B"
2) "C"
lpop/rpop 弹出链表中头/尾的成员
lpop/rpop key
# 弹出链表中头/尾的成员
# 示例
127.0.0.1:6379> lrange letters 0 -1
1) "A"
2) "B"
3) "C"
4) "D"
127.0.0.1:6379> lpop letters
"A"
127.0.0.1:6379> rpop letters
"D"
127.0.0.1:6379> lrange letters 0 -1
1) "B"
2) "C"
lrem 删除链表成员
lrem key count value
# 从key链表中删除 value值
# 删除count的绝对值个value后结束
# count>0 从表头删除
# count<0 从表尾删除
# 示例
127.0.0.1:6379> rpush letters A B C D A B C D A B C D
(integer) 12
127.0.0.1:6379> lrem letters 2 A
(integer) 2
127.0.0.1:6379> lrange letters 0 -1
1) "B"
2) "C"
3) "D"
4) "B"
5) "C"
6) "D"
7) "A"
8) "B"
9) "C"
10) "D"
127.0.0.1:6379> lrem letters -3 D
(integer) 3
127.0.0.1:6379> lrange letters 0 -1
1) "B"
2) "C"
3) "B"
4) "C"
5) "A"
6) "B"
7) "C"
lindex 获取链表索引对应的值
lindex key index
# 获取链表索引index对应的值
# 示例
127.0.0.1:6379> rpush letters A B C D
(integer) 4
127.0.0.1:6379> lindex letters 1
"B"
127.0.0.1:6379> lindex letters 2
"C"
llen key 获取链表成员个数
llen key
# 获取链表成员个数
# 示例
127.0.0.1:6379> rpush letters A B C D
(integer) 4
127.0.0.1:6379> llen letters
(integer) 4
linsert 在链表中指定位置插入成员
linsert key after|before search value
# 在key链表中寻找"search",并在search值之前|之后插入value
# 如果没有找到,不插入值
# 如果找到一个search后,命令就结束了,因此不会插入多个value
# 示例
127.0.0.1:6379> rpush id 1 3 5 7
(integer) 4
127.0.0.1:6379> linsert id before 3 2
(integer) 5
127.0.0.1:6379> lrange id 0 -1
1) "1"
2) "2"
3) "3"
4) "5"
5) "7"
127.0.0.1:6379> linsert id after 5 6
(integer) 6
127.0.0.1:6379> lrange id 0 -1
1) "1"
2) "2"
3) "3"
4) "5"
5) "6"
6) "7"
blpop/brpop 一直等待弹出头/尾成员
blpop/brpop key timeout
# 等待弹出key的头/尾成员
# Timeout为等待超时时间
# 如果timeout为0,则一直等待
# 应用s场景: 长轮询Ajax,在线聊天时,能够用到
# 示例
# 第一个终端操作:
127.0.0.1:6379> brpop chat 0
1) "chat"
2) "hello"
(40.97s)
# 第二个终端操作:
127.0.0.1:6379> rpush chat "hello"
(integer) 1
6 无序集合操作
集合特性:无序性、唯一性、确定性
sadd 往集合添加成员
sadd key value1 value2 ...
# 往集合key中增加成员
# 增加相同成员时只会添加一个(唯一性)
# 示例
127.0.0.1:6379> sadd names zhangsan lisi
(integer) 2
127.0.0.1:6379> sadd names wangwu wangwu
(integer) 1
srem 删除集合成员
srem key value1 value2 ...
# 删除集合中为value1 value2...成员
# 返回真正删除掉的成员个数(不包括不存在的成员)
# 示例
127.0.0.1:6379> sadd names zhangsan lisi wangwu
(integer) 3
127.0.0.1:6379> srem names zhangsan lisi
(integer) 2
127.0.0.1:6379> smembers names
1) "wangwu"
spop 随机删除集合一个成员
spop key
# 随机删除集合key中的一个成员
# 应用场景:抽奖,抽中的人已经排除,不可能会被再次抽中了
# 示例
127.0.0.1:6379> sadd letters A B C D E F
(integer) 6
127.0.0.1:6379> spop letters
"A"
127.0.0.1:6379> spop letters
"F"
127.0.0.1:6379> spop letters
"B"
127.0.0.1:6379> spop letters
"D"
srandmember 随机获取集合成员
srandmember key [count]
# 随机获取集合key的count个成员,默认count是1
# 示例
127.0.0.1:6379> srandmember letters
"C"
127.0.0.1:6379> srandmember letters 2
1) "E"
2) "B"
127.0.0.1:6379> srandmember letters 3
1) "D"
2) "C"
3) "E"
smembers 获取集合所有的成员
smembers key
# 返回集合所有的成员
# 返回值的顺序不一定是添加成员的顺序(无序性)
# 示例
127.0.0.1:6379> sadd names zhangsan lisi wangwu
(integer) 3
127.0.0.1:6379> smembers names
1) "lisi"
2) "wangwu"
3) "zhangsan"
sismember 判断成员是否存在集合中
sismember key value
# 判断value是否存在集合key中,存在返回1,不存在返回0
# 示例
127.0.0.1:6379> sadd names zhangsan lisi wangwu
(integer) 3
127.0.0.1:6379> sismember names lisi
(integer) 1
127.0.0.1:6379> sismember names zhaoliu
(integer) 0
scard 获取集合成员的个数
scard key
# 获取集合成员的个数
# 示例
127.0.0.1:6379> sadd letters A B C D
(integer) 4
127.0.0.1:6379> sadd letters E F
(integer) 2
127.0.0.1:6379> scard letters
(integer) 6
smove 把一个集合中成员移动到另一个集合
smove <source> <dest> value
# 把集合source中的value删除,并添加到集合dest中
# 示例
127.0.0.1:6379> sadd letters A B C
(integer) 3
127.0.0.1:6379> sadd num 1 2 3
(integer) 3
127.0.0.1:6379> smove letters num A
(integer) 1
127.0.0.1:6379> smembers letters
1) "C"
2) "B"
127.0.0.1:6379> smembers num
1) "3"
2) "1"
3) "A"
4) "2"
sunion 获取多个集合的并集
sunion key1 key2 ...
# 获取多个集合的并集
# 示例
127.0.0.1:6379> sadd zhangsan A E G
(integer) 3
127.0.0.1:6379> sadd lisi B E F
(integer) 3
127.0.0.1:6379> sadd wangwu C D E
(integer) 3
127.0.0.1:6379> sunion zhangsan lisi wangwu
1) "B"
2) "G"
3) "D"
4) "C"
5) "E"
6) "F"
7) "A"
sdiff 获取多个集合的差集
sdiff key1 key2 ...
# 获取key1与key2...的差集
# 即key1-key2...(key1有其他集合没有的成员)
# 示例
127.0.0.1:6379> sadd zhangsan A B C
(integer) 3
127.0.0.1:6379> sadd lisi B D E
(integer) 3
127.0.0.1:6379> sadd wangwu C E F
(integer) 3
127.0.0.1:6379> sdiff zhangsan lisi wangwu
1) "A"
sinterstore 获取多个集合的交集并储存
sinterstore dest key1 key2 ...
# 求出key1 key2 ...集合中的交集,并赋给dest
# 示例
127.0.0.1:6379> sadd zhangsan A C D
(integer) 3
127.0.0.1:6379> sadd lisi B D E
(integer) 3
127.0.0.1:6379> sadd wangwu D E G
(integer) 3
127.0.0.1:6379> sinterstore class zhangsan lisi wangwu
(integer) 1
127.0.0.1:6379> smembers class
1) "D"
7 有序集合操作
zadd 往有序集合添加成员
zadd key score1 key2 score2 key2 ...
# 往有序集合key添加成员
# 示例
127.0.0.1:6379> zadd ages 28 zhangsan 24 lisi 26 wangwu
(integer) 0
127.0.0.1:6379> zrange ages 0 -1
1) "lisi"
2) "wangwu"
3) "zhangsan"
zrange 按名次取成员
zrange key start stop [WITHSCORES]
# 把集合排序后,返回名次[start,stop]的成员按名次取成员
# 默认是升续排列,withscores 是把score也打印出来
# 示例
127.0.0.1:6379> zrange ages 0 -1 withscores
1) "lisi"
2) "24"
3) "wangwu"
4) "26"
5) "zhangsan"
6) "28"
zrangebyscore 按分数取成员
zrangebyscore key min max [withscores] limit offset N
# 集合(升续)排序后,取score在[min,max]内的成员,并跳过offset个,取出N个,按分数取成员
# 示例
127.0.0.1:6379> zadd ages 28 zhangsan 24 lisi 26 wangwu
(integer) 3
127.0.0.1:6379> zrangebyscore ages 25 30
1) "wangwu"
2) "zhangsan"
127.0.0.1:6379> zrangebyscore ages 25 30 limit 1 1
1) "zhangsan"
zscore 获取指定成员的分数
ZSCORE key member
# 获取指定成员的分数
# 示例
127.0.0.1:6379> zadd height 175 zhangsan 167 lisi 185 wangwu
(integer) 3
127.0.0.1:6379> zscore height lisi
"167"
zcount 计算分数区间成员个数
zcount key min max
# 计算[min,max]区间内成员的数量
# 示例
127.0.0.1:6379> zadd height 175 zhangsan 167 lisi 185 wangwu
(integer) 3
127.0.0.1:6379> zcount height 170 180
(integer) 1
zrank/zrevrank 获取成员升序/降序的排名
zrank/zrevrank key member
# 查询member的升序/降序排名,名次从0开始
# 示例
127.0.0.1:6379> zadd ages 28 zhangsan 24 lisi 26 wangwu
(integer) 0
127.0.0.1:6379> zrange ages 0 -1
1) "lisi"
2) "wangwu"
3) "zhangsan"
127.0.0.1:6379> zrank ages zhangsan
(integer) 2
127.0.0.1:6379> zrevrank ages zhangsan
(integer) 0
zrem 删除有序集合成员
zrem key value1 value2 ..
# 删除集合中的成员
# 示例
127.0.0.1:6379> zrem ages wangwu
(integer) 1
127.0.0.1:6379> zrange ages 0 -1
1) "lisi"
2) "zhangsan"
zremrangebyrank 按排名删除成员
zremrangebyrank key start end
# 按排名删除成员,删除名次在[start,end]之间的
# 示例
127.0.0.1:6379> zadd height 175 zhangsan 167 lisi 185 wangwu 178 zhaoliu
(integer) 1
127.0.0.1:6379> zremrangebyrank height 0 1
(integer) 2
127.0.0.1:6379> zrange height 0 -1
1) "zhaoliu"
2) "wangwu"
zremrangebyscore 按分数删除成员
zremrangebyscore key min max
# 按照socre来删除成员,删除score在[min,max]之间的
# 示例
127.0.0.1:6379> zadd height 175 zhangsan 167 lisi 185 wangwu 178 zhaoliu
(integer) 2
127.0.0.1:6379> zremrangebyscore height 170 180
(integer) 2
127.0.0.1:6379> zrange height 0 -1
1) "lisi"
2) "wangwu"
zinterstore 求交集再计算
zinterstore destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
# 求key1、key2...的交集,key1、key2...的权重分别是 weight1、weight2...
# 聚合方法用: sum|min|max
# 聚合的结果保存在destination集合内
# 示例
127.0.0.1:6379> zadd zhangsan 5 iphone6s 7 galaxyS7 6 huaweiP9
(integer) 3
127.0.0.1:6379> zadd lisi 3 iphone6s 9 galaxyS7 4 huaweiP9 2 HTC10
(integer) 4
127.0.0.1:6379> zinterstore result 2 zhangsan lisi
(integer) 3
127.0.0.1:6379> zrange result 0 -1 withscores
1) "iphone6s"
2) "8"
3) "huaweiP9"
4) "10"
5) "galaxyS7"
6) "16"
127.0.0.1:6379> zinterstore result 2 zhangsan lisi aggregate max
(integer) 3
127.0.0.1:6379> zrange result 0 -1 withscores
1) "iphone6s"
2) "5"
3) "huaweiP9"
4) "6"
5) "galaxyS7"
6) "9"
zunionstore 求并集再计算
zunionstore destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
# 求key1、key2...的并集,key1、key2...的权重分别是 weight1、weight2...
# 聚合方法用: sum|min|max
# 聚合的结果保存在destination集合内
# 示例
127.0.0.1:6379> zadd zhangsan 4 iphone6s 6 huaweiP9 8 xiaomi5
(integer) 3
127.0.0.1:6379> zadd lisi 2 iphone6s 8 galaxS7 5 meizu6
(integer) 3
127.0.0.1:6379> zunionstore result 2 zhangsan lisi
(integer) 5
127.0.0.1:6379> zrange result 0 -1 withscores
1) "meizu6"
2) "5"
3) "huaweiP9"
4) "6"
5) "iphone6s"
6) "6"
7) "galaxS7"
8) "8"
9) "xiaomi5"
10) "8"
127.0.0.1:6379> zunionstore result 2 zhangsan lisi aggregate max
(integer) 5
127.0.0.1:6379> zrange result 0 -1 withscores
1) "iphone6s"
2) "4"
3) "meizu6"
4) "5"
5) "huaweiP9"
6) "6"
7) "galaxS7"
8) "8"
9) "xiaomi5"
10) "8"
8 哈希数据类操作
hset 设置哈希field域的值
hset key field value
# 把key中 filed域的值设为value
# 注:如果没有field域,直接添加,如果有,则覆盖原field域的值
# 示例
127.0.0.1:6379> hset user name zhangsan
(integer) 1
127.0.0.1:6379> hset user age 25
(integer) 1
127.0.0.1:6379> hset user gender male
(integer) 1
hmset 设置哈希多个field域的值
hmset key field1 value1 [field2 value2 field3 value3 ......fieldn valuen]
# 一次设置多个field和对应的value
# 示例
127.0.0.1:6379> hmset user name lisi age 26 gender male
OK
hget 获取field域的值
hget key field
# 获取field域的值
# 示例
127.0.0.1:6379> hmset user name lisi age 26 gender male
OK
127.0.0.1:6379> hget user age
"26
hmget 获取多个field域的值
hget key field
# 获取多个field域的值
# 示例
127.0.0.1:6379> hmset user name lisi age 26 gender male
OK
127.0.0.1:6379> hmget user name age
1) "lisi"
2) "26"
hgetall 获取所有field域和值
hget key
# 获取哈希key的所有field域和值
# 示例
127.0.0.1:6379> hmset user name lisi age 26 gender male
127.0.0.1:6379> hgetall user
1) "name"
2) "lisi"
3) "age"
4) "26"
5) "gender"
6) "male"
hlen 获取field的数量
hlen key
# 获取field的数量
# 示例
127.0.0.1:6379> hmset user name lisi age 26 gender male
127.0.0.1:6379> hlen user
(integer) 3
hdel 删除field域
hdel key field
# 删除key中 field域
# 示例
127.0.0.1:6379> hmset user name lisi age 26 gender male
127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hgetall user
1) "name"
2) "lisi"
3) "gender"
4) "male"
hexists 判断field域是否存在
hexists key field
# 判断key中有没有field域
# 示例
127.0.0.1:6379> hmset user name lisi age 26 gender male
OK
127.0.0.1:6379> hexists user age
(integer) 1
127.0.0.1:6379> hexists user height
(integer) 0
hincrby 使field域的值加上整数
hincrby key field value
# 使key中的field域的值加上整型值value
# 示例
127.0.0.1:6379> hmset user name zhangsan height 158
OK
127.0.0.1:6379> hincrby user height 2
(integer) 160
hincrbyfloat 使field域的值加上浮点数
hincrbyfloat key field value
# 使key中的field域的值加上浮点值value
# 示例
127.0.0.1:6379> hmset user name zhangsan height 158
OK
127.0.0.1:6379> hincrbyfloat user height 5.5
"165.5"
hkeys 获取所有所有field域的名字
hkeys key
# 获取key中所有的field
# 示例
127.0.0.1:6379> hmset user name zhangsan age 25 gender male
OK
127.0.0.1:6379> hkeys user
1) "name"
2) "age"
3) "gender"
kvals 获取所有所有field域的值
kvals key
# 返回key中所有的value
# 示例
127.0.0.1:6379> hmset user name zhangsan age 25 gender male
OK
127.0.0.1:6379> hvals user
1) "zhangsan"
2) "25"
3) "male"
9 经纬度数据操作
geoadd 添加地理位置信息
geoadd key longitude latitude member [longitude latitude member ...]
# longitude表示经度,latitude表示纬度,member表示成员
# 示例
127.0.0.1:6379> geoadd Guangdong-cities 113.2278442 23.1255978 Guangzhou 113.106308 23.0088312 Foshan 113.7943267 22.9761989 Dongguan 114.0538788 22.5551603 Shenzhen
(integer) 4
geopos 查询位置的坐标
geopos location-set name [name ...]
# 示例
127.0.0.1:6379> geopos Guangdong-cities Guangzhou Shenzhen
1) 1) "113.22784155607223511"
2) "23.1255982020608073"
2) 1) "114.05388146638870239"
2) "22.55515920515157546"
geodist 查询位置距离
geodist key member1 member2 [m|km|mi|ft]
# 查询两个位置之间的距离
# 示例
127.0.0.1:6379> geodist Guangdong-cities Guangzhou Shenzhen
"105806.7782"
georadius 查询某点的附近点
georadius key longitude latitude radius m|km|mi|ft
# 指定经纬度作为中心来查询附近的点
# 示例
127.0.0.1:6379> georadius Guangdong-cities 113.2278442 23.1255978 100 km
1) "Foshan"
2) "Guangzhou"
3) "Dongguan"
georadiusbymember 查询某位置距离的附近点
georadiusbymember key member radius m|km|ft|mi
# 指定成员作为中心来查询附近的点
# 示例
127.0.0.1:6379> georadiusbymember Guangdong-cities Guangzhou 100 km
1) "Foshan"
2) "Guangzhou"
3) "Dongguan"
geohash 查询位置GEOHASH编码
geohash key member [member ...]
# 返回位置元素的哈希值
# 示例
127.0.0.1:6379> geohash Guangdong-cities Guangzhou
1) "ws0e89curg0"
10 事务
redis支持简单的事务。
10.1 事务命令
命令 | 说明 |
---|---|
muitl | 开启事务命令 |
command | 普通命令 |
discard | 在提交前取消 |
exec | 提交 |
注:discard只是结束本次事务,前2条语句已经执行,造成的影响仍然还在。
语句出错有两种情况: - 语法有问题,exec时报错,所有语句取消执行,没有对数据造成影响。 - 语法本身没错,但适用对象有问题(比如 zadd 操作list对象),exec之后,会执行正确的语句,并跳过有不适当的语句,对数据会造成影响,这点由程序员负责。
乐观锁
redis的事务中启用的是乐观锁,只负责监测key没有被改动,如果在事务中发现key被改动,则取消事务。使用watch命令来监控一个或多个key,使用unwatch命令来取消监控所有key。
# 示例
watch key
muitl
操作数据...
exec
unwatch
模拟抢票,场景:户买一张票,扣掉100元
# 在zhangsan买票过程中,在提交事务前一瞬间,有人成功买到票,ticket已经改变(即使ticket还有票),导致zhangsan抢票失败。
127.0.0.1:6379> watch ticket
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decr ticket
QUEUED
127.0.0.1:6379> decrby zhangsan 100
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get zhangsan
"1000"
127.0.0.1:6379> get ticket
"2"
127.0.0.1:6379> unwatch
OK
# lisi在买票整个过程都没有人抢票,所以lisi一次抢票成功。
127.0.0.1:6379> watch ticket
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby lisi 100
QUEUED
127.0.0.1:6379> decr ticket
QUEUED
127.0.0.1:6379> exec
1) (integer) 700
2) (integer) 1
127.0.0.1:6379> unwatch
11 频道发布与订阅
- 发布端:publish
- 订阅端:subscribe,psubscribe
publish 发布频道
publish 频道名称 发布内容
# 示例
127.0.0.1:6379> publish music_2 "It's Not Goodbye"
(integer) 1
127.0.0.1:6379> publish music "just one last dance"
(integer) 2
127.0.0.1:6379> publish music "stay"
(integer) 2
127.0.0.1:6379> publish music_2 "It's Not Goodbye"
(integer) 1
subscribe 订阅指定频道
subscribe 频道名称
# 示例
127.0.0.1:6379> subscribe music
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "music"
3) (integer) 1
1) "message"
2) "music"
3) "just one last dance"
1) "message"
2) "music"
3) "stay" "music"
3) (integer) 1
1) "message"
2) "music"
3) "just one last dance"
1) "message"
2) "music"
3) "stay"
psubscribe 订阅已匹配频道
psubscribe 匹配频道名称
# 示例
127.0.0.1:6379> psubscribe music*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "music*"
3) (integer) 1
1) "pmessage"
2) "music*"
3) "music"
4) "just one last dance"
1) "pmessage"
2) "music*"
3) "music"
4) "stay"
1) "pmessage"
2) "music*"
3) "music_2"
4) "It's Not Goodbye"
13 redis持久化
13.1 rdb快照持久化
rdb的工作原理:每隔N分钟或N次写操作后,从内存dump数据形成rdb文件,压缩放在备份目录,设置配置文件参数:
# 打开配置文件
vim /usr/local/redis/ redis.conf
save 900 1 # 900秒内,有1条写入,则产生快照
save 300 1000 # 如果300秒内有1000次写入,则产生快照
save 60 10000 # 如果60秒内有10000次写入,则产生快照
(这3个选项都屏蔽,则rdb禁用)
stop-writes-on-bgsave-error yes # 后台备份进程出错时,主进程停不停止写入
rdbcompression yes # 导出的rdb文件是否压缩
Rdbchecksum yes # 导入rbd恢复时数据时,要不要检验rdb的完整性
dbfilename dump.rdb # 导出来的rdb文件名
dir /usr/local/redis/data # rdb的放置路径
# 压力测试来检测是否启用了rdb快照
/usr/local/redis/bin/redis-benchmark
rdb的缺陷:在2个保存点之间断电,将会丢失1-N分钟的数据
13.2 aof日志持久化
工作原理:redis主进程 –> 后台日志进程 –> aof文件
设置配置文件参数:
# 打开配置文件
vim /usr/local/redis/ redis.conf
appendonly no # 是否打开 aof日志功能
appendfilename "appendonly.aof" # aof文件名,和rdb的dir公用一个路径
#appendfsync always # 每1个写命令都立即同步到aof文件,安全但速度慢
appendfsync everysec # 折衷方案,每秒写1次
上面方案选择一种,一般选择everysec
appendfsync no # 写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof文件,同步频率低,但速度快
no-appendfsync-on-rewrite yes # 正在导出rdb快照的过程中,要不要停止同步aof
auto-aof-rewrite-percentage 100 # aof文件大小比起上次重写时的大小,增长率100%时重写
auto-aof-rewrite-min-size 64mb # aof文件至少超过64M时才重写
注意:如果需要持久化,一般推荐rdb和aof同时开启,同时开启后redis进程启动优先选择aof恢复数据。rdb恢复速度快。
在dump rdb过程中,aof如果停止同步,会不会丢失? 不会,所有的操作缓存在内存的队列里,dump完成后统一操作.
aof重写是指什么? aof重写是指把内存中的数据,逆化成命令,写入到.aof日志里,以解决 aof日志过大的问题,手动重写aof命令:bgrewriteaof
14 redis导出导入数据库
(1) 安装redis-dump工具
yum install ruby rubygems ruby-devel
gem sources --remove http://ruby.taobao.org/
gem sources -a https://ruby.taobao.org/
gem install redis-dump -V
(2) 导出redis数据
redis-dump -u 127.0.0.1:6379 > test.json
(3) 导入redis数据
< test.json redis-load
15 redis应用示例
15.1 统计活跃用户
场景: 1亿个用户,用户登陆,标记为今天活跃,否则记为不活跃,记录最活跃用户。
# 思路
每个用户在数据库都有一个id,用第id个位的0和1来表示是否登录,例如:
login0721: '011001...............0'
......
login0726: '011001...............0'
login0727: '0110000.............1'
# 实现过程
(1) 记录用户登陆,每天按日期生成一个位图,用户登陆后,把user_id位上的bit值置为1
首先把所有用户的位置位0
redis 127.0.0.1:6379> setbit login0721 100000000 0
(integer) 0
redis 127.0.0.1:6379> setbit login0721 3 1
(integer) 0
redis 127.0.0.1:6379> setbit login0721 5 1
(integer) 0
redis 127.0.0.1:6379> setbit login0721 7 1
(integer) 0
......
redis 127.0.0.1:6379> setbit login0722 100000000 0
(integer) 0
redis 127.0.0.1:6379> setbit login0722 3 1
(integer) 0
redis 127.0.0.1:6379> setbit login0722 5 1
(integer) 0
redis 127.0.0.1:6379> setbit login0722 8 1
(integer) 0
......
redis 127.0.0.1:6379> setbit login0723 100000000 0
(integer) 0
redis 127.0.0.1:6379> setbit login0723 3 1
(integer) 0
redis 127.0.0.1:6379> setbit login0723 4 1
(integer) 0
redis 127.0.0.1:6379> setbit login0723 6 1
(integer) 0
......
(2)把1周/月的位图用and计算, 位为1的是连续登陆的用户。
redis 127.0.0.1:6379> bitop and login0721 login0722 login0723......
(integer) 12500001
# 优点
(1) 节约空间,用1亿bit表示1亿人每天的登陆情况,1亿bit约为10M。
(2) 计算方便,计算速度非常快
专题「数据库」的其它文章 »
- etcd基础与使用 (Nov 15, 2020)
- mongoDB基础和使用 (Feb 24, 2019)
- mysql基础和使用 (Feb 17, 2019)
- 搭建高可用redis集群 (Sep 26, 2018)
- 搭建高可用mysql集群PXC (Sep 21, 2018)