【Redis从入门到放弃】一、Redis简介与应用场景

Redis简介

在传统的JavaWeb项目中,使用数据库进行存储数据有一些致命的弊端,这些弊端主要来自于性能方面。由于数据库持久化数据主要是面向磁盘,而磁盘读/写比较慢,在一般管理系统上,由于不存在高并发,因此往往没有瞬间需要读/写大量数据的要求,这个时候使用数据库进行读/写是没有太大的问题的。
但在互联网中,往往存在大数据量的需求,比如一些商品抢购的场景,或者是主页访问量瞬间较大的时候,一瞬间成千上万的请求就会到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务器宕机的严重生产问题。
为了克服这些问题,JavaWeb项目往往就引入了NoSQL技术,NoSQL工具也是一种简易的数据库,它主要是一种基于内存的数据库,并提供一定的持久化功能。Redis和MongoDB是当前使用最广泛的NoSQL。Redis的性能十分优越,可以支持每秒十几万次的读/写操作,其性能远超数据库,并且支持集群、分布式、主从同步等配置,原则上可以无限扩展,让更多的数据存储在内存中。它还能支持一定的事务能力,这在高并发访问的场景下保证数据安全和一致性特别有用。
Redis的性能优越主要来自3方面:

  1. 它是基于ANSI C语言编写的,接近于汇编语言的机器语言,运行十分快速。
  2. 它是基于内存的读/写,速度自然比数据库的磁盘读/写要快得多。
  3. 它的数据库结构只有6中数据类型,数据结构比较简单,因此规则较少,而关系型数据库则是范式,完整性、规范性需要考虑的规则比较多,处理业务会比较复杂。

所以一般而言Redis的速度是正常数据库的几倍到几十倍,如果把命中率搞的数据存储在Redis上,通过Redis读/写和操作这些数据,系统的性能就会远超只使用数据库的情况,所以用好Redis对于java互联网项目的响应速度和性能是至关重要的。

Redis在Java Web中的应用

一般而言Redis在JavaWeb应用中存在两个主要的场景,一个是缓存常用的数据,另一个是需要高速读/写的场合使用它快速读/写,比如一些需要进行商品抢购和抢红包的场合。由于在高并发的情况下,需要对数据进行高速读/写的场景,一个最为核心的问题就是数据一致性和访问控制。这将涉及锁的讨论,涉及数据库、Java和Redis的协作。

缓存

在对数据库的读/写操作中,现实的情况是读操作的次数远超写操作,一般是1:9到3:7的比例,所以需要读的可能性是比写的可能性多得多。当发送SQL去数据库进行读取时,数据库就会去磁盘把对应得数据索引回来,而索引磁盘是一个相对缓慢得过程。如果把数据直接放在运行在内存中的Redis服务器上,那么就不需要去读/写磁盘了,而是直接读取内存,速度会快很多,并能极大程度上减轻数据库的压力。
但使用内存进行存储数据开销也是非常大的,因为磁盘比较廉价,可以是TGB级别的,而内存在市面上较昂贵,几百个GB的配置已经很不错了。所以内存虽然高效但是空间有限,代价较高,去考虑选择存储什么条件的数据是非常重要的。
一般来说,存储一些常用的数据,比如用户登陆信息;一些主要的业务信息,比如银行会存储一些客户基础信息、银行卡信息、最近交易信息等。一般而言在使用Redis存储的时候,需要从3方面考虑。

  1. 业务数据常用吗?缓存命中率如何?如果命中率很低,就没有必要写入缓存。

    什么是缓存命中率?
    命中:可以直接通过缓存获取到需要的数据。
    不命中:无法直接通过缓存获取到想要的数据,需要再次查询数据库或者执行其它的操作。原因可能是由于缓存中根本不存在,或者缓存已经过期。
    通常来讲,缓存的命中率越高则表示使用缓存的收益越高,应用的性能越好(响应时间越短、吞吐量越高),抗并发的能力越强。
    由此可见,在高并发的互联网系统中,缓存的命中率是至关重要的指标。

  2. 该业务数据是读操作多还是写操作多,如果写操作多,频繁需要写入数据库,也没有必要使用缓存。

  3. 业务数据大小如何?如果要存储几百兆字节的文件,会给缓存带来很大的压力,有没有必要?
    在考虑过这些问题后,如果觉得有必要使用缓存,那么就使用它。

使用Redis作为缓存的读取逻辑如图所示:


这里写图片描述

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

    综上所述,当大部分的操作时读操作,使用Redis应对读操作速度就会非常迅速,也降低了对数据库的依赖,大大降低了数据库的负担。

    使用Redis进行写操作流程:


    这里写图片描述

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

高速读/写场合

在互联网应用中,往往存在一些需要高速读/写的场合,比如商品的秒杀,抢红包,淘宝、京东的双十一活动或者春运抢票等。这类场合在一个瞬间成千上万的请求就会达到服务器,如果使用的是数据库,一个瞬间数据库就需要执行成千上万的SQL,很容易造成数据库的瓶颈,严重的会导致数据库瘫痪,造成Java Web系统服务崩溃。
在这样的场合的应对办法往往是考虑异步写入数据库,而在高速读/写的场合中单单使用Redis去应对,把这些需要高速读/写的数据,缓存到Redis中,而在满足一定的条件下,触发这些缓存的数据写入数据库中。一次请求流程操作如下图:


这里写图片描述

当一个请求到达服务器,只是把业务数据先在Redis读/写,而没有进行任何对数据库的操作,换句话说系统仅仅是操作Redis缓存,而没有操作数据库,这个速度就比操作数据库要快得多,从而达到需要高速响应的效果。但是一般缓存不能持久化,或者所持久化的数据不太规范,因此需要把这些数据存入数据库,所以在一个请求操作完Redis的读/写后,会去判断该高速读/写的业务是否结束。这个判断的条件往往就是秒杀商品剩余个数为0,抢红包金额为0,如果不成立,则不会操作数据库;如果成立,则触发事件将Redis缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。

假设面对的是一个商品秒杀的场景,从上面的流程看,一个用户抢购商品,绝大部分的场合都是在操作内存数据库Redis,而不是磁盘数据库,所以其性能更为优越。只有在商品被抢购一空后才会触发系统把Redis缓存的数据写入数据库磁盘中,这样系统大部分的操作基于内存,就能够在秒杀的场合高速响应用户的请求,达到快速应答。

而现实中这种需要高速响应的系统会比上面的分析更复杂,因为没有讨论高并发下的数据安全和一致性问题,没有讨论有效请求和无效请求、事务一致性等诸多问题。
这些后续的博文会对次进行讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值