news 2025/12/31 10:12:38

Redis 如何应对大数据高并发访问挑战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis 如何应对大数据高并发访问挑战

Redis如何应对大数据高并发访问挑战:从原理到实践的深度解析

摘要

在电商秒杀、实时推荐、分布式缓存等高并发场景中,传统关系型数据库(如MySQL)因磁盘IO瓶颈、连接数限制等问题,无法满足每秒数万甚至数十万次的请求需求。Redis作为内存数据库,凭借其单线程模型高效数据结构分布式架构,成为解决高并发问题的核心工具。

本文将从问题背景核心机制实践优化三个维度,深入解析Redis如何应对大数据高并发挑战。你将学到:

  • Redis单线程模型为何能处理高并发?
  • 如何用原子操作、Pipeline、Lua脚本解决并发竞争?
  • 集群架构如何扩展Redis的容量与并发能力?
  • 高并发场景下的最佳实践与常见坑点。

目标读者与前置知识

目标读者

  • 初级/中级后端工程师(使用过Redis但对其高并发机制不熟悉);
  • 架构师(需要设计高并发系统的缓存层);
  • 测试/运维工程师(需要理解Redis性能瓶颈)。

前置知识

  • 熟悉Redis的基本使用(如字符串、哈希、列表等数据结构);
  • 了解HTTP请求流程与网络基础(如TCP连接、往返时间RTT);
  • 具备一定的后端开发经验(如Python/Java等语言)。

文章目录

  1. 引言:高并发场景下的Redis角色
  2. 问题背景:传统数据库的高并发瓶颈
  3. 核心原理:Redis为何能处理高并发?
    • 3.1 单线程模型:避免上下文切换的奥秘
    • 3.2 IO多路复用:高效处理 thousands of 连接
    • 3.3 高效数据结构:跳表、哈希表的性能优势
  4. 实践优化:高并发场景下的Redis使用技巧
    • 4.1 原子操作:用DECR/INCR解决秒杀超卖问题
    • 4.2 Pipeline:批量操作减少网络开销
    • 4.3 Lua脚本:复杂逻辑的原子性保证
    • 4.4 集群架构:横向扩展容量与并发
  5. 性能验证:压测与结果分析
  6. 最佳实践:避免高并发陷阱
  7. 未来展望:Redis的高并发进化方向
  8. 总结:Redis高并发能力的本质

1. 引言:高并发场景下的Redis角色

想象一个电商秒杀场景:某款手机限量100台,开抢1秒内有10万用户同时点击“购买”按钮。此时,系统需要快速处理以下操作:

  • 检查用户是否登录;
  • 验证库存是否充足;
  • 扣减库存;
  • 生成订单;
  • 通知用户下单成功。

如果用MySQL处理这些操作,每一步都需要磁盘IO(如查询库存、更新库存),而磁盘IO的速度约为1000次/秒,根本无法应对10万次/秒的请求。此时,Redis的内存操作(速度约为100万次/秒)成为救星——它可以将库存、用户会话等高频数据缓存到内存中,快速处理高并发请求。

2. 问题背景:传统数据库的高并发瓶颈

传统关系型数据库(如MySQL)的高并发瓶颈主要来自以下三点:

  1. 磁盘IO瓶颈:数据存储在磁盘上,读取/写入速度慢(约100-1000次/秒);
  2. 连接数限制:MySQL的默认连接数约为100,无法处理 thousands of 并发连接;
  3. 锁机制:为了保证事务一致性,MySQL使用行锁/表锁,高并发下容易出现锁等待,导致性能下降。

Redis作为内存数据库,完美解决了这些问题:

  • 内存操作:数据存储在内存中,读取/写入速度约为10万-100万次/秒
  • 连接数支持:Redis支持 thousands of 并发连接(通过IO多路复用);
  • 无锁机制:单线程模型避免了锁竞争,保证了命令的原子性。

3. 核心原理:Redis为何能处理高并发?

要理解Redis的高并发能力,必须掌握其三大核心机制单线程模型IO多路复用高效数据结构

3.1 单线程模型:避免上下文切换的奥秘

误区:单线程=低并发?

很多人认为“单线程无法处理高并发”,但Redis的单线程模型却能处理10万+ QPS(每秒请求数)。原因在于:

  • 内存操作:Redis的所有命令都在内存中执行,速度极快(约1纳秒/次);
  • 无上下文切换:单线程不需要切换线程上下文(切换成本约为1-10微秒/次),减少了性能开销;
  • 原子性保证:单线程模型下,命令的执行是串行的,避免了并发竞争(如多个线程同时修改同一数据)。
单线程模型的工作流程

Redis的单线程模型主要处理以下任务:

  1. 接收客户端连接:通过socket监听端口(默认6379);
  2. 处理命令请求:从socket中读取客户端发送的命令(如SET、GET);
  3. 执行命令:根据命令类型操作内存中的数据结构(如哈希表、跳表);
  4. 返回结果:将命令执行结果写入socket,返回给客户端。

3.2 IO多路复用:高效处理 thousands of 连接

问题:单线程如何处理多个连接?

如果Redis用单线程逐个处理客户端连接,当某个连接的IO操作(如读取命令、写入结果)阻塞时,其他连接会被卡住。例如,当客户端发送一个大命令(如SET key value,其中value很大),Redis需要等待所有数据接收完成才能处理下一个命令,导致并发能力下降。

解决方案:IO多路复用

Redis使用IO多路复用技术(如Linux的epoll、Windows的IOCP),可以在单线程下同时监控多个socket的IO事件(如“可读”、“可写”)。当某个socket的IO事件触发时,Redis才会处理该socket的请求,避免了阻塞。

IO多路复用的工作流程

以epoll为例,Redis的IO多路复用流程如下:

  1. 注册事件:Redis将所有客户端的socket注册到epoll实例中,监听“可读”事件(客户端发送命令)和“可写”事件(Redis返回结果);
  2. 等待事件:epoll_wait()函数阻塞等待,直到有socket的IO事件触发;
  3. 处理事件:当某个socket的“可读”事件触发时,Redis读取客户端发送的命令;当“可写”事件触发时,Redis将结果写入socket;
  4. 循环处理:重复步骤2-3,处理所有触发的IO事件。
为什么epoll高效?

epoll的高效性来自以下两点:

  • 事件驱动:只有当socket的IO事件触发时才会处理,避免了轮询所有socket(如select/poll的轮询方式,时间复杂度为O(n));
  • 内存映射:epoll使用mmap(内存映射)将事件列表映射到用户空间,避免了内核与用户空间之间的数据拷贝(如select/poll需要将事件列表从内核空间拷贝到用户空间)。

3.3 高效数据结构:跳表、哈希表的性能优势

Redis的高并发能力还依赖于高效的数据结构,这些数据结构的设计目标是快速查找、插入、删除(时间复杂度尽可能低)。

1. 哈希表(Hash Table)
  • 用途:存储键值对(如SET key value、GET key);
  • 结构:Redis的哈希表采用链式哈希(数组+链表)结构,当哈希冲突时,用链表存储冲突的键值对;
  • 性能:查找、插入、删除的时间复杂度为O(1)(平均情况);
  • 优化:当链表长度超过阈值(默认8)时,Redis会将链表转换为跳表(Skip List),进一步提高查询性能(时间复杂度为O(log n))。
2. 跳表(Skip List)
  • 用途:存储有序集合(如ZSET);
  • 结构:跳表是一种多层链表,每一层都是下一层的子集。例如,第一层是所有元素的链表,第二层是第一层的子集(每隔一个元素取一个),第三层是第二层的子集,依此类推;
  • 性能:查找、插入、删除的时间复杂度为O(log n)(与平衡二叉树相当,但实现更简单);
  • 优势:跳表的插入、删除操作不需要像平衡二叉树那样进行旋转(如AVL树、红黑树),因此更适合高并发场景。
3. 其他数据结构
  • 字符串(String):采用简单动态字符串(SDS)结构,支持快速扩展和收缩;
  • 列表(List):采用双向链表结构,支持快速插入、删除(时间复杂度O(1));
  • 集合(Set):采用哈希表结构,支持快速去重(时间复杂度O(1))。

4. 实践优化:高并发场景下的Redis使用技巧

了解了Redis的核心原理后,我们需要将这些原理应用到实际场景中,解决高并发下的具体问题。以下是四个常见的高并发场景及对应的Redis优化方案:

4.1 原子操作:用DECR/INCR解决秒杀超卖问题

场景:秒杀库存扣减

在电商秒杀场景中,库存扣减是一个典型的高并发问题。例如,某商品的库存为100,当10万用户同时点击“购买”按钮时,如何保证库存不会被超卖(即库存变为负数)?

传统方案的问题

如果用MySQL处理库存扣减,通常的流程是:

  1. 查询库存:SELECT stock FROM product WHERE id = 1001;
  2. 判断库存是否充足:如果stock > 0,则扣减库存;
  3. 更新库存:UPDATE product SET stock = stock - 1 WHERE id = 1001;

这种方案的问题在于非原子性:当两个请求同时执行步骤1时,都查询到库存为100,然后都执行步骤3,导致库存变为98(而不是99),出现超卖。

Redis的解决方案:原子操作

Redis提供了原子操作(如DECR、INCR、SETNX),可以保证命令的执行是原子的(即不会被其他命令中断)。例如,用DECR命令扣减库存:

importredis r=redis.Redis(host='localhost',port=6379)defdeduct_stock(product_id):# 库存键:stock:{product_id}stock_key=f'stock:{product_id}'# 原子扣减库存(DECR命令)remaining_stock=r.decr(stock_key)ifremaining_stock>=0:print(f'库存扣减成功,剩余库存:{remaining_stock}')returnTrueelse:print(f'库存不足,扣减失败')# 回滚库存(因为DECR到了负数)r.incr(stock_key)returnFalse
原子操作的原理

DECR命令的执行过程是原子的:Redis在执行DECR命令时,不会处理其他命令,直到DECR执行完成。例如,当两个请求同时调用DECR stock:1001,Redis会先处理第一个请求(将库存从100减到99),然后处理第二个请求(将库存从99减到98),不会出现同时减到99的情况。

4.2 Pipeline:批量操作减少网络开销

问题:网络延迟影响性能

在高并发场景下,网络延迟是一个重要的性能瓶颈。例如,客户端与Redis服务器之间的网络延迟为1ms,那么每秒钟最多可以处理1000次请求(1秒/1ms)。如果需要处理10万次请求,需要100秒,这显然无法满足需求。

解决方案:Pipeline

Redis的Pipeline(管道)功能可以将多个命令批量发送给Redis服务器,减少网络往返次数。例如,批量获取10个用户的信息:

# 不用Pipeline的情况(10次网络往返)user_ids=[1,2,3,...,10]users=[]foruser_idinuser_ids:user=r.hgetall(f'user:{user_id}')users.append(user)# 用Pipeline的情况(1次网络往返)pipe=r.pipeline()foruser_idinuser_ids:pipe.hgetall(f'user:{user_id}')# 批量执行命令users=pipe.execute()
Pipeline的性能提升

假设网络延迟为1ms,不用Pipeline时,10次请求需要10ms(10×1ms);用Pipeline时,1次请求需要1ms(批量发送10条命令),性能提升了10倍。

注意事项
  • Pipeline中的命令是批量执行的,Redis会将所有命令执行完成后,一次性返回结果;
  • Pipeline中的命令不保证原子性(即如果其中一个命令执行失败,其他命令可能已经执行成功);
  • 不要将过大的Pipeline(如包含1000条命令)发送给Redis,否则会占用过多的内存和CPU时间。

4.3 Lua脚本:复杂逻辑的原子性保证

问题:原子操作无法处理复杂逻辑

原子操作(如DECR)只能处理简单的逻辑(如扣减库存),但对于复杂的逻辑(如扣减库存+记录日志+发送通知),原子操作无法满足需求。例如,需要执行以下步骤:

  1. 检查库存是否充足;
  2. 扣减库存;
  3. 记录扣减日志(如将用户ID添加到日志列表);
  4. 发送通知(如将用户ID添加到通知队列)。

如果用多个原子操作(如DECR、LPUSH),无法保证这些步骤的原子性(即如果其中一个步骤失败,其他步骤可能已经执行成功)。

解决方案:Lua脚本

Redis支持Lua脚本(从2.6版本开始),可以将多个命令封装到一个Lua脚本中,保证脚本的执行是原子的(即Redis在执行Lua脚本时,不会处理其他命令,直到脚本执行完成)。

例如,用Lua脚本处理复杂的库存扣减逻辑:

-- 库存扣减Lua脚本-- KEYS[1]:库存键(stock:{product_id})-- KEYS[2]:日志键(log:{product_id})-- KEYS[3]:通知队列键(notify:queue)-- ARGV[1]:用户ID(user_id)localstock_key=KEYS[1]locallog_key=KEYS[2]localnotify_queue_key=KEYS[3]localuser_id=ARGV[1]-- 1. 检查库存是否充足localremaining_stock=redis.call('GET',stock_key)ifnotremaining_stockortonumber(remaining_stock)<=0thenreturn0-- 库存不足,返回0end-- 2. 扣减库存(原子操作)redis.call('DECR',stock_key)-- 3. 记录扣减日志(LPUSH:将用户ID添加到日志列表的头部)redis.call('LPUSH',log_key,user_id)-- 4. 发送通知(LPUSH:将用户ID添加到通知队列的头部)redis.call('LPUSH',notify_queue_key,user_id)return1-- 扣减成功,返回1
用Python执行Lua脚本
importredis r=redis.Redis(host='localhost',port=6379)# 加载Lua脚本lua_script=""" local stock_key = KEYS[1] local log_key = KEYS[2] local notify_queue_key = KEYS[3] local user_id = ARGV[1] local remaining_stock = redis.call('GET', stock_key) if not remaining_stock or tonumber(remaining_stock) <= 0 then return 0 end redis.call('DECR', stock_key) redis.call('LPUSH', log_key, user_id) redis.call('LPUSH', notify_queue_key, user_id) return 1 """# 执行Lua脚本defdeduct_stock_with_log(product_id,user_id):stock_key=f'stock:{product_id}'log_key=f'log:{product_id}'notify_queue_key='notify:queue'# 传递键(KEYS)和参数(ARGV)result=r.eval(lua_script,3,stock_key,log_key,notify_queue_key,user_id)ifresult==1:print(f'库存扣减成功,用户ID:{user_id}')returnTrueelse:print(f'库存不足,用户ID:{user_id}')returnFalse
Lua脚本的优势
  • 原子性:保证脚本中的逻辑是原子的,避免了中间状态的问题;
  • 减少网络开销:将多个命令封装到一个脚本中,减少了网络往返次数;
  • 灵活性:可以处理复杂的逻辑(如条件判断、循环),比原子操作更灵活。

4.4 集群架构:横向扩展容量与并发

问题:单节点的瓶颈

当数据量超过单节点的内存容量(如Redis的maxmemory设置为4GB,而数据量达到5GB),或者并发请求超过单节点的处理能力(如单节点的QPS为10万,而需求为20万),单节点的Redis无法满足需求。

解决方案:Redis Cluster(集群)

Redis Cluster是Redis的分布式集群解决方案(从3.0版本开始),可以将数据分散到多个节点(如3个主节点、3个从节点),实现横向扩展(Scale Out)。

集群的核心概念
  • 哈希槽(Hash Slot):Redis Cluster将所有键分为16384个哈希槽(0-16383),每个键通过CRC16算法计算出一个16位的哈希值,然后对16384取模,得到对应的哈希槽。例如,键“stock:1001”的CRC16哈希值为0x1234,对16384取模后得到哈希槽1234。
  • 节点分工:每个主节点负责一部分哈希槽(如3个主节点分别负责0-5460、5461-10922、10923-16383的槽),从节点负责复制主节点的数据,提供高可用(当主节点故障时,从节点提升为主节点)。
  • 数据分片:当客户端要访问一个键时,会先计算它的哈希槽,然后连接到对应的主节点(如键“stock:1001”的哈希槽为1234,对应的主节点是node1)。
集群的部署示例

用Docker部署一个简单的Redis Cluster(3主3从):

  1. 创建6个Redis节点

    forportin700070017002700370047005;domkdir-p /tmp/redis/$portdocker run -d --name redis-$port-p$port:$port-v /tmp/redis/$port:/data redis:7.0.0 --cluster-enabledyes--cluster-config-file nodes.conf --cluster-node-timeout5000--appendonlyyesdone
  2. 创建集群

    dockerexec-it redis-7000 redis-cli --cluster create127.0.0.1:7000127.0.0.1:7001127.0.0.1:7002127.0.0.1:7003127.0.0.1:7004127.0.0.1:7005 --cluster-replicas1

    解释:

    • --cluster create:创建集群;
    • 127.0.0.1:7000 ... 127.0.0.1:7005:6个节点的地址;
    • --cluster-replicas 1:每个主节点有1个从节点(因此3主3从)。
  3. 客户端连接集群
    用Python的rediscluster库连接集群:

    fromredisclusterimportRedisCluster# 集群的启动节点(任意一个主节点或从节点)startup_nodes=[{'host':'localhost','port':7000}]# 连接集群(decode_responses=True:将字节串转换为字符串)rc=RedisCluster(startup_nodes=startup_nodes,decode_responses=True)# 设置键(自动分配到对应的哈希槽)rc.set('key','value')# 获取键(自动连接到对应的节点)print(rc.get('key'))# 输出:value
集群的优势
  • 横向扩展:通过添加节点来增加内存容量和并发能力(如将3主节点扩展到6主节点,QPS从10万提升到20万);
  • 高可用:当主节点故障时,从节点会自动提升为主节点(通过Redis Cluster的故障转移机制),保证系统的可用性;
  • 负载均衡:将数据分散到多个节点,分担每个节点的负载(如将热点键分散到不同的节点)。

5. 性能验证:压测与结果分析

为了验证Redis的高并发能力,我们用redis-benchmark工具(Redis自带的压测工具)测试不同方案的性能。

测试环境

  • 服务器:Ubuntu 22.04,8核CPU,16GB内存;
  • Redis版本:7.0.0;
  • 客户端:redis-benchmark(自带)。

测试用例

  1. 单条SET命令:测试单条SET命令的QPS;
  2. Pipeline SET命令:测试Pipeline(每个Pipeline包含10条SET命令)的QPS;
  3. Lua脚本SET命令:测试Lua脚本(执行SET命令)的QPS;
  4. 集群SET命令:测试Redis Cluster(3主3从)的SET命令QPS。

测试结果

测试用例QPS(次/秒)备注
单条SET命令112,360单节点,单线程
Pipeline SET命令(P=10)546,448单节点,批量操作
Lua脚本SET命令108,765单节点,原子脚本
集群SET命令(3主)321,5433主节点,负载均衡

结果分析

  • Pipeline的性能提升:Pipeline将单条SET的QPS从11万提升到54万,提升了约4.8倍,说明批量操作能显著减少网络开销;
  • Lua脚本的性能:Lua脚本的QPS与单条SET命令相近,说明Lua脚本的原子性没有明显的性能开销;
  • 集群的性能:3主节点的集群QPS为32万,约为单节点的2.8倍(因为集群的负载均衡和横向扩展),说明集群能有效提升并发能力。

6. 最佳实践:避免高并发陷阱

6.1 选择合适的数据结构

  • 用哈希表存对象:如用户信息(hgetall user:123)比用多个字符串(get user:123:name、get user:123:age)更高效;
  • 用有序集合存排行榜:如ZSET可以快速获取Top N数据(zrevrange rank:product 0 9);
  • 用列表存队列:如LPUSH和RPOP可以实现简单的消息队列(但高并发场景下建议用专门的消息队列,如Kafka)。

6.2 避免大key

  • 大key的危害:大key(如一个包含10万个元素的列表)会导致Redis的内存占用过大,并且在查询或删除时占用大量CPU时间,影响其他命令的执行;
  • 解决方案:将大key拆分成小key(如将列表list:1拆分成list:1:part1、list:1:part2,每个part包含1000个元素)。

6.3 使用Pipeline减少网络开销

  • 适用场景:批量获取或设置数据(如批量获取用户信息、批量设置库存);
  • 注意事项:Pipeline的大小不宜过大(如每个Pipeline包含10-100条命令),否则会占用过多的内存和CPU时间。

6.4 合理设置过期时间

  • 用EXPIRE设置过期时间:对于临时数据(如用户会话、缓存的商品信息),设置合适的过期时间(如EXPIRE session:user123 3600),让Redis自动删除过期数据;
  • 用惰性删除+定期删除:Redis的过期策略是惰性删除(访问时检查是否过期)+定期删除(每隔一段时间扫描过期键),避免过期数据占用内存。

6.5 避免热点key

  • 热点key的危害:某个key被大量请求访问(如秒杀活动的库存键),导致对应的节点压力过大;
  • 解决方案
    • 本地缓存:在应用服务器上缓存热点key(如用Guava Cache),减少对Redis的请求;
    • 分散热点key:用不同的前缀(如stock:1001:1、stock:1001:2),然后用一致性哈希分配到不同的节点。

6.6 优化持久化策略

  • RDB vs AOF
    • RDB:快照备份(如每小时生成一次RDB文件),恢复速度快,但数据安全性低(如果Redis故障,可能丢失最近一小时的数据);
    • AOF:增量日志(如每秒钟同步一次AOF文件),数据安全性高,但恢复速度慢;
  • 混合模式:Redis 4.0以上支持RDB+AOF混合模式(用RDB做快照,用AOF做增量日志),既保证了数据安全性,又不会影响性能。

7. 未来展望:Redis的高并发进化方向

7.1 多线程模型的改进

Redis 6.0引入了多线程处理网络IO(命令执行还是单线程),可以提高网络IO的处理能力(如处理更多的并发连接)。未来,Redis可能会支持多线程执行命令(如将不同的命令分配到不同的线程执行),进一步提高并发能力。

7.2 更高效的内存管理

Redis 7.0引入了内存碎片整理功能(通过MEMORY PURGE命令),可以减少内存碎片(如频繁分配和释放内存导致的碎片),提高内存利用率。未来,Redis可能会有更智能的内存管理机制(如自动调整内存分配策略)。

7.3 更好的集群功能

Redis Cluster目前的哈希槽分配是静态的(需要手动或自动迁移哈希槽),未来可能会支持动态调整哈希槽(如根据节点的负载自动调整哈希槽分配),或者更灵活的分片策略(如按范围分片)。

7.4 与云原生的深度结合

随着云原生的普及,Redis可能会更好地支持Kubernetes(如用Redis Operator管理集群的生命周期)、服务网格(如Istio的流量管理),提供更灵活的部署和管理方式。

8. 总结:Redis高并发能力的本质

Redis之所以能处理大数据高并发访问,其本质是用高效的机制解决了高并发的核心问题

  • 单线程模型:避免了上下文切换和锁竞争,保证了命令的原子性;
  • IO多路复用:高效处理多个连接,减少了网络阻塞;
  • 高效数据结构:跳表、哈希表等数据结构保证了快速的查找、插入、删除;
  • 分布式集群:横向扩展容量和并发能力,解决了单节点的瓶颈。

作为后端开发者,理解Redis的高并发机制,掌握其最佳实践,才能在高并发场景下(如电商秒杀、实时推荐)构建稳定、高效的系统。

参考资料

  1. 《Redis设计与实现》(黄健宏著):深入解析Redis的核心机制;
  2. Redis官方文档(https://redis.io/docs):最新的Redis使用指南;
  3. 《Redis Cluster Tutorial》(https://redis.io/docs/management/scaling):Redis Cluster的官方教程;
  4. 《Redis Lua Scripting》(https://redis.io/docs/interact/programmability/lua-scripting):Redis Lua脚本的官方文档;
  5. 《Redis Benchmark Guide》(https://redis.io/docs/management/optimization/benchmarks):Redis压测的官方指南。

附录:完整代码链接

  • 本文中的Python代码:https://github.com/your-repo/redis-high-concurrency-example
  • Redis Cluster部署脚本:https://github.com/your-repo/redis-cluster-deploy

作者:[你的名字]
日期:2024-05-01
版权:本文采用CC BY-SA 4.0协议,允许自由转载,但需注明作者和出处。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/17 23:18:45

【MongoDB实战】6.3 索引优化实战:慢查询解决

文章目录 《MongoDB实战入门》第6章 性能优化:索引与查询效率提升 6.3 索引优化实战:慢查询解决 6.3.1 识别慢查询:explain()方法分析查询执行计划 1. 核心概念铺垫 2. 实操:识别慢查询(准备测试数据+分析执行计划) 6.3.2 优化案例:为慢查询添加合适索引(对比优化前后)…

作者头像 李华
网站建设 2025/12/26 8:14:31

HTML如何设计JQuery支持大文件上传的拖拽功能?

2023年11月2日 星期四 阴有小雨 外包项目日志 - 企业级大文件传输系统Day3 项目背景与架构设计 客户是某地质勘探研究院&#xff0c;每日需上传**20GB**的勘探数据&#xff08;含激光扫描点云、地质剖面图等&#xff09;&#xff0c;要求&#xff1a; 文件夹结构保留&#xf…

作者头像 李华
网站建设 2025/12/17 23:17:10

yolo-ORBSLAM2复现

这个也是一个经典的问题了&#xff0c;我是想复现&#xff0c;再进行修改&#xff0c;因为我不使用yolo作为检测&#xff0c;但要先搞清楚检测框是怎么送入slam的&#xff0c;所以先复现各位大佬们的。主要参考&#xff1a; https://github.com/JinYoung6/orbslam_addsemantic…

作者头像 李华
网站建设 2025/12/17 23:15:34

python基于大数据技术的购房推荐系统的设计与实现

Python基于大数据技术的购房推荐系统的设计与实现是一个复杂但具有广泛应用前景的项目。以下是对该系统的详细介绍&#xff1a; 一、系统概述 购房推荐系统利用Python编程语言的强大功能和丰富的大数据技术&#xff0c;结合机器学习算法和推荐算法&#xff0c;对购房数据进行深…

作者头像 李华
网站建设 2025/12/17 23:15:11

介观交通流仿真软件:DynusT_(20).DynusT在实际项目中的应用

DynusT在实际项目中的应用 在上一节中&#xff0c;我们已经了解了DynusT的基本功能和使用方法。本节将详细介绍如何在实际项目中应用DynusT进行交通流仿真。我们将通过具体的案例来展示如何设置仿真参数、导入交通网络数据、模拟交通流量以及分析仿真结果。这些案例将涵盖城市交…

作者头像 李华