当前位置:

首页 > 编程开发 > 如何搭建fastdfs服务及单机redis服务

如何搭建fastdfs服务及单机redis服务

Redis Assistant
Redis Assistant

Redis Assistant 是一款为Redis设计的高效可视化管理与监控工具,提供多种操作模式,高效处理服务器数据。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

立即下载
¥19
Windows/macOS/Linux 2026-08-22
正版软件 Windows macOS软件 Linux 数据库管理工具

fastdfs服务搭建先要安装gcc编译器:yum-yinstallgcc-c++安装lib依赖包tar-zxvfV1.0.43.tar.gzcdlibfastcommon-1.0.43./make.sh./make.shinstallln-s/usr/lib64/libfastcommon.so/usr/local/lib/libfastcommon.soln-s/usr/lib64/libfastcommon.so/usr/lib/libfastcommon.soln-s/usr/lib

本文目录

    fastdfs服务搭建

    先要安装gcc编译器:

    yum -y install gcc-c++

    如何搭建fastdfs服务及单机redis服务

    安装lib依赖包

    tar -zxvf V1.0.43.tar.gz
    cd libfastcommon-1.0.43
    ./make.sh
    ./make.sh install

    如何搭建fastdfs服务及单机redis服务

    ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so
    ln -s /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so
    ln -s /usr/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so
    ln -s /usr/lib64/libfdfsclient.so /usr/lib/libfdfsclient.so

    安装fastdfs服务

    tar -zxvf V6.06.tar.gz
    cd fastdfs-6.06
    ./make.sh
    ./make.sh install

    配置Tracker服务

    mkdir -p /data/fastdfs/tracker
    cd /etc/fdfs
    cp tracker.conf.sample  tracker.conf
    vim tracker.conf

    要修改的内容为

    #启用配置文件(默认启用)
    disabled=false 
    #设置tracker的端口号,通常采用22122这个默认端口
    port=22122 
    #设置tracker的数据文件和日志目录
    base_path=/data/fastdfs/tracker
    #设置http端口号,默认为8080
    http.server_port=80

    启动服务

    #启动
    /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start

    如何搭建fastdfs服务及单机redis服务

    查看是否启动

    #查看启动端口
    ss -ant | grep 22122

    查看启动日志

    #查看启动日志
    tail -f /data/fastdfs/tracker/logs/trackerd.log

    如何搭建fastdfs服务及单机redis服务
    加入开机启动

    vim /etc/rc.d/rc.local

    在加入启动命令

    如何搭建fastdfs服务及单机redis服务
    如果重启后发现未能自动启动则通过命令

    ll /etc/rc.d/rc.local

    检查一下rc.local是否具备可执行权限,若是无可执行权限则通过命令进行授权

    chmod +x /etc/rc.d/rc.local

    配置Storage服务

    mkdir -p /data/fastdfs/storage
    mkdir -p /data/fastdfs/storage/file
    cd /etc/fdfs
    cp storage.conf.sample  storage.conf
    vim storage.conf

    要修改的内容为

    #启用配置文件(默认启用)
    disabled=false
    #组名,根据实际情况修改 
    group_name=group1 
    #设置storage的端口号,默认是23000,同一个组的storage端口号必须一致
    port=23000 
    #设置storage数据文件和日志目录
    base_path=/data/fastdfs/storage 
    #存储路径个数,需要和store_path个数匹配
    store_path_count=1 
    #实际文件存储路径
    store_path0=/data/fastdfs/storage/file
    #tracker 服务器的 IP地址和端口号,如果是单机搭建,IP不要写127.0.0.1,否则启动不成功(此处的ip是我的CentOS虚拟机ip)
    tracker_server=172.16.6.50:22122 
    #设置 http 端口号
    http.server_port=8888

    启动服务

    #启动
    /usr/bin/fdfs_storaged /etc/fdfs/storage.conf start

    查看启动端口

    #查看启动端口
    ss -ant | grep 23000

    查看启动日志

    #查看启动日志
    tail -f /data/fastdfs/storage/logs/storaged.log

    如何搭建fastdfs服务及单机redis服务

    通过monitor查看storage是否绑定成功

    [root@localhost /]# /usr/bin/fdfs_monitor /etc/fdfs/storage.conf
    [2021-09-23 12:59:26] DEBUG - base_path=/opt/fastdfs_storage, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0
    
    server_count=1, server_index=0
    
    tracker server is 172.16.8.11:22122
    
    group count: 1
    
    Group 1:
    group name = group1
    disk total space = 6818 MB
    disk free space = 2169 MB
    trunk free space = 0 MB
    ……

    加入开机启动

    vim /etc/rc.d/rc.local

    在该文件中,加入启动命令

    /usr/bin/fdfs_storaged /etc/fdfs/storage.conf start

    测试验证

    [root@localhost ~]# ps -ef|grep fdfs
    root     10335 17685  0 23:50 pts/3    00:00:00 grep --color=auto fdfs
    root     13335     1  0 13:17 ?        00:00:07 /usr/bin/fdfs_storaged /etc/fdfs/storage.conf start
    root     15779     1  0 12:59 ?        00:00:04 /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf

    用fdfs客户端进行测试

    cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf

    测试时需要设置客户端的配置文件

    vim /etc/fdfs/client.conf

    打开文件后依次做以下修改:

    #tracker服务器文件路径
    base_path=/data/fastdfs/tracker
    #tracker服务器IP地址和端口号
    tracker_server=172.16.7.50:22122
    # tracker 服务器的 http 端口号,必须和tracker的设置对应起来
    http.tracker_server_port=80

    配置完成后就可以模拟文件上传了,先给/data目录下放一文件test.txt,然后通过执行客户端上传命令尝试上传:

    /usr/bin/fdfs_upload_file  /etc/fdfs/client.conf  /data/test.txt

    单机redis服务搭建

    1.获取redis资源,并解压

    tar xzvf redis-4.0.8.tar.gz

    2.安装

    cd redis-4.0.8
    make
    cd src
    make install PREFIX=/usr/local/redis

    3.移动配置文件到安装目录下

    cd ../
    mkdir /usr/local/redis/etc
    mv redis.conf /usr/local/redis/etc

     4.配置redis为后台启动

    vim /usr/local/redis/etc/redis.conf

    注意,将daemonize no 改成daemonize yes,及注释掉bind 127.0.0.1,可以远程访问

    5.将redis加入到开机启动 

    vim /etc/rc.d/rc.local

    在里面添加内容:

    /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

    意思就是开机调用这段开启redis的命令.

    6.启动redis

    /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

    7.将redis-cli,redis-server拷贝到bin下,让redis-cli指令可以在任意目录下直接使用

    cp /usr/local/redis/bin/redis-server /usr/local/bin/
    cp /usr/local/redis/bin/redis-cli /usr/local/bin/

    8.设置redis密码

    a.运行命令:

    redis-cli

    b.查看现有的redis密码(可选操作,可以没有)

    运行命令:

    config get requirepass

    如果没有设置过密码的话运行结果会如下图所示

    如何搭建fastdfs服务及单机redis服务

    c.设置redis密码

    运行命令:

    config set requirepass  *******

    (******为你要设置的密码),设置成功的话会返回‘OK’字样

    d.测试连接

    重启redis服务

    //****为你设置的密码
    redis-cli -h 127.0.0.1 -p 6379 -a ****

    也可以,输入 redis-cli 进入命令模式,使用 auth '*****' (****为你设置的密码)登陆      

    9.让外网能够访问redis

    a.配置防火墙:

    #开放6379端口 
    firewall-cmd --zone=public --add-port=6379/tcp --permanent
    #重启防火墙以使配置即时生效
    systemctl restart firewalld
    #查看系统所有开放的端口
    firewall-cmd --zone=public --list-ports

    b.若是仍不可远程访问:

    此时 虽然防火墙开放了6379端口,但是外网还是无法访问的,因为redis监听的是127.0.0.1:6379,并不监听外网的请求。

    1. 把文件夹目录里的redis.conf配置文件里的bind 127.0.0.1前面加#注释掉

    2. 命令:redis-cli连接到redis后,通过 config get  daemonize和config get  protected-mode 是不是都为no,如果不是,就用config set 配置名 属性 改为no。

    其他redis相关常用命令  

    卸载redis:

    #停止redis
    pkill redis   
    #删除安装目录
    rm -rf /usr/local/redis 
    #删除所有redis相关命令脚本
    rm -rf /usr/bin/redis-* 
    #删除redis解压文件夹
    rm -rf /root/download/redis-4.0.4

    报异常,尝试重启

    原因: Redis已经启动

    解决: 关掉Redis,重启即可 

    redis-cli shutdown 
    redis-server &

    然后你就能看到Redis愉快的运行了.

    客户端检测连接是否正常

    使用redis-cli客户端检测连接是否正常

    $redis-cli 
    127.0.0.1:6379> keys * 
    (empty list or set) 
    127.0.0.1:6379> set key "hello world" 
    OK 
    127.0.0.1:6379> get key 
    "hello world"

    Redis客户端常见操作

    Redis是key-value数据库,支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

    当value是string类型,命令包括set get setnx incr del 等。

    > set server:name "fido"  // 设置键值
    OK
    > get server:name  // 获取键值
    "fido"
    > setnx connections 10   // set if not exists
    OK
    > incr connections   // 原子性增加values值
    (integer) 11
    > incr connections
    (integer) 12
    > del connections  // 删除key
    (integer) 1
    > incr connections
    (integer) 1

    当value是list类型,命令包括rpush lpush llen lrange lpop rpop del 等。

    > rpush friends "Alice"   // 在末尾追加
    (integer) 1
    > rpush friends "Bob"
    (integer) 2
    > lpush friends "Sam"    // 插入到开头
    (integer) 3 
    > lrange friends 0 -1     // 返回列表的子集,类似切片操作
    1) "Sam"
    2) "Alice"
    3) "Bob"
    > lrange friends 0 1
    1) "Sam"
    2) "Alice"
    > lrange friends 1 2
    1) "Alice"
    2) "Bob" 
    > llen friends   // 返回列表长度
    (integer) 3
    > lpop friends   // 删除并返回列表第一个元素
    "Sam"
    > rpop friends   // 删除并返回列表最后一个元素
    "Bob"
    > lrange friends 0 -1
    1) "Alice" 
    > del friends    // 删除key
    (integer) 1     // 1表示成功,0表示失败

    当value是set类型,命令包括sadd srem sismember smembers sunion del等。

    > sadd superpowers "flight"     // 添加元素
    (integer) 1
    > sadd superpowers "x-ray vision"
    (integer) 1
    > sadd superpowers "reflexes"
    (integer) 1
    > srem superpowers "reflexes"   // 删除元素1
     
    > sismember superpowers "flight"   // 测试元素是否在集合中
    (integer) 1
    > sismember superpowers "reflexes"
    (integer) 0
    > smembers superpowers    // 返回集合中所有元素
    1) "x-ray vision"
    2) "flight" 
    > sadd birdpowers "pecking"
    (integer) 1
    > sadd birdpowers "flight"
    (integer) 1
    > sunion superpowers birdpowers    // 合并多个set,返回合并后的元素列表
    1) "x-ray vision"
    2) "flight"
    3) "pecking" 
    > del superpowers   // 删除key
    (integer) 1

    当value是zset类型,命令包括 zadd zrange del等,注意给value一个编号用于排序。

    > zadd hacker 1940 "Alan Kay"     // 给value指定一个编号,比如以年份1940作为编号
    (integer) 1
    > zadd hacker 1906 "Grace Hopper"
    (integer) 1
    > zadd hacker 1953 "Richard Stallman"
    (integer) 1
    > zadd hacker 1965 "Yukihiro Matsumoto"
    (integer) 1
    > zadd hacker 1916 "Claude Shannon"
    (integer) 1
    > zadd hacker 1969 "Linux Torvalds"
    (integer) 1
    > zadd hacker 1957 "Sophie Wilson"
    (integer) 1
    > zadd hacker 1912 "Alan Turing"
    (integer) 1
     
    > zrange hacker 2 4    // 切片返回有序集合中元素
    1) "Claude Shannon"
    2) "Alan Kay"
    3) "Richard Stallman"
     
    > del hacker    // 删除key
    (integer) 1

    当value是hash类型,hash类型可以理解为字典,需要给value指定一个field用于映射,命令包括hset hmset hget hgetall hdel hincrby del 等。

    > hset user:1000 name "John Smith"   // 给value指定一个field,比如name
    (integer) 1
    > hset user:1000 email "john.smith@example.com"
    (integer) 1
    > hset user:1000 password "s3cret"
    (integer) 1
    > hgetall user:1000   // 获得hash表中所有成员,包括field和value
    1) "name"
    2) "John Smith"
    3) "email"
    4) "john.smith@example.com"
    5) "password"
    6) "s3cret"
     
    > hmset user:1001 name "Mary Jones" password "hidden" email
    "mjones@example.com"   // 设置多个field和value
    OK
    > hget user:1001 name   // 根据field获取value
    "Mary Jones"
      
    > hset user:1000 visits 10    // field可以映射到数字值
    (integer) 1
    > hincrby user:1000 visits 1    // 原子性增加value的值,增加1
    (integer) 11
    > hincrby user:1000 visits 10    // 增加10
    (integer) 21
    > hdel user:1000 visits      // 删除field及其value
    (integer) 1
    > hincrby user:1000 visits 1
    (integer) 1
     
    > del user:1000     // 删除key
    (integer) 1

    设置和查看key的生命周期,key过期会被自动删除,命令包括expire ttl 等。

    > set resource:lock "Redis Demo"
    OK
    > expire resource:lock 120   // 设置生命周期为120s
    (integer) 1
    > ttl resource:lock   // 查看当前生命周期还剩多少时间
    (integer) 109
    > ttl resource:lock   // 120s后查看,返回-2表示已过期或不存在
    (integer) -2
     
    > set resource:lock "Redis Demo 2"
    OK
    > ttl resource:lock    // 返回-1表示永不过期
    (integer) -1

    springboot实现h5与fastdfs之间的断点续传,大文件上传,秒传文件和批量上传 

    对比,只是单纯返回一个String类型?

    如何搭建fastdfs服务及单机redis服务

    改为upload_list8888,页面调用是失败的

    如何搭建fastdfs服务及单机redis服务

    改回upload_list

    如何搭建fastdfs服务及单机redis服务

    ThreadLocal与redis秒配,解决了redis线程池在被共享访问时带来的线程安全问题

    打个比方,现在公司所有人都要填写一个表格,但是只有一支笔,这个时候就只能上个人用完了之后,下个人才可以使用,为了保证"笔"这个资源的可用性,只需要保证在接下来每个人的获取顺序就可以了,这就是 lock 的作用,当这支笔被别人用的时候,我就加 lock ,你来了那就进入队列排队等待获取资源(非公平方式那就另外说了),这支笔用完之后就释放 lock ,然后按照顺序给下个人使用。

    但是完全可以一个人一支笔对不对,这样的话,你填写你的表格,我填写我的表格,咱俩谁都不耽搁谁。这就是 ThreadLocal 在做的事情,因为每个 Thread 都有一个副本,就不存在资源竞争,所以也就不需要加锁,这不就是拿空间去换了时间嘛!

    了解决redis线程池对象(笔),不能被多线程(多个人)共享访问的问题,通过 threadLocal.set() 方法,将redis线程池对象实例保存在每个线程,自己所拥有的 threadLocalMap中(生成多个副本)。

    这样的话,每个线程都使用自己的redis线程池对象实例,彼此不会影响,从而达到了隔离的作用,这样就解决了redis线程池对象在被共享访问时带来的线程安全问题。

    如何搭建fastdfs服务及单机redis服务

    import cn.hutool.core.util.StrUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
    
    import java.util.List;
    
    
    public class RedisUtil {
    
        private RedisUtil() {
        }
        private static Logger _logger = LoggerFactory.getLogger(RedisUtil.class);
        ;
    
        protected static final  ThreadLocal threadLocalJedis = new ThreadLocal();
    
        //Redis服务器IP
        private static String ADDR_ARRAY = ReadProper.getResourceValue("spring.redis.host");
    
        //Redis的端口号
        private static int PORT = Integer.parseInt(ReadProper.getResourceValue("spring.redis.port"));
    
        //访问密码
        private static String AUTH = ReadProper.getResourceValue("spring.redis.password");
    
        //可用连接实例的最大数目,默认值为8;
        //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
        private static int MAX_ACTIVE = -1;
    
        //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
        private static int MAX_IDLE = 16;
    
        //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
        private static int MAX_WAIT = 1000 * 5;
    
        //超时时间
        private static int TIMEOUT = 1000 * 5;
    
        //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
        private static boolean TEST_ON_BORROW = true;
    
        private static JedisPool jedisPool ;
    
        //默认的数据库为0
    
    
    
        /**
         * redis过期时间,以秒为单位
         */
        public final static int EXRP_HOUR = 60 * 60;          //一小时
        public final static int EXRP_DAY = 60 * 60 * 24;        //一天
        public final static int EXRP_MONTH = 60 * 60 * 24 * 30;   //一个月
    
    
    
    
    
        /**
         * 初始化Redis连接池,注意一定要在使用前初始化一次,一般在项目启动时初始化就行了
         */
        public static JedisPool  initialPool() {
            JedisPool jp=null;
            try {
                JedisPoolConfig config = new JedisPoolConfig();
                config.setMaxTotal(MAX_ACTIVE);
                config.setMaxIdle(MAX_IDLE);
                config.setMaxWaitMillis(MAX_WAIT);
                config.setTestOnBorrow(TEST_ON_BORROW);
                config.setTestOnCreate(true);
                config.setTestWhileIdle(true);
                config.setTestOnReturn(true);
                config.setNumTestsPerEvictionRun(-1);
                jp = new JedisPool(config, ADDR_ARRAY, PORT, TIMEOUT, AUTH);
                jedisPool=jp;
                threadLocalJedis.set(getJedis());
            } catch (Exception e) {
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
    
            }
    
            return  jp;
        }
    
    
    
        public static void close(Jedis jedis) {
            if (threadLocalJedis.get() == null && jedis != null){
                jedis.close();
            }
        }
    
    
    
    
    
    
    //    /**
    //     * 在多线程环境同步初始化
    //     */
    //    private static synchronized void poolInit() {
    //        if (jedisPool == null) {
    //            initialPool();
    //        }
    //    }
    
    
        /**
         * 获取Jedis实例,一定先初始化
         *
         * @return Jedis
         */
        public static Jedis getJedis() {
            boolean success = false;
            Jedis jedis = null;
    //        if (jedisPool == null) {
    //            poolInit();
    //        }
            int i=0;
            while (!success) {
                i++;
                try {
                    if (jedisPool != null) {
                        jedis=threadLocalJedis.get();
                        if (jedis==null){
                            jedis = jedisPool.getResource();
                        }else {
                           if(! jedis.isConnected()&&!jedis.getClient().isBroken()){
                               threadLocalJedis.set(null);
                               jedis = jedisPool.getResource();
                           }
                            //System.out.println(Thread.currentThread().getName()+":第"+i+"次获取成功#@利用了本地缓存redis");
                            return jedis;
                        }
    
                    }else {
                        throw new RuntimeException("redis连接池初始化失败");
                    }
                } catch (Exception e) {
    
                   System.out.println(Thread.currentThread().getName()+":第"+i+"次获取失败!!!");
                    success = false;
                    e.printStackTrace();
                    _logger.error("redis服务器异常",e);
                }
                if (jedis!=null){
                    success=true;
                }
    
                if (i>=10&&i<20){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                }
    
                if (i>=20&&i<30){
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                }
    
                if (i>=30&&i<40){
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                }
    
                if (i>=40){
                    System.out.println("redis彻底连不上了~~~~(>_<)~~~~");
                    return null;
                }
    
            }
            if (threadLocalJedis.get()==null){threadLocalJedis.set(jedis);}
            //System.out.println(Thread.currentThread().getName()+":第"+i+"次获取成功@");
            return jedis;
        }
    
    
    
    
        /**
         * 设置 String
         *
         * @param key
         * @param value
         */
        public static void setString(String key, String value) {
            Jedis jo = null;
            try {
    
                value = StrUtil.isBlank(value) ? "" : value;
                jo = getJedis();
                jo.set(key, value);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis服务器异常");
            } finally {
                if (jo != null) {
                    close(jo);
                }
    
            }
        }
    
        /**
         * 设置 过期时间
         *
         * @param key
         * @param seconds 以秒为单位
         * @param value
         */
        public static void setString(String key, int seconds, String value) {
            Jedis jo = null;
            try {
                value = StrUtil.isBlank(value) ? "" : value;
                jo = getJedis();
                jo.setex(key, seconds, value);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis服务器异常");
            } finally {
                if (jo != null) {
                    close(jo);
    
                }
            }
    
    
        }
    
        /**
         * 获取String值
         *
         * @param key
         * @return value
         */
        public static String getString(String key) {
            Jedis jo = null;
    
            try {
                jo = getJedis();
    
                if (jo == null || !jo.exists(key)) {
                    return null;
                }
                return jo.get(key);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis操作错误");
            } finally {
                if (jo != null) {
                    close(jo);
                }
            }
    
    
        }
    
        public static long incrBy(String key, long integer) {
            Jedis jo = null;
            try {
                jo = getJedis();
    
                return jo.incrBy(key, integer);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis操作错误");
            } finally {
                if (jo != null) {
                    close(jo);
                }
            }
    
        }
    
        public static long decrBy(String key, long integer) {
            Jedis jo = null;
            try {
                jo = getJedis();
                return jo.decrBy(key, integer);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis操作错误");
            } finally {
                if (jo != null) {
                    close(jo);
                }
            }
    
        }
    
        //删除多个key
        public static  long  delKeys(String [] keys){
            Jedis jo = null;
            try {
                jo = getJedis();
                return jo.del(keys);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis操作错误");
            } finally {
                if (jo != null) {
                    close(jo);
                }
            }
    
        }
    
        //删除单个key
        public static  long  delKey(String  key){
            Jedis jo = null;
            try {
                jo = getJedis();
                return jo.del(key);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis操作错误");
            } finally {
                if (jo != null) {
                    close(jo);
                }
            }
    
        }
    
        //添加到队列尾
        public static  long  rpush(String  key,String node){
            Jedis jo = null;
            try {
                jo = getJedis();
                return jo.rpush(key,node);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis操作错误");
            } finally {
                if (jo != null) {
                    close(jo);
                }
            }
    
        }
    
    
        //删除list元素
        public static  long  delListNode(String  key,int count,String value){
            Jedis jo = null;
            try {
                jo = getJedis();
                return jo.lrem(key,count,value);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis操作错误");
            } finally {
                if (jo != null) {
                    close(jo);
                }
            }
    
        }
    
    
    
    
        //获取所有list
    
        public static List getListAll(String key){
            Jedis jo = null;
            List list=null;
            try {
                jo = getJedis();
                list=    jo.lrange(key,0,-1);
            } catch (Exception e) {
                threadLocalJedis.set(null);
                e.printStackTrace();
                _logger.error("redis服务器异常",e);
                throw new  RuntimeException("redis操作错误");
            } finally {
                if (jo != null) {
                    close(jo);
                }
            }
            return  list;
        }
    
        //清理缓存redis
        public  static  void cleanLoacl(Jedis jo){
            threadLocalJedis.set(null);
            close(jo);
        }
    
    static {
      initialPool();
    }
    
    }

    使用webuploader组件实现大文件分片上传,断点续传

    webuploader:是一个以HTML5为主, Flash为辅的文件上传组件,采用大文件分片/并发上传的方式,极大地提高了文件上传的效率,同时兼容多种浏览器版本;

    前端

    如何搭建fastdfs服务及单机redis服务

    引入百度Webuploader组件,需要注意标签的id/nama属性,这些将在后面的JavaScript中使用到进行文件切分、验证。

    如何搭建fastdfs服务及单机redis服务

    以上js组件,将完成文件上传、MD5验证、删除、切片、上传进度条显示、暂停、继续上传及上传成功/失败时候的回调。

    后端

    前端,给后端提供封装的chunk,及request

    如何搭建fastdfs服务及单机redis服务

    后端,主要是判断文件是否有分片,如果没有,则直接存放到目的目录;

    如果存在分片,则创建临时目录,存放分片信息;

    之后判断当前分片所属的文件的所有分片是否已经传输完毕,如果当前分片数==所属文件总分片数,则开始合并文件并转移完整文件到目的目录,并且删除临时目录

    如何搭建fastdfs服务及单机redis服务

    检测完文件,以后,开始上传操作

    //上传操作
    path = appendFileStorageClient.uploadAppenderFile(UpLoadConstant.DEFAULT_GROUP, file.getInputStream(),file.getSize(), FileUtil.extName((String) paramMap.get("name")));
    //更新操作
    appendFileStorageClient.modifyFile(UpLoadConstant.DEFAULT_GROUP, noGroupPath, file.getInputStream(),file.getSize(),historyUpload);

    hutool工具的巧妙运用

    可参考hutool资料http://www.mianshigee.com/tutorial/hutool/26e24c7a37d93249.md

    
        cn.hutool
        hutool-all
        5.0.6
    

    cn.hutool.core.collection.CollUtil判断非空

    如何搭建fastdfs服务及单机redis服务

    cn.hutool.json.JSONObject与JSONUtil

    if (CollUtil.isNotEmpty(fileList)){
                for (String e:fileList){
                    JSONObject jsonObject= JSONUtil.parseObj(e);
                    jsonObjects.add(jsonObject);
    
                }
            }

    cn.hutool.core.convert.Convert类型转换

    如何搭建fastdfs服务及单机redis服务

    cn.hutool.core.util.RandomUtil生成随机字符串及StrUtil判断字符为空

    如何搭建fastdfs服务及单机redis服务

    解析文件的扩展名,来获该文件的类型

    import cn.hutool.core.io.FileUtil;
    FileUtil.extName((String) paramMap.get("name")));
    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    php72w redis,docker php7安装php-redis
    php72w redis,docker php7安装php-redis

    在Docker环境下为PHP安装Redis扩展:手动编译需下载源码、安装phpize、配置编译并安装,生成redis.so并在php.d目录新建redis.ini加载,重启PHP-FPM;也可直接yum安装php72w-pecl-redis,免手动编译。

    php 如何配置 redis,php 如何设置redis
    php 如何配置 redis,php 如何设置redis

    配置PHP的Redis扩展:先安装Redis服务,从GitHub下载phpredis源码,用phpize编译安装,修改php.ini添加extension=redis.so,重启php-fpm或Apache,通过phpinfo验证并连接Redis。

    c++如何将结构体序列化为Redis兼容的RESP协议格式【深度】
    c++如何将结构体序列化为Redis兼容的RESP协议格式【深度】

    C++结构体无法直接序列化为RESP协议,需手动将字段映射为*N数组嵌套$lenbulkstring形式。整数需转换为字符串并加:前缀,空字符串用$0\r\n,null用$-1\r\n。长度计算需精确到字节数,特别注意二进制安全,同时确保字段顺序与结构体定义一致。

    如何在Golang架构中部署Redict作为高能数据临时存储中转站
    如何在Golang架构中部署Redict作为高能数据临时存储中转站

    Redis作为跨服务临时状态枢纽,需按消息队列、缓存和原子状态三重角色设计。选型用List实现任务分发及延迟重试,Stream用于事件广播与位点回溯。go-redis/v8需配置MinIdleConns、MaxRetries及超时。数据写入应JSON序列化并带type标签、设合理TTL、将关键字段提至顶层。消费通过原子GET+DEL或processedkey

    TP8.0 高并发下库存超卖?Redis 原子递减结合数据库乐观锁控制
    TP8.0 高并发下库存超卖?Redis 原子递减结合数据库乐观锁控制

    在高并发秒杀场景下,利用Redis的减库存原子操作预扣减库存拦截超卖请求,再通过数据库乐观锁(版本号与库存校验)确保最终一致性,异常时回滚Redis库存并借助Lua脚本保证原子性,从而有效防止库存超卖。

    如何在 Go 中利用 go-redis 执行 Lua 脚本优化逻辑
    如何在 Go 中利用 go-redis 执行 Lua 脚本优化逻辑

    在Go中使用go-redis执行Lua脚本可借助原子性解决竞态问题,通过redis.Script封装脚本并自动处理SHA1缓存与重试。需注意KEYS必须为非空切片且所有键在Cluster模式下落在同一slot,ARGV以字符串传入并由tonumber转换。返回值需先检查错误再调用Val(),避免panic。

    TP6.0 基于 Redis SetNX 实现的简单互斥锁机制【并发】
    TP6.0 基于 Redis SetNX 实现的简单互斥锁机制【并发】

    先看一个典型场景:电商秒杀、库存扣减、定时任务重复调度——这些并发冲突在 TP6 应用里屡见不鲜。用 Redis 的 SETNX 做互斥锁,确实是轻量又直接的方案,但“能用”和“稳妥”之间,隔着三层硬功夫:原子加锁、身份校验、合理超时。这三条,差一条就翻车。 很多人第一次上手,直接写 SETNX 加

    TP6.0 如何处理高并发抢购?Redis 原子锁与队列削峰详解【秒杀】
    TP6.0 如何处理高并发抢购?Redis 原子锁与队列削峰详解【秒杀】

    高并发抢购中,Redis的DECR原子操作可安全扣库存;配合think-queue异步削峰,接口仅扣库存和推消息;分布式锁需用SETNXEX加唯一标识,释放时用Lua脚本校验;成功资格后须以数据库事务双写为准,失败时补回Redis库存。

    Golang 实现基于 Redis 的延时任务队列
    Golang 实现基于 Redis 的延时任务队列

    基于Redis的ZSET实现延时队列需解决并发重复消费、失败重试混乱、精度不足及内存爆炸等问题。通过Lua脚本保证取删原子性,使用毫秒级时间戳,对临时错误采用指数退避重试,永久错误记入独立哈希表,并限制最大延迟、定期清理过期任务、使用紧凑序列化格式。

    RedisInsight怎么修改Key的过期时间 Redis操作方法【步骤】
    RedisInsight怎么修改Key的过期时间 Redis操作方法【步骤】

    操作 Redis 的时候,改个 Key 的过期时间其实是个高频场景。特别是做运维排查或者临时调试那会儿,谁也不想反复切命令行窗口、背那些命令参数。好在 RedisInsight 这个图形工具把这事儿做得很顺手——三种方式任选,总有一种合你胃口。 在动手前,先确认一下 Key 当前的 TTL 状态是个

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。

    即将离开本站
    您即将前往第三方网站,请确认是否继续?