写点什么

Redis 高级特性

用户头像
QiyihaoLabs
关注
发布于: 5 小时前
Redis 高级特性

Redis 作为目前最流行的缓存服务器,几乎在各大互联网公司都得到了广泛的使用,本文会介绍 Redis 中一些重要的核心技术和高级特性,以及在项目中的应用场景以及最佳实战。

一、Redis 数据结构

1.1 基本数据结构



1.2 扩展数据结构

常见集合统计模式:

  • 聚合统计: 共同粉丝列表、新增粉丝列表

  • 二值统计: 元素取值只有 0 和 1,例如用户签到、打卡数据、登录状态

  • 排序统计:最新评论列表、排行榜(按时间和权重)

  • 基数统计: 统计一个集合中不重复的元素个数,例如网站 pv、uv

1.2.1 BitMap

以比特位为单位的数组,数组的每个单元只能存储 0 和 1,数组的下标在 Bitmap 中叫做偏移量

二值状态:

集合中的元素的值只有 0 和 1 两种,在签到打卡和用户是否登陆的场景中,只需记录签到(1)或 未签到(0),已登录(1)或未登陆(0)。 


适用场景

存储海量二值化数据,有效节省内存空间,比如登陆状态用一个 bit 位表示,一亿个用户也只占用 一亿 个 bit 位内存 ≈ (100000000 / 8/ 1024/1024)12 MB。

使用案例:

•SETBIT :SETBIT
Eg:用户89757在 2021 年 5 月 16 号打卡:SETBIT uid:sign:89757:202105 15 1
•GETBIT :GETBIT
Eg: 用户89757在 2021 年 5 月 16 号是否打卡:GETBIT uid:sign:89757:202105 15
•BITCOUNT: BITCOUNT
Eg: 统计该用户在 5 月份的打卡次数:BITCOUNT uid:sign:89757:202105
•BITPOS: BITPOS key bitValue [start]
返回数据表示 Bitmap 中第一个值为 bitValue 的 offset 位置
Eg:2021 年 5 月份首次打卡日期:BITPOS uid:sign:89757:202105 1
复制代码


性能比较:

假设网站有 1 亿用户,每天独立访问的用户有 5 千万,如果每天用集合 set 和 Bitmaps 分别存储活跃用户,占据内存空间如下:



可以看出,使用 Bitmap 能节省很多的内存空间,而且随着时间推移节省的内存效率越高

1.2.2 HyperLogLog: 基数统计

基数统计:

统计一个集合中不重复的元素

Hyperloglog:

基数算法,可以利用极小的内存空间完成独立总数的统计,数据集可以为 IP、Email、ID 等

适用场景:

网页 pv、uv、在线用户数统计,当存储海量集合元素时只需极小的存储空间,有效节省内存占用

常用操作:

• PFADD :PFADD element [elements…]
向hyperloglog添加元素
Eg: 用户在 2016年 3月 6 号访问网站:PFADD 20160306:unique:ids ‘uuid-1’ ‘uuid-2’ ‘uuid-3’
• PFCOUNT:PFCOUNT
计算一个hyperloglog中的独立总数(去重后)
Eg: 2016年 3月 6 号访问网站的用户数:PFCOUNT 20160306:unique:ids
• PFMERGE: PFMERGE destkey sourcekey [sourcekey…]
计算多个hyperloglog的并集并赋值给destkey
Eg: 2016年 3月 6 号和5号访问网站的用户数:
pfmerge 20160305_06:unique:ids 20160305:unique:ids 20160306:unique:ids
Pfcount 20160305_06:unique:ids
复制代码


性能比较:



可以看出,HyperLogLog 内存占用量小得惊人但是用如此小空间来估算如此巨大的数据,其中一定存在误差率。Redis 官方给出的数字是 0.81%的失误率

1.3 数据结构汇总



二、Redis 高级特性

2.1 Redis 瓶颈

Redis 为什么快?

  • 纯内存

  • 单线程

  • IO 多路复用

  • 高效的数据结构

Redis 性能瓶颈体现在哪?

  • 机器内存:受本机内存大小的限制

  • 网络带宽:

Redis 的客户端和服务端可能部署在不同的机器上。例如客户端在北京,Redis 服务端在上海,每次 RTT 耗时平均 13ms,严重拖累 redis 性能



如何解决?

2.2 Pipline: 一次性批量执行 Redis 命令

Pipline

它能将一组 Redis 命令进行组装,通过一次 RTT 传输给 Redis,再将这组 Redis 命令的执行结果按顺序 返回给客户端



没有使用 Pipeline 执行了 n 条命令,整个过程需要 n 次 RTT。



使用 Pipeline 执行了 n 次命令,整个过程需要 1 次 RTT。

性能比较



表给出了在不同网络环境下非 Pipeline 和 Pipeline 执行 10000 次 set 操作的效果,可以得出: • ·Pipeline 执行速度一般比逐条执行要快。 • ·客户端和服务端的网络延时越大,Pipeline 的效果越明显。

2.3 Redis 与 LUA

LUA 脚本优势:

  • 保证原子性,脚本在执行过程中不会插入其他命令

  • 帮助开发者定制自己的命令

  • LUA 可以将多条命令一次性打包,有效减少网络开销

使用场景:

  1. 限流脚本



  1. Redisson 分布式锁加锁、解锁脚本(保证原子性)

2.4 布隆过滤器

布隆过滤器由⼀个初值都为 0 的 bit 数组和 N 个哈希函数组成,可以⽤来快速判断某个数据是否存在。当我们想标记某个数据存在时(例如,数据已被写⼊数据库),布隆过滤器会通过三个操作完成标记:



⾸先,使⽤N 个哈希函数,分别计算这个数据的哈希值,得到 N 个哈希值。然后,我们把这 N 个哈希值对 bit 数组的⻓度取模,得到每个哈希值在数组中的对应位置。最后,我们把对应位置的 bit 位设置为 1,这就完成了在布隆过滤器中标记数据的操作。如果数据不存在(例如,数据库⾥没有写⼊数据),我们也就没有⽤布隆过滤器标记过数据,那么,bit 数组对应 bit 位的值仍然为 0。

判断数据是否存在?

•不存在的一定不存在,存在的不一定存在

布隆过滤器查询 key 是否存在时,跟 add 操作一样,会把这个 key 通过相同的多个 hash 函数进行运算,查看 对应的位置 是否 都 为 1,只要有一个位为 0,那么说明布隆过滤器中这个 key 不存在。如果这几个位置都是 1,并不能说明这个 key 一定存在,只能说极有可能存在,因为这些位置的 1 可能是因为其他的 key 存在导致的。

使用场景

• 大数据场景下判断是否存在

• 亿级数据场景下快速判断某个数据是否存在

• 解决缓存穿透

• 过滤无效请求,对不在数据库和缓存中的 key 快速过滤

• 爬虫/ 邮箱等系统的过滤

优缺点:

• 二进制组成的数组,占用内存极少,并且插入和查询速度都足够快

• 随着数据的增加,误判率会增加;无法判断数据是否一定存在;无法删除数据。

三、性能优化

这里直接贴出笔者总结的几张思维导图如下:

3.1 Redis 变慢原因



3.2 Redis 最佳实践



巨人的肩膀:

发布于: 5 小时前阅读数: 11
用户头像

QiyihaoLabs

关注

还未添加个人签名 2020.01.21 加入

还未添加个人简介

评论

发布
暂无评论
Redis 高级特性