一. 软件安装
官网下载地址: https://redis.io/download
Redis版本: 5.0.8
系统: mac os
1.1 编译和安装
- 如果是Linux系统,需要预先安装GCC编译器
yum install -y gcc-c++
- 解压
tar -zxvf redis-5.0.8.tar.gz
- 新建redis安装目录
mkdir /app/redis-5.0.8/redis-install
- 切换至redis解压根目录:
cd /app/redis-5.0.8
- 编译与安装Redis至指定目录(PREFIX参数用于指定安装目录的路径,如果不指定目录,则默认安装在/usr/local目录)
make && make install PREFIX=/app/redis-5.0.8/redis-install
执行完毕后会在指定目录下自动生成bin目录,内含6份文件:
可能出现的异常:
- 执行make命令时报错: zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory
原因是jemalloc重载了Linux下的ANSI C的malloc和free函数。解决办法:make时添加参数。
make MALLOC=libc
1.2 redis.conf简单配置
- 新建自定义配置文件
我们可以将Redis解压后得到的目录中现有的redis.conf复制一份放到redis-install目录
cp /app/redis-5.0.8/redis.conf /app/redis-5.0.8/redis-install/redis.conf
- redis.conf的简单配置
# 是否为精灵进程,默认非精灵进程启动。修改成yes即可。
# 精灵启动就是通过后台守护进程的方式启动
daemonize yes
# 端口号 默认为6379,可以自行配置
port 6379
# redis中的schema数量。schema可以看成数据库。
# schema只有编号,从0开始,到数据库数量-1为止 默认提供16个库
database 16
# 持久化规则 Redis的默认持久化规则是RDB 将数据集的内存快照dump(转存)到dump.rdb文件中。
# 我们可以通过添加配置来修改Redis服务器转存内存快照的频率,如下:
# 在900秒(15分钟)之内,如果至少有一个key发生变化,则dump(转存)内存快照
save 900 1
# 在300秒(5分钟)之内,如果至少有10个key发生变化,则dump(转存)内存快照
save 300 10
# 在60秒(1分钟)之内,如果至少有10000个key发生变化,则dump(转存)内存快照
save 60 10000
# RDB持久化文件的名称
dbfilename dump.rdb
# 存放数据的路径 默认dir ./
dir ./
# 是否启用append of file持久化方式 默认关闭
# append of file: 以追加的方式,持久化数据到文件(否则使用覆盖的方式)
appendonly no
# aof持久化方式的文件名称
appendfilename “appendonly.aof”
1.3 启动
- 启动Redis (指定配置文件)
/app/redis-5.0.8/redis-install/redis-server …/redis.conf
执行完毕后,控制台会输出以下内容:
1.4 客户端连接
客户端连接Redis服务端时,需要使用redis-cli,此程序在安装后自动生成于bin目录之下。
执行命令如下:
redis-cli [-h ip -p port]
-h与-p参数可选填,默认连接localhost 6379端口的Redis应用。
二. 数据类型
Redis中的数据都是以键值对(key-value)的形式存储,其中key只能填写字符串类型,所以讨论Redis的数据类型,实际上就是在讨论value能存储的数据类型。
Redis总共支持5种数据类型,分别是: string(字符串)、hash(哈希)、list(链表)、set(集合)以及zSet(sorted set: 有序集合)。
2.1 字符串
谈到Redis中的字符串,就不得不先引入SDS的概念。SDS又叫简单动态字符串,是Redis构建的用来表示字符串的一种数据结构,它在Redis底层中实际上保存的是byte数组。
由于Redis为SDS提供的API都是二进制安全的(在传输数据时,保证二进制数据不被篡改、破译,就算被攻击,也能够及时检测出来。由于二进制数据实际上存放在byte数组中,程序不会对数据做任何的限制、过滤,也即数据在写入的时候是什么样子的,那么在读取的时候就会是什么样子。有些特殊的数据类型会以某些特殊字符做分隔或者终止符号,比如\0),因此字符串类型的value中可以存储任何种类的数据,比如jpg图片、音频、视频、压缩文件或者序列化后的对象。
此外,Redis中一个key-value中,字符串类型的value部分最多保存512MB的数据。
数据结构: Map<String, String>
字符串数据类型所涉及到的操作就是最简单的set和get,做简单的key/value缓存。
set board JD
get board JD
输出: “JD”
2.2 哈希
value部分相当于Map,可以再次保存若干键值对,没有数据容量的限制。
数据结构: Map<String, Map<String, String>>
hash一般用于存储结构化的数据,比如一个对象(前提是这个对象没有嵌套别的对象)给缓存在redis里,然后在每次读写缓存时,就可以操作缓存里的某个hash字段。
hset person name zhangsan
hset person age 26
hset person id 1
hget person
2.3 链表
value部分相当于List,有存储顺序,底层使用链表实现。相当于一个key对应多个数据,数据可以重复。
数据结构: Map<String, List<String>>
rpush: 从右向左添加元素
lpush: 从左向右添加元素
rpop: 从右向左弹出元素
lpop: 从左向右弹出元素
rpush mylist 1 2
rpush mylist 3
lpush mylist 4 5
lpush mylist 6
rpop mylist
输出: 3
lpop mylist
输出: 6
lrange mylist 0 -1
输出:
正是因为拥有list这种有序的数据结构,所以有些时候,我们可以利用Redis做一个简单的消息队列。
2.4 集合
有些时候,我们为了对一批数据进行快速的去重,会使用基于jvm的hashSet,但如果你的某个系统部署在多台服务器上呢?此时就得使用Redis提供的set了。
value部分相当于Set,底层使用Hash算法保证数据的唯一性。相当于一个key对应多个数据,数据不能重复,且无序。基于set,我们可以做各种各样的操作,比如取两个集合的交集、并集、差集等等。比如查微博,查看两个人好友列表中相同的好友有哪些人,这就是在求交集。
数据结构: Map<String, Set<String>>
比如我们把两个大 V 的粉丝都放在两个 set 中,对两个 set 做交集。
#-------操作一个set-------
# 添加元素
sadd mySet 1
# 查看全部元素
smembers mySet
# 判断是否包含某个值
sismember mySet 3
# 删除某个/些元素
srem mySet 1
srem mySet 2 4
# 查看元素个数
scard mySet
# 随机删除一个元素
spop mySet
#-------操作多个set-------
# 将一个set的元素移动到另外一个set
smove yourSet mySet 2
# 求两set的交集
sinter yourSet mySet
# 求两set的并集
sunion yourSet mySet
# 求在yourSet中而不在mySet中的元素
sdiff yourSet mySet
2.5 有序集合
value部分相当于有序的set,既可以去重,还能排序。写入数据时需要给定一个分数,Redis会自动根据分数来排序。
数据结构: Map<String, TreeSet<String>>
zadd myzset 85 zhangsan
zadd myzset 72 lisi
zadd myzset 96 wangwu
zadd myzset 63 zhaoliu
默认正序排序,从0开始。
zrank myzset zhaoliu 输出: 0
zrank myzset wangwu 输出: 3
zrevrange myzset 0 2
输出:
三. 常用命令
3.1 通用命令
3.1.1 删除数据
删除key对应的key-value数据
语法:
del key
案例:
127.0.0.1:6379> del age
(integer) 1
127.0.0.1:6379> keys *
1) "name"
3.1.2 查询key数据
查看所有redis节点中已存在的key值
语法:
keys key
案例:
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> keys na*
1) "name"
3.1.3 设置数据的有效期
设置数据的有效期。redis中保存的数据可以设置有效期,在有效期满后,自动删除。
注意:
- 只能对已存在的key设置有效期,否则会报错: (error) ERR value is not an integer or out of range
- 如果在exipre之前,执行了save,那么Redis只会删除内存中对应的数据(逻辑删除,deleted标记成已删除)。当再一次执行save操作时,才会清空dump.rdb中对应的数据。
语法:
expire key seconds
案例:
127.0.0.1:6379> expire salary 2
(integer) 1
3.1.4 查看数据的有效期
查看指定数据剩余的有效时长。可能返回的数据如下:
- 永久保存: -1
- 无数据: -2
- 有效时长: 正数,代表剩余有效时长(单位: 秒)
语法:
ttl key
案例:
127.0.0.1:6379> set ooo 10000
OK
127.0.0.1:6379> expire ooo 500
(integer) 1
127.0.0.1:6379> ttl ooo
(integer) 494
127.0.0.1:6379> ttl ooo
(integer) 491
3.1.5 删除有效时长
删除数据原先设置的有效时长,换句话说,就是使数据永久保存。
语法:
persist key
案例:
127.0.0.1:6379> ttl ooo
(integer) 267
127.0.0.1:6379> persist ooo
(integer) 1
127.0.0.1:6379> ttl ooo
(integer) -1
3.1.6 刷新当前数据库
清空当前数据库中所有的数据,逻辑删除(真正的物理的删除需要等到下次save操作)。
语法:
flushdb
案例:
27.0.0.1:6379> flushdb 0
(error) ERR syntax error
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> save
OK
3.1.7 刷新所有数据库
语法:
flushall
案例:
127.0.0.1:6379> flushall
OK
3.1.8 选择数据库
选择指定编号的数据库
语法:
select num
案例:
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]>
小技巧: 可以通过观察接在url和端口后方的数组下标来判断当前选择是哪个数据库,比如案例中127.0.0.1:6379[1],则当前数据库是db1。默认情况下,db0会写成127.0.0.1:6379。
3.1.9 查看Redis信息
查看Redis的特征信息
语法:
info
案例:
127.0.0.1:6379[1]> info
# Server
redis_version:5.0.8
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:ab93e113dc3141c
redis_mode:standalone
... 省略
3.1.10 数据自增1
将key对应的value值自增1并返回自增后的结果。如果value不是数字,则抛出错误,如果key不存在,则返回1,并且保存<key,1>键值对。
语法:
incr key
案例:
127.0.0.1:6379[1]> get age
"26"
127.0.0.1:6379[1]> incr age
(integer) 27
127.0.0.1:6379[1]> set address wuhan
OK
127.0.0.1:6379[1]> incr address
(error) ERR value is not an integer or out of range
127.0.0.1:6379[1]> incr ppppp
(integer) 1
127.0.0.1:6379[1]> get ppppp
"1"
3.1.11 数据自减1
将key对应的value值自减1并返回自减后的结果。如果value不是数字,则抛出错误,如果key不存在,则返回-1,并保存<key,-1>键值对。
语法:
decr key
案例:
127.0.0.1:6379[1]> get age
"27"
127.0.0.1:6379[1]> decr age
(integer) 26
127.0.0.1:6379[1]> decr address
(error) ERR value is not an integer or out of range
127.0.0.1:6379[1]> decr abcdef
(integer) -1
127.0.0.1:6379[1]> get abcdef
"-1"
3.1.12 自增对应步长的数据
将key对应的value值自增step,并返回自增后的结果。如果value不是数字,则抛出错误,如果key不存在,则返回step,并且保存<key,step>键值对。step可以为负整数,0,正整数。
语法:
incrby key step
案例:
127.0.0.1:6379[1]> get age
"26"
127.0.0.1:6379[1]> incrby age 10
(integer) 36
127.0.0.1:6379[1]> incrby address 10
(error) ERR value is not an integer or out of range
127.0.0.1:6379[1]> incrby incrabc 15
(integer) 15
127.0.0.1:6379[1]> get incrabc
"15"
3.1.13 自减对应步长的数据
将key对应的value值自减step,并返回自减后的结果。如果value不是数字,则抛出错误,如果key不存在,则返回step,并且保存<key,step>键值对。step可以为负整数,0,正整数。
语法:
decrby key step
案例:
127.0.0.1:6379[1]> get age
"36"
127.0.0.1:6379[1]> decrby age 5
(integer) 31
127.0.0.1:6379[1]> decrby address 10
(error) ERR value is not an integer or out of range
127.0.0.1:6379> decrby decrabc 6
(integer) -6
3.1.14 浮点数数据自增自减
前面说的自增自减都是建立在整数(integer)的基础上,如果value值是一个浮点类型,想要自增自减就需要incrbyfloat了。step可以为负数、正数和0。
语法:
incrbyfloat key step
案例:
127.0.0.1:6379> set salary 28500.59
OK
127.0.0.1:6379> incrbyfloat salary -500.59
"28000"
3.1.15 检查key是否存在
判断当前Redis数据库中是否包含指定key数据,多个待检查的key通过空格隔开。指令执行后,会返回满足条件的数据的数量。
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists name age
(integer) 2
3.1.16 查看当前处于几号数据库之中
Redis显示的没有提供这种查询api,但我们可以直接通过观察命令行左侧的数字来判断当前位于几号数据库之中。
默认位于0号数据库,不会有任何额外的数字,如图:
如果位于其它数据库,则可以观察数字,如图:
3.2 字符串数据访问命令
3.2.1 单一新增
单一新增使用set命令,要求必须传递两个字符串参数。若字符串参数内有空格,则需要使用双引号,界定key和value的范围。
语法:
set key value
案例:
127.0.0.1:6379> set brand Ralph Lauren
(error) ERR syntax error
127.0.0.1:6379> set brand "Ralph Lauren"
OK
3.2.2 单一修改
Redis中没有单纯的修改命令,set命令同时兼顾了新增和修改两个功能。若key存在,则对value进行更新,若key不存在,则新增数据。
3.2.3 单一查询
单一查询使用get命令, 要求必须传递一个参数key。若key中有空格,则需要使用双引号界定key和value的范围。如果key没有对应的数据,则返回nil。
语法:
get key
案例:
127.0.0.1:6379> get salary
"28000"
127.0.0.1:6379> get nonexist
(nil)
3.2.4 批量新增
批量新增使用mset命令,所谓的mset,实际上就是multi set的简称。要求参数必须成对出现,传递的参数必须包含成对的数据。如果数据中有空格,则需要使用双引号界定key和value的范围。
语法:
mset key1 value1 key2 value2 key3 value3
案例:
127.0.0.1:6379> mset color purple temperature 15℃ weather sunny
OK
127.0.0.1:6379> get color
"purple"
127.0.0.1:6379> get temperature
"15\xe2\x84\x83"
127.0.0.1:6379> get weather
"sunny"
3.2.5 批量更新
使用批量新增命令
3.2.6 批量查询
批量查询使用mget命令,所谓的mget,实际上就是multi get的简称。
语法:
mget key1 key2 key3
案例:
127.0.0.1:6379> mget color weather
1) "purple"
2) "sunny"
3.3 哈希数据访问命令
Redis中的哈希数据结构实际上是Map<String, Map<String,String>> 通常把第一个String称为key,第二个String称为field, 第三个String称为value。Redis规定,在Hash数据结构中,只能为key设置有效时长,不能为field设置有效时长。
3.3.1 单一新增
单一新增使用hset命令,需要3个参数(key,field,value),如果任意一个参数内部有空格,则需要使用双引号界定边界。修改和新增操作一致,如果key和field都相同,则新的value覆盖旧的value。
语法:
hset key field value
案例:
127.0.0.1:6379> hset "month salary" xiaoming 25000
(integer) 1
127.0.0.1:6379> type "month salary"
hash
3.3.2 单一查询
单一查询使用hget命令,根据给定的key和field,查询value的值。
语法:
hget key field
案例:
127.0.0.1:6379> hget "month salary" xiaoming
"25000"
3.3.3 单一删除
使用hdel命令删除hash数据当中的一个field-value键值对,使用del命令删除key对应的所有hash值(所有键值对)。
语法:
hdel key field
del key
案例:
127.0.0.1:6379> hdel "month salary" xiaoming
(integer) 1
127.0.0.1:6379> del "month salary"
(integer) 0
3.3.4 批量新增
使用hmset命令(hash multi的简称),只支持对同一个key进行批量新增,需要的参数是一个key和若干个成对出现的field-value数据对。如果任意一个参数内部有空格,则需要使用双引号界定边界。
语法:
hmset key field1 value1 field2 value2
案例:
127.0.0.1:6379> hmset "month salary" name1 value1 name2 value2
OK
3.3.5 批量查询
批量查询使用hmget命令,需要查询的field可以接多个,通过空格隔开。
语法:
hmget key field1 field2
案例:
127.0.0.1:6379> hmget "month salary" name1 name2
1) "value1"
2) "value2"
3.3.6 批量删除
批量删除与单一删除一样,都使用hmget,只不过需要删除的field可以接多个,通过空格隔开。
语法:
hdel key field1 field2
案例:
127.0.0.1:6379> hdel "month salary" name1 name2
(integer) 2
3.3.7 查询所有的fields
查看一个key对应的hash数据中所有的field
语法:
hkeys key
案例:
127.0.0.1:6379> hkeys "month salary"
1) "xiaoming"
127.0.0.1:6379> hmset "month salary" name3 value3 name4 value4
OK
127.0.0.1:6379> hkeys "month salary"
1) "xiaoming"
2) "name3"
3) "name4"
3.3.8 查询所有的values
查看一个key对应的hash数据中所有的values
语法:
hvals key
案例:
127.0.0.1:6379> hvals "month salary"
1) "25000"
2) "value3"
3) "value4"
3.3.9 查询所有的fields-values
查看一个key对应的hash数据中所有的field-value数据对
语法:
hgetall key
案例:
127.0.0.1:6379> hgetall "month salary"
1) "xiaoming"
2) "25000"
3) "name3"
4) "value3"
5) "name4"
6) "value4"
3.3.10 检查field是否存在
语法:
hexists key field
案例:
127.0.0.1:6379> hexists "month salary" "xiaoming"
(integer) 1
127.0.0.1:6379> hexists "month salary" "xiaomingppppp"
(integer) 0
3.3.11 查询hash数据中的field-value数据对数量
语法:
hlen key
案例:
127.0.0.1:6379> hlen "month salary"
(integer) 3