相信不管是“熟悉”还是“精通” Redis 的盆友们,听到 Redis 的第一反应就是“快”吧,
至于为啥快,这里我就简单说一下,毕竟真要说这个的话几篇文章都够呛啊。
内存存储:Redis 将数据存储在内存中,因此能够实现快速的读写操作。相比于磁盘存储,内存存储的读写速度更快。
单线程模型:Redis 使用单线程模型,避免了多线程的上下文切换开销,简化了并发控制,使得 Redis 在处理请求时更加高效。
非阻塞 I/O:Redis 使用了非阻塞 I/O 模型,能够更好地处理大量并发连接,提高了系统的吞吐量。
数据结构丰富:Redis 提供了丰富的数据结构,如字符串、列表、哈希、集合、有序集合等,这些数据结构的操作都经过了优化,能够快速地执行各种操作。
当然随着 Redis 版本的不断更新,其对性能和一些其它的模块也随之进行了优化和新增,但总体上将Redis为啥快的点分成以上几个还是可行的,毕竟换汤不换药嘛(如有错误欢迎提出!).
说在前面
对我来说,别的可能都映像不深,但这个第一条,也就是在内存存储数据,这也是我们在刚接触到Redis听到最多的一类话术了,相信大家也都差不多。那我就不得不来一句经典的套话了“众所周知,Redis的访问速度快、使用性能高是因为它的数据都是存储在内存中的”。肿么样有没有很熟悉的感觉,是不是经常听到老师说。
OK,有关内存和磁盘访问的知识,大家可以自行搜索。回到开始的话题。
说到内存,就离不开资源利用率这个话题了,毕竟能省一点,谁不想省呢~,我是巴不得它能到100%,当然这时候服务器可能就挂了。从资源利用率上看,机器的内存资源消耗和磁盘消耗还是有很大的差别的,当然最主要的还是“钱”的差别,其它的速度、容量、持久性、存储方式等方面,有票子了直接加资源就行了啊,谁还搁着算着算哪的啊。<这只是调侃一下,后面几点在实际的业务场景中也是值得重视的板块,毕竟几个月前也有几个大厂中的一些业务模块业务某些原因出现了不可用的情况吗!>
当你的业务应用在Redis中存储数据很少时,可能内存资源的使用情况对我们的影响不怎么大。但随着业务的发展,你的业务存储在Redis中的数据就会越来越多。如果没有提前制定好内存优化策略,那么等业务开始增长时,Redis占用的内存也会开始膨张。所以,提前制定合理的内存优化策略,对于资源利用率的提升是很有必要的。(终于回到正题了。。)
实际场景
先列取以下几点,之后有会陆续补充:
- 控制 key 的长度
- 避免存储 bigkey
- 使用合适的数据类型
- 把 Redis 当成缓存,而不是数据库
- 设置内存上限和过期策略
- 存储前压缩数据
以下,开始展开来讲每个点的具体情况(简单实现,想深入学习可自行搜索相关资源)。
1.控制key的长度
简单粗暴且有效的方法。在实际开发场景中,如果数据量到达了百万级别的,如果 key 的长度过长或过于复杂,这也是一个不小的内存消耗,以下有几点优化key长度的方案:
使用较短的键名:尽量使用简短而且具有描述性的键名,避免过长的键名。这样可以减少每个键所占用的内存空间。
使用哈希结构:如果你需要存储大量的键值对,可以考虑将它们存储在哈希结构中。这样可以减少键名的重复,从而节省内存。
命名空间:通过给键名添加统一的前缀,可以将相关的键分组存储在一起。这样可以更好地组织数据,并且减少键名的长度。
2. 避免存储 bigkey
我们不能顾头不顾尾,key 都“上了”,value 不能不“冲了”啊。有时候我们图懒就把所有数据都存储在单个大型键中,这样随着数据的不断累积查询效果反而会适得其反,性能反而会下降。以下是几个避免bigkey的方法:
合理使用数据结构:根据实际需求选择合适的数据结构。例如,如果需要存储大量的元素,可以考虑使用列表或集合来分散数据,而不是将所有数据存储在单个大型键中。
分页处理数据:对于大型数据集,可以将数据进行分页处理,按需进行加载和卸载,而不是一次性将所有数据存储在单个键中。
压缩数据:对于大型字符串类型的值,可以考虑对数据进行压缩,以减少内存占用。
使用合适的数据存储方案:根据数据的特点,可以考虑将部分数据存储在其他存储系统中,如分布式文件系统或数据库,而不是全部存储在Redis中。
数据存储的建议:(参考大佬的)
String:大小控制在10KB以下
List/Hash/SetZSet:元素数量控制在10000以下
数据存储的建议:(搜的)
字符串(String):Redis的字符串类型可以存储的数据量最大,最大可达512MB。然而,为了保持较好的性能,建议将字符串类型的值控制在几十KB到几MB之间。
列表(List):Redis的列表类型可以存储多个元素,一般来说,建议单个列表的元素数量控制在几百至几千之间。
集合(Set):Redis的集合类型可以存储多个唯一的元素,建议单个集合的元素数量也控制在几百至几千之间。
哈希(Hash):Redis的哈希类型可以存储多个字段和值的映射关系,建议单个哈希的字段数量控制在几百至几千之间。
有序集合(Sorted Set):Redis的有序集合类型可以存储多个唯一的成员,并且每个成员都关联一个分数,建议单个有序集合的成员数量控制在几百至几千之间。
3. 选择合适的数据类型
这点从上面就可以看出来了,这里就不多说了,只说redis的几种常用数据类型对比:
字符串(String):适合存储单个数值、文本或者序列化的对象数据。例如,存储用户会话信息、缓存数据或者简单的计数器。
列表(List):适合存储有序的、可重复的数据集合。例如,存储消息队列、动态列表数据或者事件日志。
集合(Set):适合存储无序的、唯一的数据集合。例如,存储点赞用户、标签数据或者好友关系。
哈希(Hash):适合存储具有结构化的数据。例如,存储用户信息、对象属性或者配置信息。
有序集合(Sorted Set):适合存储有序的、唯一的数据集合,并且每个成员都关联一个分数。例如,存储排行榜、时间序列数据或者带权重的数据。
还有另一个可操作的点就是,在选择好用什么数据类型后,在其里存储什么样的数据,在Redis中一种数据类型可对应多种数据结构来实现。
具体的可看这篇文章,大佬讲的比我这个小卡拉米详细多了:Redis系列(一):深入了解Redis数据类型和底层数据结构-腾讯云开发者社区-腾讯云 (tencent.com)https://cloud.tencent.com/developer/article/2313606
4. 把 Redis 当成缓存,而不是数据库
见名知意,就是不要把redis当成一个存储数据的地方,它只负责当缓存,来优化我们的查询速度,毕竟内存资源不管是价格还是余量都是有得有“钞能力”的。这也就需要我们合理的使用内存资源,比如要及时把过期的数据删除掉或者在写入的时候就设置好过期时间。具体的操作需要通过实际场景来制定。
5. 设置内存上限和过期策略
在Redis中,选择合适的数据淘汰策略是非常重要的,特别是当内存空间有限时。选择合适的数据淘汰策略需要考虑你的应用程序的访问模式和数据访问频率。如果你的应用程序中有一些热门数据,那么LRU策略可能更适合;如果你的应用程序中的数据访问频率差异较大,那么LFU策略可能更适合。最终的选择取决于你对应用程序数据访问模式的了解以及对数据淘汰策略的需求。
几种淘汰策略:(具体的就不再介绍)
noeviction
:当内存不足以容纳新写入数据时,新写入操作会报错。
allkeys-lru
:移除最近最少使用的 key(LRU 算法)。
allkeys-lfu
:移除最少访问的 key(LFU 算法)。
volatile-lru
:在设置了过期时间的 key 中,移除最近最少使用的 key(LRU 算法)。
volatile-lfu
:在设置了过期时间的 key 中,移除最少访问的 key(LFU 算法)。
volatile-random
:在设置了过期时间的 key 中,随机移除 key。
volatile-ttl
:在设置了过期时间的 key 中,移除存活时间(TTL)最短的 key。
6. 存储前压缩数据
不太了解的一种方法,但又以下几点需要注意的地方:
压缩数据写入Redis的影响取决于多个因素,包括数据的压缩率、压缩和解压缩的性能、网络传输速度以及Redis服务器的负载等。压缩数据写入Redis可能会增加CPU的使用率,因为数据需要在写入和读取时进行压缩和解压缩操作。这可能会对Redis服务器的响应时间和吞吐量产生一定影响。
另一方面,压缩数据写入Redis可以减少网络传输的数据量,尤其是在数据量较大的情况下,可以降低网络传输的开销,从而提高整体性能。
为了准确评估压缩数据写入Redis对应用程序性能的影响,建议进行针对性的性能测试,并监控CPU利用率、网络传输速度、Redis服务器的响应时间和吞吐量等指标。这样可以更好地了解压缩数据写入Redis对应用程序性能的实际影响,并根据测试结果进行调整和优化。
结束,散会!!!