zoukankan      html  css  js  c++  java
  • 【Redis】四、Redis设计原理及相关问题

    (六)Redis设计原理及相关问题

      通过前面关于Redis五种数据类型、相关高级特性以及一些简单示例的使用,对Redis的使用和主要的用途应该有所掌握,但是还有一些原理性的问题我们在本部分做一个探讨。

      本部分参考了一些其他博客,在文后的参考链接中注明,特此说明。

    1、Redis与mysql的区别

      Redis是一种Key-value型的存储数据库,我们自然有一个疑惑,我们早已会用类似于mysql这样的关系型数据库了,那么他们之间有什么区别,为什么还要用Redis。

      (1)数据库类型不同

      mysql是我们熟知的关系型数据库,数据严格存储在表格的行和列中,面向的是结构化的数据。而Redis是一种非关系型数据库,属于一种NoSQL数据库,除了结构化数据,还可以存储半结构化和非结构化的数据,比如我们在数据类型中提到,字符串可以存储任何数据,比如jpg图片或者序列化的对象。

      (2)运行机制不同

      mysql主要用于存放持久化的数据,将数据存放在硬盘中,读取速度比较慢,适合存放大数据。Redis的数据保存在缓存中,缓存的读取速度快,效率高,要存放大量数据需要进行分区和横向扩展。另外,Redis天生就是适合分布式存储的,可以动态的横向扩展。

      mysql在每次访问数据库时,都存在着复杂的I/O操作,在连接数据库上花费大量时间,效率比较慢。Redis的数据本身就在缓存中,可以用于存储使用频繁的热数据,不会产生复杂的I/O。

      (3)面向的需求不同

      mysql面向大量数据的持久化存储,由于关系型数据库的优势,适合用于多表联合查询等。Redis由于缓存容量有限,只可以作为一个减轻数据库压力的缓冲和少量热数据存储的数据库。因此,实际上,很多情况下是mysql和Redis联合使用,redis存储使用频繁的数据,这样减少访问数据库的次数,提高运行效率。

      (4)性能差异明显

      关系型数据库为了维护数据的一致性付出了巨大的代价,读写性能比较差。在面对高并发读写性能非常差,面对海量数据的时候效率非常低。而Nosql存储的格式都是key-value类型的,并且存储在内存中,非常容易存储,而且对于数据的 一致性是 弱要求。Nosql无需sql的解析,提高了读写性能。

    2、为什么使用Redis

      关于为什么使用Redis,感觉有一篇博客讲的比较好,这里借用其中的两幅图(参考链接中注明)。

      使用Redis主要考虑到的是两个因素:性能和并发

      (1)高性能

      在碰到需要执行耗时特别久,且结果不频繁变动的SQL,就特别适合将运行结果放入缓存。这样,后面的请求就去缓存中读取,使得请求能够迅速响应

      (2)高并发

      在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问数据库。

    3、Redis为什么“快”

      (1) 绝大部分请求是纯粹的内存操作(非常快速)

      (2) 采用单线程,避免了不必要的上下文切换和竞争条件

      (3) 非阻塞多路IO复用

    4、Redis的单线程机制

      单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。

      这个可能不太好理解,单线程怎么还比多线程快了呢,这是因为Redis的性能瓶颈在内存的大小和网络的带宽,重点是Redis存储在内存,不涉及I/O操作,(只有在有I/O操作的时候,线程因为I/O而阻塞,此时将CPU让给别的线程会达到比较好的性能),所以Redis几乎不涉及任何的外部I/O,因此,单线程是最快的。

    5、Redis的多路I/O复用

      IO多路复用是用来解决对多个I/O监听时,一个I/O阻塞影响其他I/O的问题,跟多线程没关系。跟多线程相比较,线程切换需要切换到内核进行线程切换,需要消耗时间和资源.而I/O多路复用不需要切换线/进程,效率相对较高,特别是对高并发的应用nginx就是用I/O多路复用,故而性能极佳.但多线程编程逻辑和处理上比I/O多路复用简单.而I/O多路复用处理起来较为复杂。

      这个理解较难,可以参考文后给出的链接。

    6、redis的过期策略以及内存淘汰机制

      redis采用的是定期删除+惰性删除策略

      定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。

      如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。那么就应该采用内存淘汰机制

      在redis.conf中有一行配置maxmemory-policy allkeys-lru,该配置就是配内存淘汰策略的。
      1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。

      2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用。

      3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。

      4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。

      5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。

      6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

    参考链接(本文大多内容参考其他博客,特此注明):

    https://www.cnblogs.com/zxh1297/p/9394108.html

    https://www.cnblogs.com/bigben0123/p/9115597.html

    https://www.jianshu.com/p/9b71f8ee6e28

    作者:itcats_cn
    来源:CSDN
    原文:https://blog.csdn.net/itcats_cn/article/details/82391719

  • 相关阅读:
    _bzoj1061 [Noi2008]志愿者招募【最小费用最大流】
    _bzoj2243 [SDOI2011]染色【树链剖分】
    _bzoj1013 [JSOI2008]球形空间产生器sphere【高斯消元】
    _bzoj1002 [FJOI2007]轮状病毒【瞎搞】
    leetcode 273 Integer to English Words
    leetcode 12 Integer to Roman
    leetcode 1071 Greatest Common Divisor of Strings
    lc6 ZigZag Conversion
    lc13 Roman to Integer
    leetcode 171 Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/gzshan/p/10975129.html
Copyright © 2011-2022 走看看