百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

腾讯T4分享:Redis热点key处理,访问延迟降低90%!

wptr33 2025-03-10 21:11 15 浏览

Redis热点key问题真是让人头大,尤其在大促期间,几个热门商品的缓存key被疯狂访问,分分钟就能把系统搞趴下。不过别担心,今天咱聊聊几个实用的热点key处理方案,能帮你把访问延迟降到最低。

本地缓存大法

在Redis前面加一层本地缓存,能有效减少网络开销:

from cachetools import TTLCache
import redis

class LocalCache:
    def __init__(self):
        self.local_cache = TTLCache(maxsize=1000, ttl=5)  # 5秒过期
        self.redis_client = redis.Redis()
    
    def get_product_info(self, product_id: str):
        # 先查本地缓存
        if product_id in self.local_cache:
            return self.local_cache[product_id]
        
        # 本地没有查Redis
        value = self.redis_client.get(f"product:{product_id}")
        if value:
            self.local_cache[product_id] = value
        return value

温馨提示:本地缓存过期时间别设太长,不然数据不一致问题会让你很头疼。

分片打散技术

把一个热key分成多个子key,分散访问压力:

class ShardingCache:
    def __init__(self, shard_num=10):
        self.shard_num = shard_num
        self.redis_client = redis.Redis()
    
    def get_hot_key(self, key: str):
        # 随机选择一个分片
        shard = random.randint(0, self.shard_num - 1)
        shard_key = f"{key}:{shard}"
        
        return self.redis_client.get(shard_key)
    
    def set_hot_key(self, key: str, value: str):
        # 写入所有分片
        for i in range(self.shard_num):
            shard_key = f"{key}:{i}"
            self.redis_client.set(shard_key, value)

说实话,这招在我们公司双11时立了大功,原来动不动几百毫秒的接口直接降到了10毫秒以内。

异步读取优化

用异步方式读取热点数据,能大幅提升并发性能:

import asyncio
import aioredis

class AsyncHotKeyHandler:
    def __init__(self):
        self.redis = aioredis.from_url('redis://localhost')
    
    async def get_hot_data(self, keys: list):
        # 批量异步读取
        tasks = [self.redis.get(key) for key in keys]
        results = await asyncio.gather(*tasks)
        return dict(zip(keys, results))

温馨提示:异步读取时要注意控制并发量,不要一次性发太多请求。

延迟加载策略

有时候可以先返回旧数据,后台更新:

from threading import Thread
import time

class LazyLoader:
    def __init__(self):
        self.cache = {}
        self.redis_client = redis.Redis()
    
    def get_data(self, key: str):
        cached = self.cache.get(key)
        if cached:
            # 异步更新缓存
            Thread(target=self._async_refresh, args=(key,)).start()
            return cached
        
        # 缓存不存在时直接查Redis
        return self._load_from_redis(key)
    
    def _async_refresh(self, key: str):
        new_value = self._load_from_redis(key)
        self.cache[key] = new_value

记得去年我遇到个有意思的case,一个商品详情页的热key每秒几万次访问,直接把Redis干懵了。上了这套方案后,Redis的压力直接降了90%。

要是你想玩得更花,还可以用布隆过滤器预加载热key,提前把可能的热点数据写入本地缓存。不过话说回来,系统的复杂度也上来了,得好好权衡。

写代码也要动动脑子,比如定时任务更新热点数据时,可以错开整点,避免跟业务高峰撞到一起。我看过好多系统半夜12点集中更新缓存,结果一更新全站都卡。

有个小技巧,更新热点数据时最好用SETNX,不要直接SET,这样能避免多个实例同时更新导致的问题。

还有个坑,不少人喜欢用incr命令更新热点计数器,这种情况最好用批量操作,积累一批后一次性更新,不然Redis吃不消。

实际应用中啊,这些方案都不是单独用的,得根据业务特点组合使用。我们生产环境就是本地缓存+分片+异步读取一起上,效果相当不错。

相关推荐

每天一个编程技巧!掌握这7个神技,代码效率飙升200%

“同事6点下班,你却为改BUG加班到凌晨?不是你不努力,而是没掌握‘偷懒’的艺术!本文揭秘谷歌工程师私藏的7个编程神技,每天1分钟,让你的代码从‘能用’变‘逆天’。文末附《Python高效代码模板》,...

Git重置到某个历史节点(Sourcetree工具)

前言Sourcetree回滚提交和重置当前分支到此次提交的区别?回滚提交是指将改动的代码提交到本地仓库,但未推送到远端仓库的时候。...

git工作区、暂存区、本地仓库、远程仓库的区别和联系

很多程序员天天写代码,提交代码,拉取代码,对git操作非常熟练,但是对git的原理并不甚了解,借助豆包AI,写个文章总结一下。Git的四个核心区域(工作区、暂存区、本地仓库、远程仓库)是版本控制的核...

解锁人生新剧本的密钥:学会让往事退场

开篇:敦煌莫高窟的千年启示在莫高窟321窟的《降魔变》壁画前,讲解员指着斑驳色彩说:"画师刻意保留了历代修补痕迹,因为真正的传承不是定格,而是流动。"就像我们的人生剧本,精彩章节永远...

Reset local repository branch to be just like remote repository HEAD

技术背景在使用Git进行版本控制时,有时会遇到本地分支与远程分支不一致的情况。可能是因为误操作、多人协作时远程分支被更新等原因。这时就需要将本地分支重置为与远程分支的...

Git恢复至之前版本(git恢复到pull之前的版本)

让程序回到提交前的样子:两种解决方法:回退(reset)、反做(revert)方法一:gitreset...

如何将文件重置或回退到特定版本(怎么让文件回到初始状态)

技术背景在使用Git进行版本控制时,经常会遇到需要将文件回退到特定版本的情况。可能是因为当前版本出现了错误,或者想要恢复到之前某个稳定的版本。Git提供了多种方式来实现这一需求。...

git如何正确回滚代码(git命令回滚代码)

方法一,删除远程分支再提交①首先两步保证当前工作区是干净的,并且和远程分支代码一致$gitcocurrentBranch$gitpullorigincurrentBranch$gi...

[git]撤销的相关命令:reset、revert、checkout

基本概念如果不清晰上面的四个概念,请查看廖老师的git教程这里我多说几句:最开始我使用git的时候,我并不明白我为什么写完代码要用git的一些列指令把我的修改存起来。后来用多了,也就明白了为什么。gi...

利用shell脚本将Mysql错误日志保存到数据库中

说明:利用shell脚本将MYSQL的错误日志提取并保存到数据库中步骤:1)创建数据库,创建表CreatedatabaseMysqlCenter;UseMysqlCenter;CREATET...

MySQL 9.3 引入增强的JavaScript支持

MySQL,这一广泛采用的开源关系型数据库管理系统(RDBMS),发布了其9.x系列的第三个更新版本——9.3版,带来了多项新功能。...

python 连接 mysql 数据库(python连接MySQL数据库案例)

用PyMySQL包来连接Python和MySQL。在使用前需要先通过pip来安装PyMySQL包:在windows系统中打开cmd,输入pipinstallPyMySQL ...

mysql导入导出命令(mysql 导入命令)

mysql导入导出命令mysqldump命令的输入是在bin目录下.1.导出整个数据库  mysqldump-u用户名-p数据库名>导出的文件名  mysqldump-uw...

MySQL-SQL介绍(mysql sqlyog)

介绍结构化查询语言是高级的非过程化编程语言,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统,可以使用相同...

MySQL 误删除数据恢复全攻略:基于 Binlog 的实战指南

在MySQL的世界里,二进制日志(Binlog)就是我们的"时光机"。它默默记录着数据库的每一个重要变更,就像一位忠实的史官,为我们在数据灾难中提供最后的救命稻草。本文将带您深入掌握如...