当前位置: 首页 > 编程日记 > 正文

业界对生成图片缩略图的做法归纳

网站如果有很多用户上传图片(相册,商品图片),一般的做法是将用户图片保存在磁盘上面(数据库中记录图片的地址)。用户上传的时候按照原图、中图、小图等各个尺寸都生成一份保存在磁盘上。比如php的网店系统echsop就是这么做的,而shopex之类也大同小异。

这种做法也不是不可以。多生成几个尺寸,在磁盘上无非多存储几份而已,磁盘现在也便宜。

不过,有个问题:运营部经常需要很多尺寸版本的图片,比如需要80*80,又需要70*80,各个版面随着活动的需要,尺寸往往不同。有些一张图片可能需要根据不同的应用场景提供的图片尺寸不同,假设统计一下有几十种不同尺寸的缩略图。难道生成20张保存在磁盘上?磁盘价格固然白菜价。但是要考虑大量图片请求导致的磁盘读写的性能问题。

后来发现,随着流量大,尤其并发访问大,图片非常多的时候,频繁的读写,图片存储在磁盘上,磁盘磁头频繁定位造成的延时。

后面我了解到,业界比较成熟的做法是实时生成缩略图。也就是传递尺寸,当时就生成(生成也可以保存在磁盘上,以备下回需要的时候继续使用,也可以不保存,自己控制),这样子在磁盘上就不用保存很多份了。

看过淘宝网对自己图片存储的介绍:http://news.cnblogs.com/n/73189/

了解到如下关键点:

淘宝网的图片文件数量达到286亿多个,这些图片文件包括根据原图生成的缩略图。平均图片大小是17.45K;8K以下图片占图片数总量的61%,占存储容量的11%。

这就给淘宝网的系统带来了一个巨大的挑战,众所周知,对于大多数系统来说,最头疼的就是大规模的小文件存储与读取,因为磁头需要频繁的寻道和换道,因此在读取上容易带来较长的延时。在大量高并发访问量的情况下,简直就是系统的噩梦。

 

实时生成缩略图的好处总结如下:

1、节省存储空间。虽然现在磁盘确实很便宜。1g的成本很低。但是毕竟还是需要钱的。更关键一点是,图片保存在磁盘上读取时磁头频繁定位的性能问题(服务器实时生成消耗的应该是cpu资源,cpu速度很快)

图片越多时,问题越大。

2、更加灵活响应运营部的多尺寸图片需求。比如有些一张图片可能需要根据不同的应用场景提供的图片尺寸不同,假设统计一下有几十种不同尺寸的缩略图。难道生成20张保存在磁盘上?

程序员确实不用纠结保存多少份的问题了。

有些图片尺寸,只会用到一次,比如做活动使用一次,后面可能永远都不会被用到。没必要在上传图片的时候消耗cpu资源去生成,浪费磁盘空间去存储

还是一样,图片种类越多,这个问题越明显。图片就那么点点就没问题(比如就是存储用户头像而已,而商品图片就会用到很多尺寸的版本)

淘宝网提到了他们使用GraphicsMagick进行图片处理。

 

搜索到的资料如下

1、ImageMagickImageMagick是一套功能强大、稳定而且开源的工具集和开发包,可以用来读、写和处理超过89种基本格式的图片文件

利用ImageMagick,你可以根据web应用程序的需要动态生成图片, 还可以对一个(或一组)图片进行改变大小、旋转、锐化、减色或增加特效等操作,并将操作的结果以相同格式或其它格式保存,对图片的操作,即可以通过命令行进行,也可以用C/C++、Perl、Java、PHP、Python或Ruby编程来完成。

功能如下:

1. 将图片从一个格式转换到另一个格式,包括直接转换成图标。

2. 改变尺寸、旋转、锐化(sharpen)、减色、图片特效

3. 缩略图片的合成图( a montage of image thumbnails)

4. 适于web的背景透明的图片

5. 将一组图片作成gif动画,直接convert

6. 将几张图片作成一张组合图片,montage

7. 在一个图片上写字或画图形,带文字阴影和边框渲染。

8. 给图片加边框或框架

9. 取得一些图片的特性信息

2、  GraphicsMagick

GraphicsMagick 支持大图片的处理,并且已经做过GB级别的图像处理实验。GraphicsMagick能够动态的生成图片,特别适用于互联网的应用。可以用来处理调整尺寸、旋转、加亮、颜色调整、增加特效等方面

也支持C、C++、Perl、PHP、Tcl、 Ruby等的调用。事实上,GraphicsMagick是从 ImageMagick 5.5.2 分支出来的,但是现在他变得更稳定和优秀,下面就是两个之间的一些比较。

GM更有效率(测评),能更快的完成处理工作

GM更小更容易安装

GM已经被Flickr和Etsy使用,每天处理百万计的图片

GM与已经安装的软件不会发生冲突

GM几乎没有安全问题

GM的手册非常丰富

使用GraphicsMagick常见的做法是:单独一台图片服务器用来响应生成缩略图的请求。nginx+GraphicsMagick+lua结合起来。图片服务器上安装nginx,nginx调用lua程序,让lua程序来执行shell命令(GraphicsMagick原本就是可以通过shell命令来调用的,这里就是让lua来调用),大体像下面这样子:

location ~ '/images/([0-9a-z]+)_([0-9]+)x([0-9]+).jpg$' {

root /home/images;

set $image_root =  '/home/images';

set $fileName = ngx.arg[1];

set $width = ngx.arg[2];

set $height = ngx.arg[3];

set $origin = $image_root/$fileName.jpg

set $file = $image_root/$fileName_$widthx$height.jpg

#请求的图片尺寸不存在 ,就实时生成,并且保存一份到磁盘上备下回使用

if (!-f $file) {

rewrite_by_lua '

local command = "gm convert "..ngx.var.origin.." -thumbnail "..ngx.var.width.."x"

..ngx.var.height.." "..ngx.var.file;

os.execute(command);

';

# rewrite_by_lua右边的单引号里面是lua程序语法。里面关键就是os.execute执行一条命令。这条命令就是调用GraphicsMagick

}

 

 

这里有篇好文章,专门分析亚马逊是如何保存图片的(其实也是实时生成缩略图的方式):

http://aaugh.com/imageabuse.html

不过是纯英文的。

其实大部分网站通过实时生成图片应该能够满足需求了。达到淘宝那样子需要研发自己的cdn图片网络环境,很少公司达到。

有个理论性的东西比较重要:

对数据库的读/写的速度永远都赶不上文件系统处理的速度。所以把图片文件丢到磁盘上让文件系统来维护比较好。只是磁盘频繁的定位造成的速度慢又是一个问题,呵呵。不过,只是并发访问量大的时候才会出现。没到极限不必担心,避免过度设计。

我写这篇文章,就是预留以后遇到这种问题,备个解决方案。

15年更新:

恰好进入的一家公司,图片存储占用的磁盘空间大。有几十个t,针对图片还要进行备份。同一张图片分为不同的尺寸。这样占据的空间比较麻烦。

基于存储成本考虑。使用动态生成图片尺寸的方式。

一张图片如果有多个尺寸。不保持多个尺寸,需要什么尺寸就实时生成。图片让七牛存储去生成?
硬盘就保存原图。如果需要a尺寸,b尺寸。传递参数,当时生成一个返回,硬盘不保存多个尺寸的图。

使用了第三方的图片存储,没有自己搭建服务来生成尺寸。之所以使用第三方,因为他们有cdn加速服务,图片可以就近节点存储,用户访问可以就近节点进行访问图片。

目前的硬盘24t。快占满了。

转载于:https://www.cnblogs.com/wangtao_20/p/3481098.html

相关文章:

thinkPHP5.0 URL路由优化

在tp中访问页面的时候URL地址是 域名/模块/控制器/方法,在点击首页的时候URL是 域名/index/index/index 而不是只显示域名,这样不利于SEO,而且强迫症的我看着很不爽,这个时候我们需要优化路由 Route::rule(路由表达式,路由地址,请…

Rocksdb 获取当前db内部的有效key个数 (估值)

文章目录1. 基本接口2. Memtable key个数统计3. Immutable Memtable key个数统计4. Sstables key个数统计5. 疑问Rocksdb因为是AppendOnly 方式写入,所以没有办法提供db内部唯一key个数的接口(可能存在多版本的key,对用户来说只有一个userkey…

Java项目:网上花店商城系统(java+jsp+servlert+mysql+ajax)

源码获取:博客首页 "资源" 里下载! 一、项目简述 功能: 一套完整的网上花店商场系统,系统支持前台会员的注册 登陆系统留言,花朵的品种选择,详情浏览,加入购物 车,购买花…

使用Uboot启动内核并挂载NFS根文件系统

配置编译好内核之后,将生成的内核文件uImage拷贝到/tftpboot/下,通过tftp服务器将内核下载到开发板,使用命令:tftp 31000000 uImage.下载完成之后配置bootargs环境变量:setenv bootargs noinitrd consolettySAC0,11520…

Centos系统上安装php遇到的错误解决方法集锦

Centos系统上安装php遇到的错误解决方法集锦1.configure: error: xml2-config not found. Please check your libxml2 installationyum install libxml2 libxml2-devel2.configure: error: Cannot find OpenSSL’s yum install openssl openssl-devel3.configure: error: Pleas…

2.27 MapReduce Shuffle过程如何在Job中进行设置

一、shuffle过程 总的来说: *分区 partitioner*排序 sort*copy (用户无法干涉) 拷贝*分组 group可设置 *压缩 compress*combiner map task端的Reduce二、示例 package com.ibeifeng.hadoop.senior.mapreduce;import java.io.IOException; import java.util.StringTo…

Rocksdb Slice使用中的一个小坑

本文记录一下使用Rocksdb Slice过程中的一个小小坑,差点没一口老血吐出来。 rocksdb的Slice 数据结构是一个小型得不可变类string数据结构,设计出来的目的是为了保证rocksdb内部处理用户输入的key在从内存到持久化磁盘的整个处理链路是不会被修改的&…

Java项目:仿天猫网上商城项目(java+jsp+servlet+mysql+ajax)

源码获取:博客首页 "资源" 里下载! 一、项目简述 功能: 前台: * 用户模块 * 分类模块 * 商品模块 * 购物车模块 * 订单模块 后台: * 管理员模块 * 分类管理模块 * 商品管理模块 * 订单模块…

转--Android如何在java代码中设置margin

3 在Java代码里设置button的margin(外边距)? 1、获取按钮的LayoutParams LinearLayout.LayoutParams layoutParams (LinearLayout.LayoutParams)button.getLayoutParams(); 2、在LayoutParams中设置margin layoutParams.setMargins(100,20,10,5);//4个参数按顺序分…

poj12月其他题解(未完)

最近编程的时间比较少啊…… poj3253 就是个合并果子,各种优先队列即可(显然单调队列最优) poj3263 线段树统计每个点被覆盖了多少次即可,注意要去重 poj3625 最小生成树 poj3626 bfs poj3624 01背包 poj3615 floyd即可 poj3278 简…

0409-0416的笔记

1 获取前几天,近几个月的时间 function getDay(day) {var today new Date();var targetday_milliseconds today.getTime() 1000 * 60 * 60 * 24 * day;today.setTime(targetday_milliseconds); //注意,这行是关键代码var tYear today.getFullYear();…

Linux NUMA 架构 :基础软件工程师需要知道一些知识

文章目录前言从物理CPU、core到HT(hyper-threading)UMA(Uniform memory access)NUMA架构NUMA下的内存分配策略1. MPOL_DEFAULT2. MPOL_BIND3. MPOL_INTERLEAVE4. MPOL_PREFERRED5. 一些NUMA架构下的内核配置总结参考前言 NUMA(Non-Uniform m…

Java项目:网上书城+后台管理系统(java+jsp+servlert+mysql+ajax)

源码获取:博客首页 "资源" 里下载! 一、项目简述(附带IW文档) 功能: 前台: * 用户模块 * 分类模块 * 图书模块 * 购物车模块 * 订单模块 后台: * 管理员模块 * 分类管理模块 * 图书管理模块 * 订单模块 …

java.util.concurrent包API学习笔记

newFixedThreadPool 创建一个固定大小的线程池。 shutdown():用于关闭启动线程,如果不调用该语句,jvm不会关闭。 awaitTermination():用于等待子线程结束,再继续执行下面的代码。该例中我设置一直等着子线程结束。Java…

oracle读书记录

很久没有关注自己怕博客了,差不多有两年了。虽然这两年来一直关注51CTO,每天上班打开电脑或者周末在家开启电脑的时候都会浏览一下,这已经是习惯了,但是把自己的blog给忘了。今天,周末,2013年12月21日,同往…

输入、方法的运用

/ /猜数游戏,编写一个功能,完成猜数游戏,产生一个1~10之间的随机数 //与输入的数对对比,返回结果 猜中和没猜中 import java.util.Scanner; //引入(输入)的util包Scanner public class HelloWorld { public static void main(String[] args) {System…

Rocksdb 利用recycle_log_file_num 重用wal-log文件

recycle_log_file_num 复用wal文件信息, 优化wal文件的空间分配,减少pagecache中文件元信息的更新开销。 为同事提供了一组rocksdb写优化参数之后有一个疑惑的现象被问到,发现之前的一些代码细节有遗忘情况,同时也发现了这个参数…

Java项目:网上商城系统(java+jsp+servlert+mysql+ajax)

源码获取:博客首页 "资源" 里下载! 一、项目简述(需求文档PPT) 功能: 主页显示热销商品;所有商品展示,可进行商品搜索;点 击商品进入商品详情页,显示库存&…

clock函数返回负值~ (转)

使用clock() 函数来进行计时,时不时的返回一个很大的负数,怎么检查也检查不出错误,现在找出错误原因,给大家分享一下。 来源网页:http://kebe-jea.blogbus.com/logs/33603387.html 跑实验的时候,结果时不时…

c实现面向对象编程(3)

http://blog.csdn.net/kennyrose/article/details/7564105转载于:https://www.cnblogs.com/pengkunfan/p/3486612.html

echarts - 条形图grid设置距离绘图区域的距离

在一些数据量过大的情况下,在一个固定的区域绘图往往需要对图表绘制区域的大小进行动态改变。这时候设置条形图距离绘图区域上下左右的距离可使用如下方式:表示条形图的柱子距离绘图区左边30%,距离右边40%,而距离顶部和底部分别为…

TitanDB 中使用Compaction Filter ,产生了预期之外几十倍的读I/O

Compaction过程中 产生大量读I/O 的背景 项目中因大value 需求,引入了PingCap 参考Wisckey 思想实现的key-value分离存储 titan, 使用过程中因为有用到Rocksdb本身的 CompactionFilter功能,所以就直接用TitanDB的option 传入了compaction fi…

Java项目:前台+后台精品图书管理系统(java+SSM+jsp+mysql+maven)

源码获取:博客首页 "资源" 里下载! 一、项目简述 功能包括: 登录注册,办理借阅。借阅记录,预约借阅,借出未还, 借阅逾期,学生管理,图书管理,书库分类查询搜索…

消除 activity 启动时白屏、黑屏问题

默认情况下 activity 启动的时候先把屏幕刷成白色&#xff0c;再绘制界面&#xff0c;绘制界面或多或少有点延迟&#xff0c;这段时间中你看到的就是白屏&#xff0c;显然影响用户体验&#xff0c;怎么消除呢&#xff1f; 在 Activity theme 设置style 即可 1 <style na…

理解并实施:HSRP(CCNA200-120新增考点)

理解并实施:HSRP思科热备路由器协议HSRP&#xff08;HotStandby Router Protocol&#xff09;是企业级网络路由器的故障冗余服务。如图9.116所示&#xff0c;192.168.2.0/24的子网需要与目标192.168.5.2的计算机通信。192.168.2.0/24的子网有两台出口路由器&#xff0c;一台是R…

使用机智云APP控制战舰V3 (转)

源&#xff1a;使用机智云APP控制战舰V3 转载于:https://www.cnblogs.com/LittleTiger/p/10725586.html

从JoinBatchGroup 代码细节 来看Rocksdb的相比于leveldb的写入优势

文章目录1. Rocksdb写入模型2. LevelDB写入的优化点3. Rocksdb 的优化1. Busy Loop2. Short Wait -- SOMETIMES busy Loop3. Long-wait4. 测试验证4. 总结1. Rocksdb写入模型 本节讨论一下Rocksdb在写入链路上的一个优化点&#xff0c;这个优化细节可以说将Rocksdb这个存储引擎…

Java项目:嘟嘟网上商城系统(java+jdbc+jsp+mysql+ajax)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 一、项目简述 功能&#xff1a; 商品的分类展示&#xff0c;用户的注册登录&#xff0c;购物车&#xff0c;订单结算&#xff0c; 购物车加减&#xff0c;后台商品管理&#xff0c;分类管理&#xff0c;订单…

SOAPUI请求及mockservice 使用

1、新建soap Project&#xff0c;输入wsdl的地址&#xff0c;运行request 2.邮件Project&#xff0c;建立mockservice&#xff0c;建立多个response&#xff0c;选在mock operation&#xff0c;选择response dispa…

空间直角坐标系与球面坐标互转

空间直角坐标系与球面坐标互转 1 using System;2 using System.Collections.Generic;3 using System.Linq;4 using System.Text;5 6 namespace AppSurveryTools.SphericalAndCartesian7 {8 class CartesianCoord9 { 10 public double x; 11 public dou…