Kv for Redis

2019-12-04  本文已影响0人  Secret_Sun

Redis 是一个高性能的key-value数据库。主要用Redis实现缓存数据的存储,可以设置过期时间。对于一些高频读写、临时存储的数据特别适合,并非 MySQL 的一种可靠性存储。

少量数据存储,高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景。

使用场景:

取最新N个数据的操作

比如典型的取你网站的最新文章,我们可以将最新的5000条评论的ID放在Redis的List集合中,并将超出集合部分从数据库获取。

排行榜应用,取TOP N操作

这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序, 这时候就需要我们的sorted set出马了,将你要排序的值设置成sorted set的score, 将具体的数据设置成相应的value,每次只需要执行一条ZADD命令即可。

需要精准设定过期时间的应用

比如你可以把上面说到的sorted set的score值设置成过期时间的时间戳,那么就可以简单地通过过期时间排序, 定时清除过期数据了,不仅是清除Redis中的过期数据,你完全可以把Redis里这个过期时间当成是对数据库中数据的索引, 用Redis来找出哪些数据需要过期删除,然后再精准地从数据库中删除相应的记录。

计数器应用

Redis的命令都是原子性的,你可以轻松地利用INCR,DECR命令来构建计数器系统。

实现点赞、签到、like等功能

uniq操作,获取某段时间所有数据排重值

这个使用Redis的set数据结构最合适了,只需要不断地将数据往set中扔就行了,set意为集合,所以会自动排重。

构建队列系统 「解耦」

使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。

数据一致性缓存场景

Redis的Transactions提供的并不是严格的ACID的事务(比如一串用EXEC提交执行的命令,在执行中服务器宕机,那么会有一部分命令执行了,剩下的没执行),但是这个Transactions还是提供了基本的命令打包执行的功能(在服务器不出问题的情况下,可以保证一连串的命令是顺序在一起执行的,中间有会有其它客户端命令插进来执行)。Redis还提供了一个Watch功能,你可以对一个key进行 Watch,然后再执行Transactions,在这过程中,如果这个Watched的值进行了修改,那么这个Transactions会发现并拒绝执行。

缓存

最常用,性能优于Memcached(被libevent拖慢),数据结构更多样化。

缓存雪崩和缓存穿透

缓存雪崩是什么?

假设有如下一个系统,高峰期请求为5000次/秒,4000次走了缓存,只有1000次落到了数据库上,数据库每秒1000的并发是一个正常的指标,完全可以正常工作,但如果缓存宕机了,每秒5000次的请求会全部落到数据库上,数据库立马就死掉了,因为数据库一秒最多抗2000个请求,如果DBA重启数据库,立马又会被新的请求打死了,这就是缓存雪崩。「程序设计需要考虑后端 MySQL & Redis 配合下能峰值抵抗多少的问题」

缓存穿透是什么?

假如客户端每秒发送5000个请求,其中4000个为黑客的恶意攻击,即在数据库中也查不到。总而言之,缓存雪崩就是缓存失效,请求全部全部打到数据库,数据库瞬间被打死。缓存穿透就是查询了一个一定不存在的数据,并且从存储层查不到的数据没有写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。「程序设计时需要考虑冷热数据的问题」

合理使用

合理使用集合类

使用 sortedset、set、list、hash 等集合类的 O(N) 操作时要评估当前元素个数的规模以及将来的增长规模,对于短期就可能变为大集合的 key,要预估 O(N) 操作的元素数量,避免全量操作,可以使用 HSCAN、SSCAN、ZSCAN 进行渐进操作。集合元素数量过大在使用过程中会影响 redis 的实际性能,元素个数建议尽量不要超过 5000,元素数量过大可考虑拆分成多个 key 进行处理。

合理设置过期时间

如果 key 没有设置超时时间,会导致一直占用内存。对于可以预估使用生命周期的 key 应当设置合理的过期时间或在最后一次操作时进行清理,避免垃圾数据残留 redis。

合理利用批操作命令

在 redis 使用过程中,要正视网络往返时间,合理利用批量操作命令,减少通讯时延和 redis 访问频次。redis 为了减少大量小数据 CMD 操作的网络通讯时间开销 RTT (Round Trip Time),支持多种批操作技术:MSET/HMSET 等都支持一次输入多个 key,LPUSH/RPUSH/SADD 等命令都支持一次输入多个 value, 也要注意每次操作数量不要过多, 建议控制在 500 个以内;PipeLining 模式 可以一次输入多个指令。redis 提供一个 pipeline 的管道操作模式,将多个指令汇总到队列中批量执行,可以减少 tcp 交互产生的时间,一般情况下能够有 10%~30% 不等的性能提升;更快的是 Lua Script 模式,还可以包含逻辑。redis 内嵌了 lua 解析器,可以执行 lua 脚本,脚本可以通过 eval 等命令直接执行,也可以使用 script load 等方式上传到服务器端的 script cache 中重复使用。「当然最好是别用 Lua,类似 MySQL 老用存储过程也不合适」

减少不必要的请求

redis 的所有请求对于不存在的 key 都会有输出返回,合理利用返回值处理,避免不必要的请求,提升业务吞吐量。

避免 value 设置过大

String 类型尽量控制在 5KB 以内。虽然 redis 对单个 key 可以缓存的对象长度能够支持的很大,但是实际使用场合一定要合理拆分过大的缓存项,1k 基本是 redis 性能的一个拐点。当缓存项超过 10k、100k、1m 性能下降会特别明显。关于吞吐量与数据大小的关系可见下面官方网站提供的示意图。在局域网环境下只要传输的包不超过一个 MTU(以太网下大约 1500 bytes),那么对于 10、100、1000 bytes 不同包大小的处理吞吐能力实际结果差不多。


借鉴了大量文档之后浓缩的一些日常体会,希望能给到大家帮助。

上一篇下一篇

猜你喜欢

热点阅读