什么是redis?主要作用?
redis(remote dictionary server)远程字典服务:是一个开源的使用ANSI C语言编写,支持网络、可基于内存可持久化的日志型、key-value数据库,并提供多种语言的api
redis的数据存在内存中,读写速度非常快,每秒可以超过10万次读写操作。因此广泛用于缓存,另外,redis也经常用来做分布式锁。
redis的基本数据类型
type key
:获取key的类型
-
string
- 是redis最基础的数据结构类型,可以存储图片或者序列化的对象,值最大存储为512M
- 应用场景:共享session、计数器、限流等
- 内部编码:int/embstr(<=39字节字符串)/raw(>39字节字符串)
-
格式 功能 set key value 将key-value缓存到Redis中 get key 从redis中获取key对应的value del key 从Redis中删除key incr key 将key对应的value加1 decr key 将key对应的value减1 setex key seconds value 将key-value缓存到Redis中并设置过期时间 setnx key value 将key-value缓存到redis中,若key存在,不做任何操作 ttl key 查看key的存活命时间 incrby key increment 给key对应值加increment mset k1 v1 k2 v2… 批量添加key-value对到redis中 mget k1 k2 批量根据key获取value append key value 在key对应的value中拼接value setrange key offset value 从offset位置开始将key对应的value,替换为指定value
-
hash
- hash类型是指v(值)本身又是一个键值对结构
- 内部编码:ziplist、hashtable
- 应用场景:缓存用户信息等
- 注意:若开发使用hgetall,哈希元素比较多的话,可能导致redis阻塞,可以使用hscan.而如果只是获取部分field,建议使用hmget
-
命令 功能 hset key field value 将field value缓存到redis的hash中,键值为key hget key field 从key对应hash中获取filed字段 hexists key field 判断key对应hash中是否存在field字段 hincrby key field increment 给key对应hash中的field字段+increment hdel key field 删除key对应hash中的field字段 hkeys key 获取key对应hash中的所有field hvals key 获取key对应hash中的所有filed的val hgetall key 获取key对应hash中所有的filed和value
-
list
- 用来存储多个有序的字符串,一个列表最多可以存储2^32-1个元素
- 内部编码:ziplist、linkedlist
- 应用场景:消息队列,收藏文章列表
- lpush+lpop=stack
- lpush+rpop=queue
- lpsh+ltrim=capped collection(有序集合)
- lpush+brpop=message queue(消息队列)
-
命令 功能 rpush key value 从右边向key集合中添加value lrange key start end 从左边开始获取key集合,从start开始到end结束 lpush key value 从左边向key集合添加value lpop key 弹出key集合最左边的数据 rpop key 弹出key集合最右边的数据 llen key 获取key集合的长度 linsert key BEFORE|AFTER pivot element 操作key集合,在privot之前/后添加element lset key index value 操作key集合,更新索引index位置的值为value lrem key count value 操作key集合,删除count个value值 ltrim key start end 操作key集合,截取start到end的列表值 lindex key index 操作key集合,获取index位置的值 brpop key seconds 延迟seconds弹出
-
set
- 用来保存多个的字符串元素,但是不允许重复元素
- 内部编码:intset、hashtable
- 注意点:smembers和lrange、hgetall都属于比较重的命令,若元素过多存在阻塞redis的可能性,可以使用sscan完成
- 应用场景:社交需求、生成随机数抽奖
-
命令 格式 sadd key members 向key集合中添加member元素 smembers key 遍历key集合中所有元素 srem key members 删除key集合中member元素 spop key count 从key集合中随机弹出count个元素 sdiff key1 key2 返回key1中特有的元素(差集) sidiffstore dest key1 key2 将差集缓存到dest中 sinter key1 key2 返回key之间的交集 sinterstore dest key1 key2 将交集缓存到dest中 sunion key1 key2 返回并集 sunionstore dest key1 key2 将并集缓存到dest中 smove source dest member 将source集合中member元素移动到dest集合 sismember key member 判断member是否存在于key集合中 srandmember key count 随机获取key集合中count个元素
-
zset
- 已排序的字符串集合,同时元素不能重复
- 内部编码:ziplist、skiplist
- 应用场景:排行榜、点赞
-
命令 格式 zadd key score member 向key集合中添加member元素,分数为score zincrby key increment member 向key集合中member元素score+increment zrange key start end [withscores] 将key集合中元素升序排序,显示分数 zrevrange key start end [withscores] 将key集合中元素倒序排序,显示分数 zrank key member 返回member在key集合中的正序排名 zrevrank key member 返回member在key集合中的倒序排名 zcard key 返回key集合元素的个数 zrangebysocre key min max withscores 按[min,max)分数范围正序返回key集合中的元素,显示分数 zrevrangebyscore key min max withscores 按[min,max)分数范围倒序返回key集合中的元素,显示分数 zrem key member 删除key集合中的member元素以及分数 zremrangebyscore key min max withscores 按[min,max)分数范围删除key集合中的元素 zremrangebyrank key start stop 删除key集合中按照正序排列,索引在[min,max)分数范围内的元素 zcount key min max 按[min,max)分数范围统计key集合中的元素个数
-
全局命令
命令 | 功能 |
---|---|
keys pattern | 按照pattern模式匹配key |
exists key | 判断key是否存在 |
expire key seconds | 设置key的过期时间 |
persist key | 取消key的过期时间 |
select index | 切换数据库,默认是第0个,共有0~15个 |
move key db | 从当前库将key移动到指定DB库 |
randomkey | 随机返回一个key |
rename key newkey | 将key改名为newkey |
echo message | 打印message信息 |
dbsize | 查询key个数 |
info | 查看redis数据库信息 |
config get * | 查看redis所有配置信息 |
flushdb | 清空当前数据库 |
flushall | 清空所有数据库 |
-
value设计
-
一般模式
-
是否需要排序,需要使用zset
-
缓存的数据是多个值还是单个值
-
多个值:是否允许重复,允许使用list,不允许使用set
-
单个值:简单值选择string,对象值选择hash
-
-
-
取巧模式
- 除去需要排序的需求使用zset外,其余都使用string
-
-
key设计
-
唯一性,常用缓存数据的主键作为key
-
可读性,目的是为了确保见名知意
-
普通单值,如
userinfo:id1
-
表名:主键名:主键值:列名,如
userinfo:id:1:name
-
-
灵活性
-
时效性,redis key一定要设置过期时间
-
不设置过期时间,key就为永久有效,会一直占用内存,当key的数量过多时,就容易达到服务器内存上限,导致宕机,所以一般要设置过期时间
-
key的时效性设置,必须根据业务场景进行评估,设置合理的有效时间
-
-
### 事务
-
单个redis命令执行是原子性的,但是redis没有在事务上添加任何维持原子性的机制,所以redis的事务并不是原子性的
-
redis事务可以看为一组打包的批量执行脚本,因为其不具有原子性,所以中间的某条指令失败并不会导致之前的操作回滚,也不会导致后续操作失败
-
redis事务可以一次执行多个命令
-
批量操作在发送exec命令前被放入queue中缓存
-
接收到exec指令之后进入事务执行,事务中任意指令出错,不会导致其他指令失败及回滚
-
在事务执行过程中,其他客户端提交的命令请求不会插入到该事务执行的命令队列中
-
持久化机制
-
快照方式(RDB,redis database)
-
将内存数据以快照的方式写入到二进制文件中,默认为dump.rdb
-
手动触发
-
使用save命令:会阻塞当前redis服务器,直到rdb过程完成,若内存数据过多,会造成长时间阻塞,影响其他命令的使用
-
使用bgsave:redis进程执行fork指令创建子进程,由子进程实现rdb持久化
-
-
自动触发
-
使用save相关配置,
save m n
,表示m秒内数据集存在n次修改会自动触发bgsave命令save 1000 19
,表示1000s内若超过19个key被修改则发起快照保存
-
-
优点
-
rdb快照文件是一个紧凑压缩的二进制文件,常使用于备份、全量复制等场景
-
redis加载rdb恢复数据远远快于aof的方式
-
-
缺点
-
无法做到实时持久化,每次bgsave都需要fork一个子进程,频繁执行有时间成本
-
rdb快照容易一起兼容性问题
-
-
-
文件追加方式(AOF,append only file),不建议单独使用
-
是一种独立日志的方式记录每次写命令,重启时在重新执行aof文件中命令达到回复数据的目的,解决了数据持久化的实时性问题
-
默认未开启,需要在配置文件中将
appendonly no
改为appendonly yes
-
文件同步策略
-
appendfsync always
:收到命令就立即写到磁盘,效率慢,但是可以保证完全的持久化 -
appendfsync everysec
:每秒写入磁盘一次 -
appendfsync no
:完全依赖操作系统,一般同步周期是30s
-
-
优点
-
数据安全性更高,配置合理最多损失1s的数据量
-
在不小心执行flushall命令,也可以通过aof方式恢复(删除最后一个命令即可)
-
当aof变的太大时,redis能够在后台自动重写aof
-
-
缺点
-
相同数据量来说,aof文件体积大于rdb文件
-
aof比rdb持久化效率慢
-
-
-
混合持久化方式(4.0之后)
- 在写入的时候,先将当前的数据以rdb的方式写入文件开头,再将后续的操作命令以aof的格式存入文件,就是以rdb做全量备份,aof作为增量备份,来提高备份的效率。这样不仅能保证redis重启时的速度,又可以防止数据丢失的风险
内存淘汰机制
maxmemory参数设置内存使用上限 ,0代表不设置上限
-
LRU:最近最少使用,从数据库中删除最近最少访问的数据。可以理解为从数据库中删除最近最少访问的数据,长期不用的数据,意味着再次访问的概率也就很小了,淘汰的数据为最长时间未被使用的数据,仅与时间相关
-
LFU:最不经常使用,淘汰一段时间内,使用次数最少的数据,与频次和时间相关
-
TTL:Redis中设置了过期时间的数据,当内存不够时,并且该数据即将过期,就会直接清除该数据
-
随机淘汰
-
淘汰策略(通过maxmemory-policy配置)
-
volatile-lru:找出已经设置过期时间的数据集,将最近最少使用的数据淘汰掉
-
volatile-ttl:找出已经设置过期时间的数据集,将即将过期的数据淘汰掉
-
volatile-random:找出已经设置过期时间的数据集,随机淘汰数据
-
volatile-lfu:找出已经设置过期时间的数据集,将一段时间内,使用次数最少的数据淘汰掉
-
allkeys-lru:与1类似,只不过为全体数据
-
allkeys-lfu:与4类似,只不过为全体数据
-
allkeys-random:与3类似,只不过为全体数据
-
no-enviction:什么都不做,直接报错,通知内存不足,可以保证数据不丢失(默认)
-