我们都知道,在互联网项目中往往存在大数据量的需求,比如一些商品抢购的场景,或是访问量瞬间较大的时候,一瞬间成千上万的请求就会到来,比如在双十一活动。这就需要在短时间内完成成千上万次读或者写的操作,对于传统数据库来说,这肯定是不行的,容易使系统宕机,所以这时候NoSQL的出现改变了这个现状,例如一些非关系型数据库redis、文档型mongoDB等等。这篇主要介绍我所认识的redis,由于本人才疏学浅,而且刚刚学习不久,若有说的不对的地方希望各位海涵。
这篇文章主要是作为我现阶段对redis认识的总结,另一方面对未来的我可以随时复习这一内容而准备。redis的性能十分优越,大概每秒可以支持十几万次的读或者写的操作,其性能可以说非同一般,而且支持集群、分布式、主从同步等配置,而且还支持一定的事务能力,这就在高并发下保证数据的安全和一致性起到了相当大的作用。redis的性能优越主要来源3个方面:第一,它是基于c语言编写的,因为c是接近汇编语言的机器语言,所以运行快。第二,它是基于内存的读写,读取速度自然会比磁盘读写快多了。第三,他的数据结构只有6种数据类型,结构简单且规则少。一般来说,redis在Java web应用中主要存在于两个场景:一个是缓存常用的数据,让数据用其所用。一个是需要在高并发下快速地的读或者写。
使用环境一:缓存。
首先,当前时代系统的对数据库的读操作远远大于写的操作,所以这就需要读的性能较强。当发送sql去查询数据的时候,就会去数据库就会把数据从磁盘传过来,通过磁盘就相当的缓慢了,当然这只是对比于redis来说,redis是直接从运行时内存中读取数据,这就会快很多,而且减缓了数据库的压力。但是,并不是说它好我们就必须得用它,有的时候不用它会有更好的效果。一般来说,在使用redis存储数据的时候,需要从3个方面进行考虑:
1. 业务数据常用吗?命中率如何?如果命中率很低,那就没必要用redis把这一数据写入缓存了。
2. 该业务数据是读操作多?还是写操作多?如果写操作多,那就需要频繁的将数据写到数据库中,redis不是做这个的,所以就没必要将这部分数据写入redis的缓存中了。
3. 业务数据的大小如何?如果要存储几百兆字节的文件,这会给缓存带来巨大的压力,因为会耗费我们的内存,影响速度,有没有必要?
redis的读取逻辑图如下所示:
redis作为缓存的读取逻辑
当第一次读取数据的时候,读取redis必然会失败,因为redis里没有这一数据,需要先从数据库中拿,然后写入redis。当第二次及以后读取数据时,就直接读取redis,读到数据就将数据返回,并结束这一流程,这样速度就大大提高了。redis也有写操作的流程,如下图所示:
redis写操作的流程
从流程可以看出,更新或者写入的操作,需要多个redis的操作。如果业务数据数据的写操作的次数远大于读操作的次数,那就没有必要使用redis缓存了。
使用环境二:高并发场景-也叫高速读写场合
我们所知道的例如商品的秒杀、抢红包,抢票等等,在双十一零点的那个瞬间,可能就会有几十万个请求蜂拥而来,想想要在1秒内或更少时间处理这么多的请求,一般的服务器真是受不了。想想一个瞬间数据库就处理这么多sql语句,这样很可能会造成数据库的瘫痪以及系统宕机。我们也看到过某宝在双十一出现过界面延迟加载,系统崩溃等情况,我想一定要理解他们的工作人员,每次到这个时候都有不少的运维人员加班加点的维修,他们真的很辛苦。所以在这种情况下,我们往往考虑异步地去写入数据库,而在高速读或者写的情况下使用redis去应对,把这些需要高速读或写的数据缓存到redis中,而在满足一定的条件后,再将这些数据写入到内存中。流程图如下所示:
redis在高速读或者写的场合的应用流程
也就是,当一个请求到达服务器,只是把业务数据现在redis上进行读写,而没有进行任何对数据库的操作,换句话说就是,系统仅仅是操作redis缓存,而没有操作数据库,这个速度就比操作数据库要快的多。但是缓存不能持久化,因此需要把这些数据存入数据库,所以在一个请求操作完redis的读或写操作后,会判断该高速读写业务是否结束。这个条件一般是商品剩余个数为0,抢红包剩余金额为0。如果不成立,就不会操作数据库,如果成立,则会触发事件将redis缓存的数据以批量的形式一次性写入数据库,从而完成持久化操作。而实际上,真正的情况远比上述更为复杂,因为实际中要考虑高并发下的数据安全和一致性的问题,以及有效请求无效请求以及事务一致性等诸多问题。