zoukankan      html  css  js  c++  java
  • 2020重新出发,NOSQL,什么是Redis?

    @

    Redis是什么?

    Redis 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统,是当前互联网世界最为流行的 NoSQL 数据库。NoSQL 在互联网系统中的作用很大,因为它可以在很大程度上提高互联网系统的性能。

    Redis 开源免费,提供了 Java,C/C++,C#,PHP 等客户端,使用方便。主要应用于**内容缓存 ** 和 处理大量数据的高访问负载

    Redis 具备一定持久层的功能,也可以作为一种缓存工具。对于 NoSQL 数据库而言,作为持久层,它存储的数据是半结构化的,这就意味着计算机在读入内存中有更少的规则,读入速度更快。

    对于那些结构化、多范式规则的数据库系统而言,它更具性能优势。作为缓存,它可以支持大数据存入内存中,只要命中率高,它就能快速响应,因为在内存中的数据读/写比数据库读/写磁盘的速度快几十到上百倍,其作用如图 1 所示。

    NoSQL的作用

    ​ 图 1 NoSQL 的作用

    NoSQL和传统数据库的区别

    目前 NoSQL 有很多争议,有些人认为它可以取代数据库,有些人却不这么认为。

    1. 首先,NoSQL 的数据主要存储在内存中(部分可以持久化到磁盘),而数据库主要是磁盘。其次,NoSQL 数据结构比较简单,虽然能处理很多的问题,但是其功能毕竟是有限的,不如数据库的 SQL 语句强大,支持更为复杂的计算。
    2. 再者,NoSQL 并不完全安全稳定,由于它基于内存,一旦停电或者机器故障数据就很容易丢失数据,其持久化能力也是有限的,而基于磁盘的数据库则不会出现这样的问题。
    3. 最后,其数据完整性、事务能力、安全性、可靠性及可扩展性都远不及数据库。

    基于以上原因,有些人并不认为 NoSQL 会取代数据库。

    毫无疑问,Redis 作为一种 NoSQL 是十分成功的,但是它的成功主要是解决互联网系统的一些问题,而主要的问题是性能问题。

    实际上,在互联网系统大部分的业务场景中,业务都是相对简单的,而难以处理的问题主要是性能问题,特别是那些会员数比较多的高并发服务网站。

    • 例如,你可以常常在淘宝或者京东网站上看到一个即将被抢购的商品,有多达几万人的关注,可能一个时刻就发生了成千上万笔业务,此时使用 Redis 作为缓存数据,就可以明显提升系统的性能,而且这十分有效。

    因为数据库系统有更好的规范性和数据完整性,功能更强大,作为持久层更为完善,安全性更高。而 NoSQL 结构松散、不完整,功能有限,目前尚不具备取代数据库的实力,但是作为缓存工具,它的高性能、高响应等功能,使它成为一个很重要的工具。

    Redis的优点

    当前 Redis 已经成为了主要的 NoSQL 工具,其原因如下:

    1. 响应快速(速度快):Redis 响应非常快,每秒可以执行大约 110 000 个写入操作,或者 81 000 个读操作,其速度远超数据库。如果存入一些常用的数据,就能有效提高系统的性能。
    2. 支持6种数据类型(数据类型丰富):它们是字符串、哈希结构、列表、集合、可排序集合和基数。比如对于字符串可以存入一些 Java 基础数据类型,哈希可以存储对象,列表可以存储 List 对象等。这使得在应用中很容易根据自己的需要选择存储的数据类型,方便开发。对于 Redis 而言,虽然只有 6 种数据类型,但是有两大好处:
      • 一方面可以满足存储各种数据结构体的需要;
      • 另外一方面数据类型少,使得规则就少,需要的判断和逻辑就少,这样读/写的速度就更快。
    3. 操作都是原子的(原子性):所有 Redis 的操作都是原子的,从而确保当两个客户同时访问 Redis 服务器时,得到的是更新后的值(最新值)。在需要高并发的场合可以考虑使用 Redis 的事务,处理一些需要锁的业务。
    4. MultiUtility 工具:Redis 可以在如缓存、消息传递队列中使用(Redis 支持“发布+订阅”的消息模式),在应用程序如 Web 应用程序会话、网站页面点击数等任何短暂的数据中使用。正是因为 Redis 具备这些优点,使得它成为了目前主流的 NoSQL 技术,在 Java 互联网中得到了广泛使用。
      • 一方面,使用 NoSQL 从数据库中读取数据进行缓存,就可以从内存中读取数据了,而不像数据库一样读磁盘。现实是读操作远比写操作要多得多,所以缓存很多常用的数据,提高其命中率有助于整体性能的提高,并且能减缓数据库的压力,对互联网系统架构是十分有利的。
      • 另一方面,它也能满足互联网高并发需要高速处理数据的场合,比如抢红包、商品秒杀等场景,这些场合需要高速处理,并保证并发数据安全和一致性。

    Redis在Java Web中的应用

    一般而言 Redis 在 Java Web 应用中存在两个主要的场景,

    • 一个是缓存常用的数据,
    • 另一个是在需要高速读/写的场合使用它快速读/写,比如一些需要进行商品抢购和抢红包的场合。

    由于在高并发的情况下,需要对数据进行高速读/写的场景,一个最为核心的问题是数据一致性和访问控制。

    缓存

    在对数据库的读/写操作中,现实的情况是读操作的次数远超写操作,一般是 1:9 到 3:7 的比例,所以需要读的可能性是比写的可能性多得多。

    当发送 SQL 去数据库进行读取时,数据库就会去磁盘把对应的数据索引回来,而索引磁盘是一个相对缓慢的过程。如果把数据直接放在运行在内存中的 Redis 服务器上,那么不需要去读/写磁盘了,而是直接读取内存,显然速度会快得多,并且会极大减轻数据库的压力。

    而使用内存进行存储数据开销也是比较大的,因为磁盘可以是 TGB 级别,而且十分廉价,内存一般是几百个 GB 就相当了不起了,所以内存虽然高效但空间有限,价格也比磁盘高许多,因此使用内存代价较高,并不是想存什么就存什么,因此我们应该考虑有条件的存储数据。

    一般而言,存储一些常用的数据,比如用户登录的信息;一些主要的业务信息,比如银行会存储一些客户基础信息、银行卡信息、最近交易信息等。一般而言在使用 Redis 存储的时候,需要从 3 个方面进行考虑。

    1. 业务数据常用吗?命中率如何?如果命中率很低,就没有必要写入缓存。
    2. 该业务数据是读操作多,还是写操作多,如果写操作多,频繁需要写入数据库,也没有必要使用缓存。
    3. 业务数据大小如何?如果要存储几百兆字节的文件,会给缓存带来很大的压力,有没有必要?

    在考虑过这些问题后,如果觉得有必要使用缓存,那么就使用它。使用 Redis 作为缓存的读取逻辑如图 1 所示。

    Redis的缓存应用

    ​ 图 1 Redis 的缓存应用

    从图 1 中可以知道以下两点。

    • 当第一次读取数据的时候,读取 Redis 的数据就会失败,此时会触发程序读取数据库,把数据读取出来,并且写入 Redis。
    • 当第二次及以后读取数据时,就直接读取 Redis,读到数据后就结束了流程,这样速度就大大提高了。

    从上面的分析可知,大部分的操作是读操作,使用 Redis 应对读操作,速度就会十分迅速,同时也降低了对数据库的依赖,大大降低了数据库的负担。

    分析了读操作的逻辑后,下面再来分析写操作的流程,如图 2 所示。

    写操作的流程

    ​ 图 2 写操作的流程

    从流程可以看出,更新或者写入的操作,需要多个 Redis 的操作。如果业务数据写次数远大于读次数没有必要使用 Redis。如果是读次数远大于写次数,则使用 Redis 就有其价值了,因为写入 Redis 虽然要消耗一定的代价,但是其性能良好,相对数据库而言,几乎可以忽略不计。

    高速读/写场合

    在互联网的应用中,往往存在一些需要高速读/写的场合,比如商品的秒杀,抢红包,淘宝、京东的双十一活动或者春运抢票等。

    以上这类场合在一个瞬间成千上万的请求就会达到服务器,如果使用的是数据库,一个瞬间数据库就需要执行成千上万的 SQL,很容易造成数据库的瓶颈,严重的会导致数据库瘫痪,造成 Java Web 系统服务崩溃。

    在这样的场合的应对办法往往是考虑异步写入数据库,而在高速读/写的场合中单单使用 Redis 去应对,把这些需要高速读/写的数据,缓存到 Redis 中,而在满足一定的条件下,触发这些缓存的数据写入数据库中。先看看一次请求操作的流程图,如图 3 所示。

    Redis在高速读/写场合的应用

    ​ 图 3 Redis 在高速读/写场合的应用

    进一步论述这个过程:

    • 当一个请求达到服务器,只是把业务数据先在 Redis 读/写,而没有进行任何对数据库的操作,换句话说系统仅仅是操作 Redis 缓存,而没有操作数据库,这个速度就比操作数据库要快得多,从而达到需要高速响应的效果。
    • 但是一般缓存不能持久化,或者所持久化的数据不太规范,因此需要把这些数据存入数据库,所以在一个请求操作完 Redis 的读/写后,会去判断该高速读/写的业务是否结束。
    • 这个判断的条件往往就是秒杀商品剩余个数为 0,抢红包金额为 0,如果不成立,则不会操作数据库;如果成立,则触发事件将 Redis 缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。
    • 假设面对的是一个商品秒杀的场景,从上面的流程看,一个用户抢购商品,绝大部分的场合都是在操作内存数据库 Redis,而不是磁盘数据库,所以其性能更为优越。只有在商品被抢购一空后才会触发系统把 Redis 缓存的数据写入数据库磁盘中,这样系统大部分的操作基于内存,就能够在秒杀的场合高速响应用户的请求,达到快速应答。
    • 而现实中这种需要高速响应的系统会比上面的分析更复杂,因为这里没有讨论高并发下的数据安全和一致性问题,没有讨论有效请求和无效请求、事务一致性等诸多问题。
  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/yeyuliuyun/p/13605719.html
Copyright © 2011-2022 走看看