一、Redis 简介
Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库,类似于 Java 中的 Map<key, value>。
Redis 与其他 key - value 缓存产品有以下特点:
(1)
Redis 数据库中所有数据都存储在内存中,由于内存的读写速度远快于硬盘,因此 Redis 在性能上对比其他基于硬盘存储的数据库有非常明显的优势。
(2)Redis 支持数据的持久化,可以将内存中的数据异步写入到磁盘中,重启的时候可以再次加载进行使用。
(3)Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
(4)Redis支持数据的备份,即 master-slave 模式的数据备份。
Redis 的特点:
(1)速度快
1)
纯内存操作
2)单线程操作,避免了频繁的上下文切换
3)采用了非阻塞 I/O 多路复用机制(2)原子性
Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来。(3)键值对的数据结构服务器
5种常用数据结构:String、hash、 list、 set、 zSet
(4)简单稳定
单线程,协议简单
(5)持久化
将内存数据写入磁盘
(6)主从复制
实现多个相同数据的 redis 副本(7)高可用和分布式集群
哨兵机制实现高可用,保证 redis 节点故障发现和自动转移(8)客户端语言多
java、php、python、c、c++、node.js等
使用 Redis 的缺点
(1)缓存和数据库双写一致性问题
(2)缓存雪崩问题
(3)缓存击穿问题
(4)缓存的并发竞争问题
Redis 应用场景
1、
缓存数据库合理使用缓存加快数据访问速度,降低关系型数据库压力
2、
排行榜按照热度排名,按照发布时间排行,
主要用到列表和有序集合3、
计数器应用视频网站播放数,网站浏览数
4、社交网络
赞、踩、粉丝、下拉刷新
5、
消息队列发布和订阅
6、其他场景。。
二、redis 配置、启动、操作、关闭

停止 redis 服务:redis-cli shutdown
注意:
a、
关闭时,断开连接,持久化文件生成,相对安全。
b、使用 kill 方式关闭进程时,不会做持久化,还会造成缓冲区非法关闭,会导致数据丢失。
c、 关闭前持久化文件,登录 redis-cli 客户端,再 shutdown nosave|save 。
三、Redis 的数据结构
1、String
字符串类型:实际上可
以是字符串(包括 XML JSON),还有数字(整形 浮点数),二进制(图片 音频 视频),最大不能超过 512MB。
示例
// 1、设值指令
set age 22 ex 10 // 10秒后过期, ttl age 查询剩余时间
setnx name test // 不存在键name时,返回1设置为成功,返回0失败
// 2、获取指令
get age // 存在返回age的值
// 3、删除指令
del age // 删除age,返回1
// 4、批量操作
mset name wanglei age 22 // 批量set
mget name age // 批量get
// 5、计数
incr age // 必须为证书自加1,非整数返回错误,无age键从0开始自增返回1
decr age // 整数age减1
incrby age 2 // 整数age + 2
decrby age 2 // 整数age - 2
incrbyfloat score 1.1 // 浮点型 score + 1.1
// 5、追加、长度、截取字符串
set name hello;
append name zhangsan; // 追加字符串,变成 hellozhangsan
set zhangsan "张三";
strlen zhangsan // 字符串长度,结果为6,每个中文占3个字节
set name helloworld;
getrange name 0 2 // 截取字符串,返回hel
补充
1)EX seconds : 将键的过期时间设置为 seconds 秒。 执行 SET key value EX seconds 的效果等同于执行 SETEX key seconds value 。
2)PX milliseconds : 将键的过期时间设置为 milliseconds 毫秒。 执行 SET key value PX milliseconds 的效果等同于执行 PSETEX key milliseconds value 。
3)NX : 只在键不存在时, 才对键进行设置操作。 执行 SET key value NX 的效果等同于执行 SETNX key value 。
4)XX : 只在键已经存在时, 才对键进行设置操作。
2、Hash
Redis hash 是一个键值对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,类似 Java 里面的 Map<String,Object>,最大存储 512M。
示例:
hset user:1 name wanglei // 设置指令,成功返回1,失败返回0
hget user:1 name // 读取指令,返回wanglei
hlen user:1 // 计算field个数,返回2
hdel user:1 name // 删除field,返回删除个数
hmset user:2 name wanglei age 23 sex boy // 批量设置,返回OK
hmget user:2 name age sex // 批量读取,返回三行:wanglei 23 boy
// 判断field是否存在:
hexists user:2 name // 若存在返回1,不存在返回0
// 获取所有field:
hkeys user:2 // 返回name age sex三个field
// 获取user:2所有value:
hvals user:2 // wanglei 23 boy
// 获取user:2所有field与value:
hgetall user:2
// 整型增加1:
hincrby user:2 age 1 // age+1
// 浮点型增加2:
hincrbyfloat user:2 age 2 // 浮点型加2
三种方式存储user信息比较
1)原生
set user:1:name wanglei;
set user:1:age 22;
set user:1:sex boy;
优点:简单直观,每个键对应一个值。
缺点:键数过多,占用内存多,用户信息过于分散,不用于生产环境。
2)将对象序列化存入 redis。
set user:1 serialize(userInfo);
优点:编程简单,若使用序列化合理内存使用率高。
缺点:序列化与反序列化有一定开销,更新属性时需要把 userInfo 全取出来进行反序列化,更新后再序列化到 redis。
3)使用 hash 类型。
hmset user:1 name wanglei age 23 sex boy
优点:简单直观,使用合理可减少内存空间消耗。
缺点:要控制 ziplist 与 hashtable 两种编码转换,且 hashtable 会消耗更多内存 serialize(userInfo)。
3、List
用来
存储多个有序的字符串,一个列表可以存的最大元素:2的23次方减1 。
因为有序,可以通过索引下标获取元素或某个范围内的元素列表,列表元素可以重复。
特点
单键多值,底层实际是个双向链表,对两端的操作性能很高,通过索引下标操作中间的节点性能会较差。
示例
rpush testlist c b a // 从右向左插入c b a, 返回3
lrange testlist 0 -1 // 从左往右获取列表元素,返回c b a,0 -1为索引下标
lpush testlist 1 2 3 // 从左向右插入1 2 3, 返回6
linsert testlist before 1 0 // 在1之前插入0,返回7,after为之后,使用lrange testlist 0 -1 查看,返回结果为3 2 0 1 c b a
lindex testlist -1 // 返回最右末尾a,-2返回b
llen testlist // 当前列表长度,返回7
lpop testlist // 把最左边的第一个元素删除,返回3
rpop testlist // 把最右边的第一个元素删除,返回a
4、 Set
用户标签,社交,查询有共同兴趣爱好的人,智能推荐。
保存多元素,与列表不一样的是
不允许有重复元素,且集合是无序,一个集合最多可存2的32次方减1个元素,除了支持增删改查,还支持集合交集、并集、差集。
底层其实是一个 value 为 null 的哈希表。
示例
exists user // 检查user键值是否存在,存在返回1,不存在返回0
sadd user a b c // 向user插入3个元素,返回3
sadd user a b // 若再加入相同的元素,则重复无效,返回0
smembers user // 获取user的所有元素,返回结果无序
srem user a // 返回1,删除a元素
scard user // 返回2,计算元素个数
// 场景,求共同爱好语言
// 使用方式,给用户添加标签,或者给标签添加用户。
// 给用户添加标签
sadd user:1:fav java js vue python
sadd user:2:fav vue python node.js
sadd user:3:fav c c++ c#
// 求共同爱好,即求交集
sinter user:1:fav user:2:fav // 返回vue、python
sinter user:1:fav user:2:fav user:3:fav // 返回(empty list or set)
5、zSet
Redis
有序集合 zset与普通集合 set 非常相似,是一个没有重复元素的字符串集合。不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复的。
zset 底层使用了两个数据结构:1)hash:hash 的作用就是关联元素 value 和权重 score,保障元素 value 的唯一性,可以通过元素 value 找到相应的 score 值。
2)跳跃表:跳跃表的目的在于给元素 value 排序,根据 score 的范围获取元素列表。
常用于排行榜,如视频网站需要对用户上传视频做排行榜,或点赞数与集合有联系,不能有重复的成员。
示例
zadd user:zan 200 wanglei 120 zhangsan 140 lisi // 增加元素,返回3
zrange user:zan 0 -1 withscores // 查询元素,返回点赞数和成员名称,返回张三 120 lisi 140 wanglei 200
zrank user:zan lisi // 返回名次,返回1,排名为0,1,2
zrevrank user:zan wanglei // 反向排名,点赞越多排名越前,返回0
zadd test:1 nx 100 wanglei // 键test:1必须不存在,主要用于添加
zadd test:1 xx incr 200 wanglei // 键test:1必须存在,主要用于修改,此时300
zadd test:1 xx ch incr -299 wanglei // 返回操作结果1,300-29=1
zcard test:1 // 计算成员个数,返回1
list、set、zSet 比较

Redis6 的新数据类型
(1)Bitmaps
Redis提供了Bitmaps这个“数据类型”可以实现对位的操作:
(1)Bitmaps 本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它
可以对字符串的位进行操作。(2)Bitmaps 单独提供了一套命令, 所以在 Redis 中使用 Bitmaps 和使用字符串的方法不太相同。 可以把 Bitmaps 想象成一个以位为单位的数组, 数组的每个单元只能存储 0 和 1, 数组的下标在 Bitmaps 中叫做偏移量。
(2)HyperLogLog
Redis HyperLogLog 是用来做
基数统计的算法。
HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数,这与元素越多耗费内存就越多的集合形成鲜明对比。
(3)Geospatial
redis 基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度 Hash 等常见操作。
四、redis 数据库管理

默认支持16个数据库;可以理解为一个命名空间。跟关系型数据库不一样的点:
redis
不支持自定义数据库名词。
每个数据库不能单独设置授权。
每个数据库之间并不是完全隔离的。 可以通过 flushall 命令清空 redis 实例面的所有数据库中的数据。
通过 select dbid 去选择不同的数据库命名空间,dbid 的取值范围默认是 0 -15。
全局命令
(1)查看所有键: keys * (可以查询所有key,也可以模糊搜索,如 keys user* ,但是线上不推荐使用。)
(2)键总数:dbsize (如果存在大量键,线上不建议使用。)
(3)检查键是否存在:exists key (存在返回 1,不存在返回 0。)
(4) 设置键过期时间: expire username 20 (设置 username 20秒过期,ttl username 查看剩余时间。)
(5)查看数据类型:type username (返回string,不存在返回none。)
五、Redis 持久化机制
redis 是一个支持持久化的内存数据库,也就是说 redis 需要经常将内存中的数据同步到磁盘来保证持久化,持久化可以避免因进程退出而造成数据丢失。
1、RDB 持久化方式
RDB 持久化把当前进程数据生成快照(.rdb)文件保存到硬盘的过程,有手动触发和自动触发。
手动触发有 save 和 bgsave 两命令 :
1) save命令:阻塞当前redis,直到RDB持久化过程完成为止,若内存实例比较大会造成长时间阻塞,线上环境不建议用它。
2)bgsave命令:redis 进程执行 fork 操作创建子进程,由子线程完成持久化,阻塞时间很短(微秒级),是 save 的优化,在执行 redis-cli shutdown 关闭 redis 服务时,如果没有开启 AOF 持久化,自动执行 bgsave。
RDB 如何恢复
redis.conf 文件配置了指定目录,重启 redis 恢复数据。
RDB 持久化优缺点
优点:
压缩后的二进制文,适用于备份、全量复制,用于灾难恢复。
加载 RDB 恢复数据远快于 AOF 方式。缺点:
无法做到实时持久化,每次都要创建子进程,频繁操作成本过高。
保存后的二进制文件,存在老版本不兼容新版本 rdb 文件的问题。
2、AOF 持久化
针对 RDB 不适合实时持久化,redis 提供了 AOF 持久化方式来解决。
开启:redis.conf 设置:appendonly yes (默认不开启,为no)
默认文件名:appendfilename “appendonly.aof”
AOF 持久化流程
1)
所有的写入命令(set hset)会 append 追加到 aof_buf 缓冲区中。
2)AOF 缓冲区向硬盘做 sync 同步。
3)随着 AOF 文件越来越大,需定期对 AOF 文件 rewrite 重写,达到压缩。
4)当 redis 服务重启,可 load 加载 AOF 文件进行恢复。
AOP如何恢复
redis.conf 文件配置了指定目录,重启 redis 恢复数据。
AOP 配置详解
appendonly yes // 启用aof持久化方式
# appendfsync always // 每收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec // 每秒强制写入磁盘一次,性能和持久化方面做了折中,推荐
no-appendfsync-on-rewrite yes // 正在导出rdb快照的过程中,要不要停止同步aof
auto-aof-rewrite-percentage 100 // aof文件大小比起上次重写时的大小,增长率100%时,重写
auto-aof-rewrite-min-size 64mb // aof文件,至少超过64M时,重写
Redis 重启时加载 AOF 和 RDB 的顺序
(1)
当 AOF 和 RDB 文件同时存在时,优先加载 AOF。
(2)若关闭了 AOF,加载 RDB 文件。
(3)加载 AOF/RDB 成功,redis 重启成功。
(4)AOF/RDB 存在错误,启动失败打印错误信息。
本文详细介绍了Redis作为内存数据库的特性、配置、操作、数据结构(如String、Hash、List、Set、ZSet),以及其在缓存、排行榜、计数器等场景的应用。涵盖了RDB和AOF持久化机制,以及Redis的管理和恢复策略。








587

被折叠的 条评论
为什么被折叠?



