Redis如何弥补传统MySQL架构的不足?

VIP-linxi


Mysql是一款开源免费,使用最多的非关系型数据库,体积小,性能强大,查询速度快!

但是大多数关系型数据库的数据都是存储在计算机硬盘上的,数据在磁盘存取的时候是机械操作,断电不丢失数据,而内存是存储电信号,断电就丢失数据,内存的存取速度比硬盘的存取速度快了很多很多!


mysql数据也是存在硬盘,存取速度相对于存在内存的redis有很大差距,在高并发环境,如果有瞬间的大量请求通过,则mysql会存在存取速度慢导致系统崩溃的情况!

比如说秒杀场景,在一秒钟之内,有可能有数百万的数据访问,而mysql是完全不能处理的,对这种场景可使用内存型数据库,比如redis,先将需要秒杀的商品ID存入到redis中,将商品ID和用户的信息异步保存到数据库,减少数据库的冲击!

再比如一个场景,某个产品非常热门,大量的客户端在访问这个产品的详情,这时候可以把这个数据的详情缓存到redis中,可以减少大量的访问数据库,提升整个系统的吞吐性能!


由此可见,其实缓存就是相当于数据库的限流工具!

不过,缓存加数据库的果架构也会存在问题,如缓存击穿,缓存穿透,缓存雪崩,这些事故的发生可能是因为缓存突然宕机,也可能是因为程序设置不当导致缓存失效,进而大量的数据请求冲击数据库,引发数据库崩溃!

针对这种情况,应该做到以下几点:

1,尽量使用缓存集群,防止单机宕机引发的缓存失效!

2,防止大量数据库key同时失效的情况!

3,对key进行合理性检验,防止攻击!(比如数据库ID一般来说都是正整数吧,别人使用一个负数一直来查询,这样所有的请求都落在了数据库)!


总之,在高并发环境,缓存极大的释放了数据库的压力,提升了整个系统的性能,我对JAVA相关技术算是比较了解,以后也会一直分享,欢迎关注,互相沟通!


此生唯一


谈一下我的理解,如果有不对的地方,请留言指正。


MySQL+Redis

Redis自身是可以做数据持久化的,很多同学都会想Redis应该可以替代MySQL,但是我们使用一项技术、一个框架的时候,不是看它能不能,而是要看它适合不适合。

所以大多数公司的存储都是MySQL+Redis,MySQL(或者其他关系型数据库)作为主存储,Redis作为辅助存储,被用作缓存,这样可以加快访问读取的速度,提高性能。



Redis被用作缓存,以减少数据库IO的读操作,减轻数据库的压力,例如:

  • 存储热点数据:经常会被查询,但是不经常被修改或者删除的数据;

  • 计数器:诸如很多论坛用于统计点击数;

  • 分布式锁及单线程机制;

  • 最新列表、排行榜:请不要使用select top 10 from xxxx。


划重点,下面介绍一下缓存穿透

很多时候,程序员习惯先查询Redis,查询不到的话再去查询数据库,能查到的话再写入Redis中,认为这样不仅缓解了数据库的压力,同时也能保证数据的准确性。

但是由于缓存不命中就会查询数据库,如果一直查询不到的话,就导致每次请求都会查询数据库,如果短时间内有大量这样的请求,那么数据库可能会扛不住。


这就是缓存穿透。

其实应对的方法也很简单,查询不到的数据,也缓存到Redis中,并设置数据的过期时间。

举个不一定恰当的例子,例如Redis中缓存员工信息,提供接口根据工号查询员工信息:

  1. 接口入参工号A001。

  2. 系统先在Redis中查询,查询不到。

  3. 系统去数据库中查询,也查询不到。

  4. 系统插入Redis,key=A001,value=null,设置过期时间五分钟。


  5. 这样,五分钟之内再根据A001查询,不会穿透到数据库。

  6. 四分钟后,数据库中插入了A001的数据。

  7. 五分钟后,Redis中数据过期,下一次请求过来,会查询数据库,并把信息加载到Redis中。



希望我的回答,能够帮助到你!

我会持续分享Java程序开发、架构设计、职业发展等方面的知识和见解,希望能得到你的关注今日头条【会点代码的大叔】,转载请注明出处。


会点代码的大叔


使用的就是Redis+MySql来互相辅助。

MySQL的优势

首先,我们必须承认Mysql作为关系型数据库管理系统有其不可代替的优势,主要体现在以下5个方面。

1 支持处理大量数据,量级可达到八位数

2 支持常见的SQL语句规范

3 可移植性强,安装起来小巧方便

4 运行效率高

5 使用量大,能够获得广泛的网络信息支持

基于此,MySQL通常作为持久层,出现在各种web应用场景。

MySQL的局限性

但是当表内数据量很大之后,如果不加索引,其查询效率将有惊人的衰退。

我们通常默认查询语句是毫秒级别的返回,但是我在实际工作中曾经遇到过一张包含10个字段的表,900万+条数据。当根据一个未加索引的字段进行精确查询的时候,单条sql语句的执行时长有时能够达到2min以上,就更别提如果用like这种模糊查询的话,其效率将会多么低下。

也许你会说,那再对该字段加一个索引好了。

如果你真的这么做了,恭喜你,你踩了一个比大查询还可怕的坑。

假设我们使用的Mysql已经是主从库了,那么大查询语句执行很久时,卡住的顶多是从库,主库还是不受任何影响的。但是如果此时你又执行了增加索引操作,那么主库将会对这900万+条数据依次操作增加索引,结果就是主库从库全部卡住,此时所有请求,不论增删改查,全部hang住,等待查询与增加索引操作执行结束。从用户的角度,感受到的就是服务响应变慢,甚至超时。

Redis的优势如何弥补Mysql

在这种时刻,Redis的重要性就体现出来了。

Redis具有读写速度极快,支持多种存储类型,支持事务以及分布式锁的优势。

与上面的局限性结合起来看就可以看出,Redis能够弥补MySQL读写慢的劣势,对于一些无需持久化的数据,或者是在持久化之前会频繁变动的数据,就可以选择用Redis做缓存。

举个例子,我创建了一个任务数据Task,这个Task在最终完成写入数据库之前,有很多个步骤需要改变Task的属性值,在这个过程中,将Task持久化数据库是无意义的,反而会徒增很多读写的步骤,浪费执行时间。如果选择在创建Task之后,就将其写入数据库与Redis,在中间过程,只读写Redis中Task的值,在完成Task之后,确认其值不会改变后,再持久化入MySql,就能够极大的提高系统的效率。

这样,就能够将原本给Mysql的读写压力,分配到了Redis上。

Redis无法取代Mysql

虽然Redis的读写速度优于MySQL,并且支持配置持久化,但是没有任何一个对外应用汇选择Redis来代替MySQL。

主要原因是Redis持久化数据是需要一定代价的。我们曾亲身经验过一次事件,我们一个服务的Redis节点误开启了持久化开关,重启节点后,几分钟都无法读取,最开始我们以为是服务器的问题,网络问题,最后通过日志才发现,是由于Redis重启后,要load持久化的数据进来,尽管这个数据量远远小于MySQL存储的数据,但是启动时长却用了分钟级别。

此外,Redis不支持sql语句,当数据量增加后,其读写效率也会显著下降等问题,也是它无法代替MySQL的原因。


综上,最科学的方法是用MySQL+Redis的结合,分摊数据读写压力,从而提高系统效率。


以上是我个人经验,如果对你有帮助,请顺手送个赞给我,或者在下方评论区留言给我。



我是苏苏思量,头像是本人,来自BAT的java工程师,经常分享科技类见闻,欢迎关注我,与我互动。


一个存在感小透明


大声反对楼下说的Redis做主库。

Redis要求内存,你想想你们的数据量增长态势,先算一下内存够不够用。

Redis的持久化有问题,想保证数据不丢时使用AOF模式(注:AOF持久化策略是将发送到Redis服务端的每一条命令都记录下来,并且保存到硬盘中的AOF文件中,类似打日志文件,来一条命令就记录一条),策略为fsync always,这种的性能比Mysql还低!如果你喜欢它直观的kv结构而对性能要求不高,或者性能要求很高,但允许一定程度的丢失数据,则可以用redis做为主数据库。你真的考虑好了吗?你能确定丢了什么数据吗?Redis做主数据库是不靠谱的,并不是所有的数据都是立即回写磁盘!

它适合小数据量重复查询,实时要求高的地方,项目中主要是做高速缓存和session状态存储等,其作为Nosql数据库,多条件联合查询效率低,操作不便,主要数据结构不够丰富,int,date之类也没有,主库还是采用成熟的Mysql比较好。

如何弥补不足?

主要是它适合存储一些不是特别紧要的比如关注,粉丝关系,等等可以直接转换为kv格式的数据,能够避免频繁查询数据库给数据库造成的压力。可以做一些数据聚合和统计工作,这些都允许少量的数据丢失,网站今天有12800人访问和12795人访问,对老板来说都是一样的。Redis还有特别的地理关系数据结构,适合做附近关系等等。

总结下来就是三方面,一方面做缓存,扛住访问关系型数据库的压力。二是做运营推广时效性活动,数据聚合统计工作的,可以全放在Redis,有对应的数据结构可用。三是地理位置等特殊用途。

每种数据库都有它合适的位置,眉毛胡子一把抓不可取。

如果您认同我的观点,请点击右上角红字“关注”,谢谢。


小七读书涨知识


Redis本身有固化机制,完全可以当作主数据库使用,如果对事务要求不高的话。和MySQL配合用,可以把MySQL当作Redis后备库,业务数据放在Redis中运行,用异步方式写入MySQL。Redis的优点是可以任意做镜像,可以集群。Redis当主库使用,必须要保证至少一个异地Slave,防止主库当机时丢失数据。


光明右使8787


redis把数据存在内存,效率高。mysql每次查询要有io性能差,redis可以减少服务器压力。


分享到:


相關文章: