ItGo.me - 专注IT技术分享

首页 > Redis > FastDFS加Redis实现自定义文件名存储海量文件

FastDFS加Redis实现自定义文件名存储海量文件

时间:2016-08-28来源:网友分享 点击:
FastDFS非常适合存储大量的小文件,遗憾的是本身不支持自定义文件名,文件名是存储成功以后根据存储位置生成的一个file_id。很多应用场景不得不使用自定义文件名,在不修改其源码的情况下,可以在存储客户端fdfs_client增加一个用来存储自定义文件名和fastdfs的file_id之间的映射关系的数据库间接实现自定义文件名的存取和访问,在这里我们选用了reids。顺便说一下,淘宝也有一个类似于FastDFS的文件存储系统TFS,对于自定义文件名,它是用mysql来存储映射关系的,我认为在高并发访问下mysql本身就是瓶颈,因此在这个方案中采用了redis。
准备工作:
fastdfs环境安装...略...(官方:
redis环境安装...略...(官方:)
用python实现,因此需要安装fastdfs的python客户端(下载:)
python的redis客户端,到https://
详见博客:标签:<无>
代码片段(2)
1. [代码]    跳至
# -*- coding: utf-8 -*-import settingfrom fdfs_client.client import *from fdfs_client.exceptions import *from fdfs_client.connection import *import redisimport timeimport loggingimport randomlogging.basicConfig(format='[%(levelname)s]: %(message)s', level=logging.DEBUG)logger = logging.getLogger(__name__)logger.setLevel(logging.DEBUG)class RedisError(Exception):def __init__(self, value):self.value = valuedef __str__(self):return repr(self.value)class fastdfsClient(Fdfs_client):def __init__(self):self.tracker_pool = ConnectionPool(**setting.fdfs_tracker)self.timeout  = setting.fdfs_tracker['timeout']return Nonedef __del__(self):try:self.pool.destroy()self.pool = Noneexcept:passclass fastdfs(object):def __init__(self):'''conf_file:配置文件'''self.fdfs_client = fastdfsClient()self.fdfs_redis = []for i in setting.fdfs_redis_dbs:self.fdfs_redis.append(redis.Redis(host=i[0], port=i[1], db=i[2]))def store_by_buffer(self,buf,filename=None,file_ext_name = None):'''buffer存储文件参数:filename:自定义文件名,如果不指定,将远程file_id作为文件名file_ext_name:文件扩展名(可选),如果不指定,将根据自定义文件名智能判断返回值:{'group':组名,'file_id':不含组名的文件ID,'size':文件尺寸,'upload_time':上传时间}'''if filename and  random.choice(self.fdfs_redis).exists(filename):('File(%s) exists.'%filename)return   random.choice(self.fdfs_redis).hgetall(filename)t1 = time.time()#        try:ret_dict = self.fdfs_client.upload_by_buffer(buf,file_ext_name)#        except Exception,e:#            logger.error('Error occurred while uploading: %s'%e.message)#            return Nonet2 = time.time()('Upload file(%s) by buffer, time consume: %fs' % (filename,(t2 - t1)))for key in ret_dict:logger.debug('[+] %s : %s' % (key, ret_dict[key]))stored_filename = ret_dict['Remote file_id']stored_filename_without_group = stored_filename[stored_filename.index('/')+1:]if not filename:filename =stored_filename_without_groupvmp = {'group':ret_dict['Group name'],'file_id':stored_filename_without_group,'size':ret_dict['Uploaded size'],'upload_time':int(time.time()*1000)}try:for i in self.fdfs_redis:if not i.hmset(filename,vmp):raise RedisError('Save Failure')('Store file(%s) by buffer successful' % filename)except Exception,e:logger.error('Save info to Redis failure. rollback...')try:ret_dict = self.fdfs_client.delete_file(stored_filename)except Exception,e:logger.error('Error occurred while deleting: %s'%e.message)return Nonereturn vmpdef remove(self,filename):'''删除文件,filename是用户自定义文件名return True|False'''fileinfo = random.choice(self.fdfs_redis).hgetall(filename)stored_filename = '%s/%s'%(fileinfo['group'],fileinfo['file_id'])try:ret_dict = self.fdfs_client.delete_file(stored_filename)('Remove stored file successful')except Exception,e:logger.error('Error occurred while deleting: %s'%e.message)return Falsefor i in self.fdfs_redis:if not i.delete(filename):logger.error('Remove fileinfo in redis failure')('%s removed.'%filename)return Truedef download(self,filename):'''下载文件返回二进制'''finfo = self.getInfo(filename)if finfo:ret = self.fdfs_client.download_to_buffer('%s/%s'%(finfo['group'],finfo['file_id']))return ret['Content']else:logger.debug('%s is not exists'%filename)return Nonedef list(self,pattern='*'):'''列出文件列表'''return random.choice(self.fdfs_redis).keys(pattern)def getInfo(self,filename):'''获得文件信息return:{'group':组名,'file_id':不含组名的文件ID,'size':文件尺寸,'upload_time':上传时间}'''return random.choice(self.fdfs_redis).hgetall(filename)

2. [代码]    跳至
# -*- coding: utf-8 -*-#fastdfs tracker, multiple tracker supportedfdfs_tracker = {'host_tuple':('192.168.2.233','192.168.2.234'),'port':22122,'timeout':30,'name':'Tracker Pool'}#fastdfs meta db, multiple redisdb supportedfdfs_redis_dbs = (('192.168.2.233',6379,0),('192.168.2.233',6379,1))

FastDFS加Redis实现自定义文件名存储海量文件

FastDFS加Redis实现自定义文件名存储海量文件  讨论


redis集群方案

根据一些测试整理出来的一份方案: 1. Redis 性能 对于redis 的一些简单测试,仅供参考: 测试环境:Redhat6.2 , Xeon E5520(4核)*2/8G,1000M网卡 Redis 版本:2.6.9 客户端机器使用redis-benchmark 简单GET、...

redis安装使用配置

一、安装前的准备 下载redis http://redis.io/download https://github.com/mythz/redis-windows 下载Windows版客户端 (分布式存储)ServiceStack.Redis https://github.com/ServiceStack/ServiceStack.Redis https://servicestack.net/downloa...

Redis的WEB界面管理工具 phpRedisAdmin

有过传统LAMP经验的同学肯定都对phpmyadmin非常熟悉,phpmyadmin是一个PHP的MySQL WEB管理工具,非常实用也非常好用。而本文要介绍的是一个叫phpRedisAdmin的工具,从名字上你就能看到,它是一个PHP的...

FastDFS非常适合存储大量的小文件,遗憾的是本身不支持自定义文件名,文件名是存储成功以后根据存储位置生成的一个file_id。很多应用场景不得不使用自定义文件名,在不修改其源码的情况下
------分隔线----------------------------