Redis基础
1 概要
1.1 简介
Redis
是使用ANSI C
语言编写、支持网络、基于内存、可持久化的日志型、Key-Value
数据库。
- 安装在磁盘
- 数据存储在内存
1.2 特性
- 速度快
- 键值对格式存储
- 功能丰富
- 简单稳定
- 持久化
- 主从复制
- 高可用分布式转移
- 客户端语言多
1.3 应用场景
- 缓存数据库
- 排行耪
- 计数器
- 社交网络
- 消息队列
1.4 启动、配置
1.5 全局指令
指令 | 说明 | 备注 |
---|---|---|
keys * |
查看所有键 | |
dbsize |
键总数 | 如果存在大量键,线上禁止使用 |
exists key |
检查键是否存在 | |
del key |
删除键 | |
expire key seconds |
设置键过期 | |
ttl key |
查看过期时间 | |
type key |
查看键数据类型 | 不存在返回none |
1.6 数据库管理
select 0
选择数据库 默认有16个数据库flushdb
只删除当前db
flushall
删除所有db
2 5种数据结构
key | value | 指令 | |
---|---|---|---|
String | name | set name zhangch |
|
Hash | user:1 | hmset user:1 name zhangch age 18 |
|
List | testKey1 | lpush testKey1 a b c d |
|
Set | testKey2 | zadd testKey2 a b c |
|
ZSet | testKey3 | zadd testKey3 2 a 4 b 5 c |
2.1 字符串String类型
字符串类型,实际上可以是json,xml,数字,二进制(图片,音频,视频),大小限制512M
命令:set key value
例 set name zhangch
ex
设置过期时间 秒px
设置过期时间 毫秒nx
仅当key
不存在时设置 Not eXistxx
仅当key
存在时设置
批量设置mset k1 v1 k2 v2
mset name zhangch age 26 sex male
批量获取同理mget k1 k2 k3
mget name age sex
计数
incr key
整数自增1
,非整数报错,无key
从0
自增到1
decr key
同上,减法incrby key num
加给定的值decrby key num
同上incrbyfloat key num
加给定的值,用于浮点数
追加append key value
追加strlen key
获取长度getrange str beginIndex endIndex
截取字符串长度 从0
开始,包含尾
2.2 哈希Hash类型
1.命令
有用户表如下:
使用String
类型来存储,使用如下命令。
哈希类型的数据结构维护了一个String类型的field-value的映射表,适合存储对象。
hset key filed value
设值,成功返回1,失败返回0hget key filed
取值,返回valuehdel key
删值,返回成功的个数hdel key field...
删值,返回成功的个数hlen key
返回映射个数hmset key f1 v1 f2 v2
批量设值hmget key f1 f2
批量取值hexists key field
判断field是否存在hkeys key
获取所有fieldhvalues key
获取所有valuehgetall key
获取所有field-valuehincrby key field num
增加hincrbyfloat key field num
增加浮点数
2.内部编码ziplist
<压缩列表>和hashtable
<哈希表>redis
初始创建hash
表,有序集合,链表时, 存储结构采用一种ziplist
的存储结构, 这种结构内存排列更紧密, 能提高访存性能。
- 当
field
个数少且没有大的value
时,内部编码为ziplist
如:hmset user:3 name zhangch age 27;
object encoding user:3 //返回ziplist
- 当
value
大于64
字节,内部编码由ziplist
变成hashtable
2.3 列表List类型
用来存储多个有序的字符串,一个列表最多存2的32次方减一个元素。
因为有序,所以可以使用下标来获取元素,也可获取范围内的元素。
命令:
-
lpush user:1:love sing jumb rap basketball
从列表左边开始逐一放入元素
列表元素为basketball rap jumb sing
-
rpush key value
同上,从右侧插入 -
linsert key before oldValue newValue
在old前面插入new -
linsert key after oldValue newValue
在old后面插入new -
llen key
返回列表长度 -
lindex key index
从左侧获取下标index的元素 -
lrange key beginIndex endIndex
获取列表指定的索引 index:[0,n-1] -
lpop key
删除左侧第一个元素,并返回它 -
rpop key
删除右侧第一个元素,并返回它
2.4 集合Set
与列表List类似,元素不重复,且无序,用于用户标签、社交、查询有共同爱好的人、智能推荐等。最大存储元素2的32次方减1,支持增删改查,对集合求交集、差集、并集。
如上图,有两个key,分别为用户1和用户2的爱好。
命令:exists key
检查key
是否存在sadd key value1 value2 ....
加入元素,无序,若加入相同元素无效srem key value1 value2 ...
删除元素,返回成功的个数smembers key
返回所有元素,无序scard key
返回元素个数
sinter key1 key2
求交集sdiff key1 key2
求差集sunion key1 key2
求并集sinterstore key3 key1 key2
将key1
与key2
的value
相交,结果存储到key3
,sdiff
,sunion
同理
2.5 有序集合ZSet
带有分数的set
,可用于排行榜,点赞数,不能有重复的成员。
指令
-
key [NX|XX] [CH] [INCR] score member [score member ...]
-
zadd key score1 member1 score2 member2 ...
添加 -
zadd key score3 member3 nx
用于添加,不存在key才添加 -
zadd key score1 member1 xx
用于修改 xx为存在时才添加 -
zrange key beginIndex endIndex withscores
查询指定index,随分数一并 -
zrank key member
返回排名 -
zrevrank key member
逆向返回排名 -
XX: 仅仅更新存在的成员,不添加新成员。
-
NX: 不更新存在的成员。只添加新成员。
-
CH: 修改返回值为发生变化的成员总数,原始是返回新添加成员的总数 (CH 是 changed 的意思)。更改的元素是新添加的成员,已经存在的成员更新分数。 所以在命令中指定的成员有相同的分数将不被计算在内。注:在通常情况下,ZADD返回值只计算新添加成员的数量。
-
INCR: 当ZADD指定这个选项时,成员的操作就等同ZINCRBY命令,对成员的分数进行递增操作。
3 使用场景
key
的设计原则,简短明了,节约内存,一般以业务功能为主。
如:user:1:order 标识用户1的订单
3.1 String应用
-
结构体或对象的存储
1.set user:1 value
value
可以为xml
或json
2.mset user:1:name zhangch user:1:age 27
3.mget user:1:name user:1:age
-
计数功能
incr article:001
文章编号001get article:001
-
各类场景下(单机或分布式)标识号
incr serialNo 1000
-
集群环境下的
Session
共享
使用spring session
与redis
完成session
共享
3.2 Set应用~用户标签、喜好、社交
3.2.1 用户标签
-
给用户添加标签:
sadd user:1:fav basball fball pq
sadd user:2:fav basball fball
… -
给标签添加用户
sadd basball:users user:1 user:2
sadd fball:users user:1 user:2
… -
计算出两个人相同的兴趣:
sinter user:1:fav user2:fav
3.2.2 微信抽奖活动
-
活动001 ,member为参加用户id
sadd act:001 1 2 3 4
四个用户参加了这个活动 -
随机抽取2位
srandmember act:001 2
或spop act:001 2
-
查看活动参与用户
smembers act:001
3.2.3 朋友圈点赞
-
朋友圈消息
ID 008
,点赞统计sadd thumb:008 user:001 user:002 user:003
三个用户点了这个消息的赞 -
取消点赞
srem thumb:008 user:001
用户001取消了这个赞 -
统计点赞个数
scard thumb:008
-
统计点赞的人
smembers thumb:008
3.3 Hash应用
- 购物车
用户001
购物车:cart
hmset cart:001 prod:01 1 prod:02 1 prod:03 1
1.全选功能-获取所有该用户的所有购物车商品hgetall cart:001
2.商品数量-购物车图标上要显示购物车里商品的总数hvals cart:001
3.删除-要能移除购物车里某个商品hdel cart:001 prod:03
4.增加或减少某个商品的数量hincrby cart:001 prod:01 2
3.4 List应用
-
实现栈
lpush + lpop
-
实现队列
lpush + rpop
-
实现阻塞队列
lpush + brpop
-
微信订阅号信息
用户微信id
为001
,关注了CSDN
,男子别输在说话上,如何设计?
1.男子别输在说话上发布一条消息id 101
lpush message:001 101
2.CSDN发布一条消息id 102
lpush message:001 102
3.查询001
用户的微信消息列表lrange message:001 0 -1
3.5 Zset应用
排行榜,热门话题,热搜等
-
日期作为key
zadd 20191221 10 topic:1 12 topic:2 14 topic:3
-
点击
topic:1
zincrby 20191221 1 topic:1
-
统计热搜前10
zrevrange 20191221 0 9
-
统计近三天的话题量
zunionstore topic:3d 3 20191221 20191222 20191223
3.6 Hash与List应用~订单场景
订单 --> 订单详情
用户 --> 订单
-
有三个订单 ,订单id,订单价格,下单时间
hmset order:1 oderId 1 price 10 time 2019-12-10
hmset order:2 oderId 2 price 12 time 2019-12-11
hmset order:3 oderId 3 price 13 time 2019-12-12
-
用户1有多个订单
lpush user:1:order order:1 order:2 order:3 -
用户1又下单了
hmset order:3 oderId 4 price 34 time 2019-12-14
lpush user:1:order order:4
-
查询用户1的订单记录
List orderKeyList = lrange user:1:order 0 -1 //查询用户1所有订单的key
orderKeyList.forEach(k->{
orderInfo = hmget k
})
4 使用String Hash 序列化三种方式存储用户信息比较
1.String
方式set user:1:name zhangch
set user:1:age 23
优:简单直观,每个键对应一个值
缺:键数过多,占用内存多,用户信息分散,不用于生成环境
2.将用户序列化后存入set user:1 (UserObject)
优:编程简单,内存使用率高
缺:序列化反序列化存在开销
3.Hash
方式hset user:1 name zhangch age 26
优:简单直观,使用合理,可减少内存空间消耗
缺:需要控制ziplist
和hashtable
两种编码转换,且hashtable
消耗更多内存
5 持久化机制
Redis
是一个支持持久化的数据库,可将内存中的数据同步到磁盘中来保证数据持久化,避免进程退出造成的数据丢失。
5.1 RDB
将当前进程数据生成快照.rdb
文件保存到硬盘中,有手动触发(save
、bgsave
)和自动触发。
-
save
阻塞redis
,直到rdb
持久化完成,若内存实例较大会造成长时间阻塞,线上不建议使用。 -
bgsave
redis
进行fork
一个子线程,由子线程完成持久化操作,阻塞时间很短,是save
操作的优化,在redis-cli
shutdown
关闭redis
服务时,如果没有开启AOF
持久化,会自动执行bgsave
。 -
操作
1.设置RDB文件保存路径:config set dir /usr/local
2.bgsave
将dump.rdb
保存到/usr/local
下
3.恢复 :将rdb
文件放到redis安装目录与redis.conf同级目录,重启redis即可。 -
优点
加载RDB恢复数据速度快于AOF
方式。RDB
文件适用于备份、全量复制,用于灾难恢复。 -
缺点
无法实时持久化,每次操作需要fock
子进程,操作成本过高。
保存过后的RDB
文件,可能存在新老版本不兼容问题。
5.2 AOF
针对RDB
方式不适合实时持久化,Redis
提供AOF
的方式来解决。redis.config
设置 appendonly yes
(默认不开启,为no
)
默认文件名 appendfilename "appendonly.aof"
-
持久化流程:
1.所有的写入操作,会append追加到aof_buf缓冲区
2.aof_buf缓冲区向硬盘做sync同步
3.随着AOF文件越来越大,需要定期对AOF文件rewrite重写,达到压缩
4.当redis重启,可load加载AOF文件进行恢复 -
恢复过程
1.appendonly
设置为yes
2.将AOF
文件放到指定位置
3.重启redis
,redis
会自动加载appendonly.aof
文件
-
AOF
配置
启用AOF
持久化方式appendonly yes
每收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用appendfsync always
每秒强制写入磁盘一次,性能和持久化方面做了折中,推荐appendfsync everysec
正在导出rdb快照的过程中,要不要停止同步AOF
no-appendfsync-on-rewrite yes
AOF
文件大小比起上次重写时的大小,增长率100%
时,重写auto-aof-rewrite-percentage 100
AOF
文件,至少超过64M
时,重写auto-aof-rewrite-min-size 64mb
-
5.3 RDB 与AOF 恢复顺序
6 分布式锁
todo
来源:CSDN
作者:popcivilar
链接:https://blog.csdn.net/popcivilar/article/details/103646192