1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| #redis.conf
设置显示行号
:set nu
搜索 /daemonize
把daemonize no 的no改为yes
#(该配置为是否让redis作为服务(守护进程)在后台启动)
搜索 /protected-mode
把protected-mode yes 改为no
#(该配置为resis的安全模式,当他开启就会禁止别人访问redis,如操作redis的工具)
搜索 /bind 127.0.0.1 -::1
注释掉bind 127.0.0.1 -::1
#(该配置生效时表示只有本机能访问redis,这显然是不行的,注释掉它)
搜索requirepass foobared
把改行的注释取消掉 并把 foobared 改成自己的密码
(该配置为设置自己的redis登录密码)
搜索 /port 6379
把端口号修改成自己需要的端口。
|
服务启动/结束#
1
2
3
4
5
6
7
8
9
10
11
12
13
| #使用我们修改好的 redis.conf 配置文件启动服务!
redis-server /opt/redis-7.0.0/redis/redis.conf
#查看redis服务是否启动
ps -aux | grep redis | grep -v grep
#使用我们修改过的 密码 以及 端口号 登录客户端!
redis-cli -a 你的密码 -p 你的端口
#在Redis命令行中:输入shutdown退出(quit退出服务)
#在Redis命令行外:
redis-cli -a 你的密码 -p 你的端口(可填多个端口) shutdown
|
常用命令#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| help @?
# 查询帮助,比较有用
set k v
#设置一个String类型的数据k 值为v
get k
#获取k?的值
keys *
#查询所有key
exists k
#k是否存在,返回1表示存在
type k
#查询数据类型
del k
#删除指定key
unlink k
#异步删除,对于大数据的删除,使用异步防止阻塞
ttl k
#数据是否过期,返回-1表示永不过期,-2表示已过期。数据在默认情况下永不过期
expire k S
#设置k在s秒后过期(过期会删除该值)
move k index
#将k移动到下标为index的数据库中
select index
#切换到下标为index的数据库
#(redis中我们默认处于0号数据库)
dbsize
#统计数据库中key的数量
flushdb
#清空当前数据库(谨慎使用!)
flushall
#清空所有数据库(谨慎使用!)
|
十大数据类型#
String(字符串)#
- String是redis中最基本的数据类型,一个key对应1个value
- redis中的String是二进制安全的(支持序列化),这意味着我们可以将二进制存储的文件存入其中,比如:一张图片。
- redis中单个String的最大容量为521M
基础命令#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
| set命令中的可选参数分别有
get EX PX EXAT PXNX NX XX KEEPTTL
GET用法
set k1 jack GET
#它会把k1赋值为jack,但同时返回k1之前的值
EX用法
set k1 jack EX 10
#设置k1值为jack,但在10秒后过期(expire)
PX用法
set k1 jack PX 100
#设置k1值为jack,但在100毫秒后过期
EXAT用法
set k1 jack EXAT 1685775704
#设置k1值为jack,但在指定的秒级unix时间戳后过期
set K1 JACK PXAT 1685775857409
#设置k1值为jack,但在指定的毫秒级unix时间戳后过期
NX用法
set k1 jack NX
#当k1不存在时设置k1的值为jack
XX用法
set k1 tom XX
#当k1存在时才将k1的值设为tom
KEEPTTL用法
set k1 jack KEEPTTL
#当我们在设置给key赋值时偶然或遇到这样的业务需求,只改变key的值,但不要改变之前设置的过期时间。
#这时我们就需要用到KEEPTTL,要知道普通的set赋值会改变value的过期时间(默认为-1:即永不过期)
mset k1 v1 k2 v2 k3 v3
#设置多个值(m multi多个)
#注意 mset k1 v1 k2 v2 k3 v3 NX 当其中一个不满足条件则全部失败
mget k1 k2 k3 k4
#获取多个值
getrange k1 1 2
#截取k1,从下标1-下标2
getrange k1 0 -1
#获取全长
setrange k1 1 omomom
#定位替换,从下标1开始替换字符串
INCR k2
#递增k2(k2必须为数字!)
DECR K2
#递减k2(k2必须为数字!)
INCRBY k2 2
#每次递增步长为2
DECRBY k2
#每次递减步长为2
strlen k1
#获取k1的长度
append k1
#往k1尾部插入字符
getset k1 v1
#与set k1 v1 get一样,它会把k1赋值为v1,但同时返回k1之前的值
|
分布式锁#
1
2
3
4
5
| setnx k1 jack
#当k1不存在设置值为jack
setex k1 jack
#当k1存在设置值为jack
|
set k1 jack nx与setnx k1 jack区别
set k1 locked nx (查看与上锁)
服务1 查看是否上锁(同时其他的服务也在查看)
服务1 上锁过程中, 服务2 认为没有上锁,发生线程安全问题
setnx (单个原子操作)
服务1 开始查看(其他服务等待)
(查看锁与上锁属于不可分割的原子操作,其他服务只能等待)
list(列表)#
- redis中的list指的是简单的字符串列表
- 你可以插入一个字符串到头部或者尾部,数据结构其实就是双向链表
- 它最多包含 2 ^ 32 - 1个元素,超过40亿个
基础命令#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| lpush list1 1 2 3 4
#从左侧 依次 将12345插入到list1中
lrange list1 0 -1
#从左侧开始遍历整个list1
#5 4 3 2 1
rpush list2 1 2 3 4 5
#从右侧 依次 将12345插入到list1中
lrange list2 0 5
#从左侧开始遍历list2 从0-5
#1 2 3 4 5
lpop list1
#从左侧弹出一个元素
rpop list1
#从右侧弹出一个元素
lindex list1 n
#找出从左侧数下标为n的元素
lrem list1 n tom
#从左侧开始数,删除n个tom
ltrem list1 n m
#裁剪list1,只保留从下标n到下标m(会改变原list!)
rpoplpush list1 list2
#把list1元素尾部取出,插入list2头部(它是原子操作)
lset list1 n tom 把list1中下标为n的元素替换为tom
linsert list1 before/after tom jack
#在list1中,给元素tom的前面或者后面添加一个jack
#注意:list中的元素是可以重复的!当有多个tom时,它只会在第一个tom的前面添加,而不是在每个tom前面都添加
|
Hash (哈希表)#
- 以一个filed(字段 String) 一个value(值)来存储数据的映射表。与Java中的hashmap数据结构极为相似:
- map< String,map< String,object > >
- 单个hash最多包含 2 ^ 32 - 1个键值对,超过40亿个键值对
基础命令#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| hset user name tom age 12 hobby sing
#设置一个key为 user 的hash 它的值是一个个键值对
#分别是 name tom ,age 12 ,hobby sing
hget user name
#获取hash表user的name属性
hgetall user
#获取hash表user的n所有属性
hlen user
#获取hash表user的键值对个数
hexists user name
#hash表user有没有name属性
hkeys user
#查询user中所有键值对中的key
hvals user
#查询user中所有键值对中的value
hincreby user age n
#给user的年龄字段增加n
#(注意,他没有hdecrby递减 但是我们可以增加 -1,相当于递减了)
hincrbyfloat user age 0.5
#float类型增加
hsetnx user hobby coding
#当的hobby字段不存在时赋值为coding (原子操作)
|
set(集合)#
- redis中的set是存储String的无序集合,要求存储的String数据数据唯一无重复
- 底层其实由hash来实现的,集合对象的编码类型可以是inset或者hashtable
- 它的查询复杂度为 O1,做法与java一样,value全部置空,比对key就完了
- 单个set最多包含 2 ^ 32 - 1个成员,超过40亿个成员
基础命令#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| sadd set1 1 2 3 4 5 5 5 5
#添加将1 2 3 4 5 添加到 set1中,set会自动去重
smember set1
#遍历set1所有 成员(member)
sismember set1 x
#x是否是set1的成员
srem set1 x
#删除set1中的x元素
scard set1
#获取set1的长度
srandmember set1
#随机显示一个set1中的元素
spop set1 n
#随机弹出(删除)n个set1中的元素
smove set1 set2 x
#将x从set1中移动到set2中
sdiff set1 set2
#获得set1中有而set2中没有的元素,差集
union set1 set2
#获得set1与set2合并后的set,并集
sinter set1 set2
获得set1与set2中共有的数据交集
sintercard 2 set1 set2
#获得set1与set2这2个set交集的长度
#注意,必须指定要获得交集长度的set个数 (2)
|
zset(sorted set)#
- 它是一个有序的无重复set 可以有序的存储String,它通过给每一个value指定一个double类型的score分数来设定value该放置的位置
- zset的分数可以重复,但成员唯一
- 查询,插入,删除复杂度都是O1
- 可存储 2 ^ 32 - 1个成员
基础命令#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| zadd zset1 10 tom 20 jack 30 lisa 40 monika
#给zset1中添加 tom jack lisa monika,他们关联的score分别是10 20 30 40
zrange zset1 0 -1 withscores
#遍历zset1 withscores 带上score
zrevrange zset1 0 -1
#反向遍历zset1
zrangebyscore zset1 0 100
#获取zset1的score,不能填0 -1,要填分数的范围,0 100的意思是获取的score要大于等于0 小于等于100的
zrangebyscore zset1 (0 100
#括号表示不包含0
zrangebyscore zset1 0 100 limt 0 1
#limt 0 1 表示只要两个数,类似于分页
zrem zset1 tom
#删除tom 它无法通过分数获取指定的元素,score只用来排序
zcard zset1
#获取zset1的长度
zincrby zset1 3 tom
#tom加3分
zcount zset1 0 20
#统计从0分 到 20分之间有几个元素
zmpop 2 zset1 zset2 min/max count 1
#对zset1和zset2进行元素删除 最小或最大 删除数量为1(他会先删除zset1),删除完后删除
#zset2,如果指定的count数大于zset的总长度,则删除当前zset的全部,不会影响下一个zset
zrank zset1 tom
#获得zset1中tom的下标
zrevrank zset1 tom
#获得逆序中tom的下标
|
GEO (地理位置信息)#
- 用来存储经纬度,可以对存储的经纬信息进行操作,底层还是zset
- 存储位置信息
- 删除位置信息
- 计算两个位置信息之间的距离
基础命令#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| geoadd city 116.403968 39.915094 "天安门" 116.403414 39.924091 "故宫" 116.746579 40.482509 "长城"
#将经纬度与名称存入city中
zrange city 0 -1
#遍历city (zset数据类型不能使用参数 0 -1直接获取全部,而它可以)
#出现乱码需要退出登录,重新登录时在登录指令后添加 --raw ,此时zrange指令不再乱码。
geopos city 天安门
#返回定位点的坐标
geohash city 天安门
#//wx4g0f6f300
#工作中面对大量的定位置,一个经度,一个维度一般使用geohash
#将定位信息转换成base32编码使用。(这并不影响存入的数据本身,只是获取数据的编码)
geodist city 天安门 故宫 m / km / ft(英尺) / mi(英里)
#获取在city中天门到故宫两地之间的距离,不输入单位则默认是米
georadius city 经度 纬度 100 km withdist withcoord withhash count 10 desc
#withdist 带上距离
#withcoord 带上经纬度坐标
#withhash 带上base32编码
#count 数量
#desc 倒序
#经纬度指定点为圆心,半径100km以内的最多10个坐标,并带上坐标的经纬度,跟指定坐标之间的距离,带上编码,然后倒序排列。
georadiusbymamber city 天安门 100 km
#以天安门为圆心半径一百千米的地点名称
|
HyperLogLog (基数统计)#
- 基数就是指不重复的数据,比如人口基数,指的就是每个单独存在的个体
- HyperLogLog是用来做基数统计的算法,它的优点在于统计大数量的基数时,运算速度会非常快。
- 对于2 ^ 64 -1 个数据的统计,只需要占用12k的内存,要知道一般的集合,它存储的数据量越大,进行基数统计时所需要占用的内存就越大。
- 它不像常用的数据类型一样,存储基数本身,也无法返回指定的基数。
基础命令#
1
2
3
4
5
6
7
8
9
10
11
12
13
| pfadd date01 tom jack jack lisa lisa lisa
#定义了一个名为date01的HyperLogLog
#在这一天tom访问网站一次,jack两次,lisa三次
#注意命名以非数字开头
pfcount date01
#统计访问人数,结果为3
pfadd date02 tom jack jack lisa lisa lisa monika
#我们统计2号的访问用户基数
pfmerge result date01 date02
#2号相比1号访问用户增加了monika,上述命令统计两天访问的用户并通过result的新HyperLogLog中
|
bitmap(位图)#
- 是用来存储二进制位的bit数组,当我们只需要记录简单的Y/N状态时,他就派上大用场了,比如,打卡上班,统计调研分析。
基础命令#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| setbit k1 1 1
#将k1 下标为1的位置设为1
get k1
#我们使用获取字符串的方式来获取k1,返回的是它所指定的ascii码所对应的值
#如1 表示的就是2进制 01000000 (众所周知二进制0开头) 对应的就是字符 @
getbit k1 n
#我们通过getbit来获取下标n上面的数字 下标必须指定
strleng k1
#我们获取的是该bitmap占用的字节,8位一字节。比如0100 0000 1所占用的就是2字节
bitcount k1
#获取k1中一共有多少个1(用于统计上班签到)
|
bitfield(位域)#
Stream redis流#
数据持久化#
Redis的持久化在配置文件redis.conf中记录
RDB(redis database)#
Redis按照一定的时间间隔(触发条件)执行对数据进行备份。称之为时间点快照。文件名为dump.rdb
SAVE指令
实际生产中禁止使用该指令,因为该指令会阻塞Redis!致使Redis不服务而去进行持久化操作!
BGSAVE指令
生产中我们会使用该指令立即持久化操作,它会另起一个Redis的子线程去异步的执行持久化操作,不会影响Redis正常提供服务!
LASTSAVE指令
该指令可以查看最后一次备份的执行时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| 修改配置文件 vim /opt/redis-7.0.0/redis.conf
更改RDB备份存储位置
搜索 dir ./ 按n切换下一个
将 ./ 换成你想保存的目录
更改RDB备份文件名
搜索 dbfilename dump.rdb
把 dump.rdb 改成 redis端口号 + dump.rdb
更改RDB备份频率
搜索 save 3600 1 300 100 60 10000
在3600秒(1小时)内有1个键发生了改变
在300秒(5分钟)内10个键发生改变
在60秒内10000个键发生改变
另起一行写入规则
如 save 5 1
禁用RDB备份
将配置文件redis.conf中的save 改成 save ""
注意,配置修改后重启redis服务才会生效!
1 shutdown结束服务
2 redis-server +配置文件路径 重启Redis
|
AOF (append only file)#
Redis记录数据库中所执行过的所有写操作,在服务器重启时重播这些操作重写数据库原始数据,命令的记录格式与 Redis 协议本身相同。
always
在写命令执行后立即记录该条命令(频繁的磁盘IO会降低Redis性能)
everysec 默认
每秒写入1次,看似频率高,其实性能影响不大,最多丢失1秒内执行的写入,是最优选。
no
由操作系统控制的持久化。每条命令执行后,只是将命令存入AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写入磁盘
。(宕机会丢数据!)
1
2
3
4
5
6
7
8
9
| 修改配置文件 vim /opt/redis-7.0.0/redis.conf
开启AOF
搜索 appendonly no
将 no 改为yes
更改策略
搜索 appendfsync everysec
更改everysec
|
No persistence#
不进行持久化操作
有时我们不需要Redis做备份,而是以更高的性能单纯的作为缓存数据库存在
即便禁用了aof与rdb,我们仍然可以使用bgrewirteaof或bgsave指令生成相应的备份
RDB+AOF#
组合使用AOF和RDB进行持久化,当Redis同时开启了RDB与AOF,则Redis在开启服务时会优先选择AOF来恢复数据, 如果不存在,则会去寻找RDB文件恢复,如果都没有则不恢复直接启动
配置
1
| aof-use-rdb-preamble yes 开启混合模式!
|