当前位置:首页 > 问答 > 正文

用Redis缓存图片,想快点拿图其实也没那么难嘛

根据网络上关于图片缓存的常见技术讨论与实践经验综合整理)

用Redis缓存图片,想快点拿图其实也没也没那么难嘛,你可能觉得这玩意儿听起来挺高大上的,是不是得懂一堆复杂的概念,写一堆绕来绕去的代码?其实真不是,它的核心思路就跟咱们平时过日子一样,怎么省事怎么来,怎么快怎么弄。

你想啊,你的网站或者App上有很多图片,比如用户头像、商品展示图什么的,每次有人来访问,你的服务器都得吭哧吭哧地从硬盘里把图片找出来,再传过去,要是同时有成千上万人要看图,你这服务器不就跟小餐馆里只有一个厨师一样,忙得脚打后脑勺,客人等得心急火燎,体验能好吗?

这时候,Redis就派上用场了,你可以把它想象成你家厨房里的一个超级大的、离客厅特别近的备餐台,厨师(也就是你的服务器)提前把一些最常被点的“招牌菜”(也就是那些热门图片)做好,放在这个备餐台上,客人一点这道菜,服务员(你的程序)都不用跑去后厨,转身就从备餐台端上来了,速度飞快,Redis干的就是这个“备餐台”的活儿,它是个内存数据库,数据都存在内存里,读取速度比从硬盘上读取快了几个数量级,简直就是秒级响应。

用Redis缓存图片,想快点拿图其实也没那么难嘛

那具体怎么把图片放进去呢?很简单,有两种家常便饭式的做法。

第一种,也是最直接的一种,就是把整个图片文件变成一串数据,然后塞进Redis里,你可以把图片想象成一块肉,Redis的存储方式就像不同的容器,你可以用“字符串”这种容器,把图片数据整个放进去,虽然听起来有点像是把一整只烤鸭直接塞进饭盒,但对于不太大的图片,比如缩略图、小图标什么的,完全没问题,简单粗暴效果好,或者,你也可以用“哈希”这种带格子的饭盒,把图片的ID、名字、二进制数据分门别类地放好,管理起来更清晰,这种方法的好处是直白,取出来就能用,但缺点就是,如果你的图片特别大,比如好几兆的高清图,那就会占用很多Redis的内存空间,有点浪费这个“黄金摊位”了。

第二种方法就更巧妙一点,我们叫它“留钥匙”的方法,你不把整个图片放进Redis,而是把图片存放在一个专门的文件存储服务或者对象存储里(比如阿里云OSS、腾讯云COS,或者你自己搭建的简单文件服务器),这些地方存大文件更划算,然后呢,你在Redis里只存一个“钥匙”,也就是这个图片的访问地址,当用户第一次请求某张图片时,你的程序先飞快地去Redis里查一下有没有这把“钥匙”,如果有,直接根据这个地址去把图片取回来展示给用户;如果没有,说明是张新图,那就让服务器去硬盘上找,找到之后,一方面传给用户,把这个图片的地址写到Redis里,相当于配了把新钥匙存起来,下次再有人要这张图,就能直接拿着钥匙去开门了,省去了在硬盘仓库里翻箱倒柜的时间,这种方法特别适合图片量大或者图片体积大的情况,经济实惠,速度提升也很明显。

用Redis缓存图片,想快点拿图其实也没那么难嘛

光存进去还不够,还得会管理,你不能让那个“备餐台”上的菜放馊了是吧?所以得设置一个“保质期”,Redis可以很方便地给存入的数据设置一个过期时间,你可以设置用户头像24小时过期,商品图片7天过期,时间一到,Redis自动就把这些数据清理掉,释放出空间给新的热门图片用,这样既保证了缓存的新鲜度,又避免了内存被无用数据占满。

还有一招叫“淘汰策略”,万一内存快满了,但有些数据还没到期,这时候有新图片要缓存,怎么办?Redis很聪明,它有几种策略,把最近最少用的那个菜撤掉”,或者“随机撤掉一个”等等,你可以根据情况选一种,确保缓存里留下来的都是最受欢迎的“硬菜”。

当然啦,事情没有完美的,用Redis缓存图片也得注意几个小坑,万一Redis服务器本身宕机了,所有缓存瞬间清空,这时候所有请求又会一下子全砸向你的主数据库,可能会造成压力过大,所以对于非常重要的系统,你可能需要考虑搭建一个Redis集群,让它们互相备份,确保高可用性,但这属于“豪华装修”了,刚开始的时候,单机的Redis已经能带来非常显著的提升。

用Redis给图片加速,核心思想就是“空间换时间”,用宝贵的内存资源,换取用户等待时间的极大缩短,你不用一开始就追求最完美的方案,可以先从最简单的“字符串存小图”或者“存路径钥匙”开始试试看,你会发现,可能就加了那么几十行代码,网站的图片加载速度就会有肉眼可见的提升,用户体验上去了,你的心情自然也舒畅了,所以你看,想让图片飞起来,真的没那么难嘛。