深圳 GIAC 技术大会 Redis 演讲文字稿

Redis高并发缓存设计问题与性能优化 缓存设计典型问题 阅读详情

观众朋友们,我是来自掌阅的工程师钱文品,今天我带来的是分享主题是:Redis 在海量数据和高并发下的优化实践。Redis 对于从事互联网技术工程师来说并不陌生,几乎所有的大中型企业都在使用 Redis 作为缓存数据库,但是对于绝大多数企业来说只会用到它的最基础的 KV 缓存功能,还有很多 Redis 的高级功能可能都未曾认真实践过。今天在这一个小时的时间我会围绕 Redis,分享在平时的日常业务开发中遇到的 9 个经典案例,希望通过此次分享可以帮助大家更好的将 Redis 的高级特性应用到日常的业务开发中来。

掌阅电子书阅读软件 ireader 的总用户量大概是 5亿左右,月活 5kw,日活近 2kw 。服务端有 1000 多个 Redis 实例,100+ 集群,每个实例的内存控制在 20g 以下。

KV 缓存

第一个是最基础也是最常用的就是 KV 功能,我们可以用 Redis 来缓存用户信息、会话信息、商品信息等等。下面这段代码就是通用的缓存读取逻辑。

def get_user(user_id):
    user = redis.get(user_id)
    if not user:
        user = db.get(user_id)
        redis.setex(user_id, ttl, user)  // 设置缓存过期时间
    return user

def save_user(user):
    redis.setex(user.id, ttl, user)  // 设置缓存过期时间
    db.save_async(user)  // 异步写数据库

除此之外 Redis 还提供了缓存模式,Set 指令不必设置过期时间,它也可以将这些键值对按照一定的策略进行淘汰。打开缓存模式的指令是:config set maxmemory 20gb ,这样当内存达到 20gb 时,Redis 就会开始执行淘汰策略,给新来的键值对腾出空间。这个策略 Redis 也是提供了很多种,总结起来这个策略分为两块:划定淘汰范围,选择淘汰算法。比如我们线上使用的策略是 allkeys-lru。这个 allkeys 表示对 Redis 内部所有的 key 都有可能被淘汰,不管它有没有带过期时间,而volatile只淘汰带过期时间的。Redis 的淘汰功能就好比企业遇到经济寒冬时需要勒紧裤腰带过冬需要进行一轮残酷的人才优化。它会选择只优化临时工呢,还是所有人一律平等都可能被优化。当这个范围圈定之后,会从中选出若干个名额,怎么选择呢,这个就是淘汰算法。最常用的就是 LRU 算法,它有一个弱点,那就是表面功夫做得好的人可以逃过优化。比如你乘机赶紧在老板面前好好表现一下,然后你就安全了。所以到了 Redis 4.0 里面引入了 LFU 算法,要对平时的成绩也进行考核,只做表面功夫就已经不够用了,还要看你平时勤不勤快。最后还一种极不常用的算法 —— 随机摇号算法,这个算法有可能会把 CEO 也给淘汰了,所以一般不会使用它。

分布式锁

下面我们看第二个功能 —— 分布式锁,这个是除了 KV 缓存之外最为常用的另一个特色功能。比如一个很能干的资深工程师,开发效率很快,代码质量也很高,是团队里的明星。所以呢诸多产品经理都要来烦他,让他给自己做需求。如果同一时间来了一堆产品经理都找他,它的思路呢就会陷入混乱,再优秀的程序员,大脑的并发能力也好不到哪里去。所以呢他就在自己的办公室的门把上挂了一个请勿打扰的牌子,当一个产品经理来的时候先看看门把上有没有这个牌子,如果没有呢就可以进来找工程师谈需求,谈之前要把牌子挂起来,谈完了再把牌子摘了。这样其它产品经理也要来烦他的时候,如果看见这个牌子挂在那里,就可以选择睡觉等待或者是先去忙别的事。如是这位明星工程师从此获得了安宁。

640?wx_fmt=png
图片

这个分布式锁的使用方式非常简单,就是使用 Set 指令的扩展参数如下

# 加锁
set lock:$user_id owner_id nx ex=5
# 释放锁
if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
else
    return 0
end
# 等价于
del_if_equals lock:$user_id owner_id

官方其实并不推荐这种方式,因为它在集群模式下会产生锁丢失的问题 —— 在主从发生切换的时候。官方推荐的分布式锁叫 RedLock,作者认为这个算法较为安全,推荐我们使用。不过掌阅这边一直还使用上面最简单的分布式锁,为什么我们不去使用 RedLock 呢,因为它的运维成本会高一些,需要 3 台以上独立的 Redis 实例,用起来要繁琐一些。另外呢 Redis 集群发生主从切换的概率也并不高,即使发生了主从切换出现锁丢失的概率也很低,因为主从切换往往都有一个过程,这个过程的时间通常会超过锁的过期时间,也就不会发生锁的异常丢失。还有呢就是分布式锁遇到锁冲突的机会也不多,这正如一个公司里明星程序员也比较有限一样,总是遇到锁排队那说明结构上需要优化。

延时队列

下面我们继续看第三个功能 —— 延时队列。前面我们提到产品经理在遇到「请勿打扰」的牌子时可以选择多种策略,1. 干等待 2. 睡觉 2. 放弃不干了 3. 歇一会再干。干等待就是 spinlock,这会烧 CPU,飙高 Redis 的QPS。睡觉就是先 sleep 一会再试,这会浪费线程资源,还会增加响应时长。放弃不干呢就是告知前端用户待会再试,现在系统压力大有点忙,影响用户体验。最后一种呢就是现在要讲的策略 —— 待会再来,这是在现实世界里最普遍的策略。这种策略一般用在消息队列的消费中,这个时候遇到锁冲突该怎么办?不能抛弃不处理,也不适合立即重试(spinlock),这时就可以将消息扔进延时队列,过一会再处理。

640?wx_fmt=png
图片

有很多专业的消息中间件支持延时消息功能,比如 RabbitMQ 和 NSQ。Redis 也可以,我们可以使用 zset 来实现这个延时队列。zset 里面存储的是 value/score 键值对,我们将 value 存储为序列化的任务消息,score 存储为下一次任务消息运行的时间(deadline),然后轮询 zset 中 score 值大于 now 的任务消息进行处理。

# 生产延时消息
zadd(queue-key, now_ts+5, task_json)
# 消费延时消息
while True:
  task_json = zrevrangebyscore(queue-key, now_ts, 0, 0, 1)
  if task_json:
    grabbed_ok = zrem(queue-key, task_json)
    if grabbed_ok:
      process_task(task_json)
  else:
    sleep(1000)  // 歇 1s

local res = nil
local tasks = redis.pcall("zrevrangebyscore", KEYS[1], ARGV[1], 0, "LIMIT", 0, 1)
if #tasks > 0 then
  local ok = redis.pcall("zrem", KEYS[1], tasks[1])
  if ok > 0 then
    res = tasks[1] 
  end
end
	
return res

为什么我要将分布式锁和延时队列一起讲呢,因为很早的时候线上出了一次故障。故障发生时线上的某个 Redis 队列长度爆表了,导致很多异步任务得不到执行,业务数据出现了问题。后来查清楚原因了,就是因为分布式锁没有用好导致了死锁,而且遇到加锁失败时就 sleep 无限重试结果就导致了异步任务彻底进入了睡眠状态不能处理任务。那这个分布式锁当时是怎么用的呢?用的就是 setnx + expire,结果在服务升级的时候停止进程直接就导致了个别请求执行了 setnx,但是 expire 没有得到执行,于是就带来了个别用户的死锁。但是后台呢又有一个异步任务处理,也需要对用户加锁,加锁失败就会无限 sleep 重试,那么一旦撞上了前面的死锁用户,这个异步线程就彻底熄火了。因为这次事故我们才有了今天的正确的分布式锁形式以及延时队列的发明,还有就是优雅停机,因为如果存在优雅停机的逻辑,那么服务升级就不会导致请求只执行了一半就被打断了,除非是进程被 kill -9 或者是宕机。

定时任务

分布式定时任务有多种实现方式,最常见的一种是 master-workers 模型。master 负责管理时间,到点了就将任务消息仍到消息中间件里,然后worker们负责监听这些消息队列来消费消息。著名的 Python 定时任务框架 Celery 就是这么干的。但是 Celery 有一个问题,那就是 master 是单点的,如果这个 master 挂了,整个定时任务系统就停止工作了。

640?wx_fmt=png
图片

另一种实现方式是 multi-master 模型。这个模型什么意思呢,就类似于 Java 里面的 Quartz 框架,采用数据库锁来控制任务并发。会有多个进程,每个进程都会管理时间,时间到了就使用数据库锁来争抢任务执行权,抢到的进程就获得了任务执行的机会,然后就开始执行任务,这样就解决了 master 的单点问题。这种模型有一个缺点,那就是会造成竞争浪费问题,不过通常大多数业务系统的定时任务并没有那么多,所以这种竞争浪费并不严重。还有一个问题它依赖于分布式机器时间的一致性,如果多个机器上时间不一致就会造成任务被多次执行,这可以通过增加数据库锁的时间来缓解。

640?wx_fmt=png
图片

现在有了 Redis 分布式锁,那么我们就可以在 Redis 之上实现一个简单的定时任务框架。

# 注册定时任务
hset tasks name trigger_rule
# 获取定时任务列表
hgetall tasks
# 争抢任务
set lock:${name} true nx ex=5
# 任务列表变更(滚动升级)
# 轮询版本号,有变化就重加载任务列表,重新调度时间有变化的任务
set tasks_version $new_version
get tasks_version

Life is Short,I use Redis
https://github.com/pyloque/taskino

如果你做过社区就知道,不可避免总是会遇到垃圾内容。一觉醒来你会发现首页突然会某些莫名其妙的广告帖刷屏了。如果不采取适当的机制来控制就会导致用户体验收到严重影响。

控制广告垃圾贴的策略非常多,高级一点的通过 AI,最简单的方式是通过关键词扫描。还有比较常用的一种方式就是频率控制,限制单个用户内容生产速度,不同等级的用户会有不同的频率控制参数。

频率控制就可以使用 Redis 来实现,我们将用户的行为理解为一个时间序列,我们要保证在一定的时间内限制单个用户的时间序列的长度,超过了这个长度就禁止用户的行为。它可以是用 Redis 的 zset 来实现。

640?wx_fmt=png
图片

图中绿色的部门就是我们要保留的一个时间段的时间序列信息,灰色的段会被砍掉。统计绿色段中时间序列记录的个数就知道是否超过了频率的阈值。

# 下面的代码控制用户的 ugc 行为为每小时最多 N 次

hist_key = "ugc:${user_id}"
with redis.pipeline() as pipe:
  # 记录当前的行为
  pipe.zadd(hist_key, ts, uuid)
  # 保留1小时内的行为序列
  pipe.zremrangebyscore(hist_key, 0, now_ts - 3600)
  # 获取这1小时内的行为数量
  pipe.zcard(hist_key)
  # 设置过期时间,节约内存
  pipe.expire(hist_key, 3600)
  # 批量执行
  _, _, count, _ = pipe.exec()
  return count > N

技术成熟度稍微高一点的企业都会有服务发现的基础设施。通常我们都会选用 zookeeper、etcd、consul 等分布式配置数据库来作为服务列表的存储。它们有非常及时的通知机制来通知服务消费者服务列表发生了变更。那我们该如何使用 Redis 来做服务发现呢?

640?wx_fmt=png
图片

这里我们要再次使用 zset 数据结构,我们使用 zset 来保存单个服务列表。多个服务列表就使用多个 zset 来存储。zset 的 value 和 score 分别存储服务的地址和心跳的时间。服务提供者需要使用心跳来汇报自己的存活,每隔几秒调用一次 zadd。服务提供者停止服务时,使用 zrem 来移除自己。

zadd service_key heartbeat_ts addr
zrem service_key addr

zremrangebyscore service_key 0 now_ts - 30  # 30s 都没来心跳

if zadd() > 0 || zrem() > 0 || zremrangebyscore() > 0:
  incr service_version_key

640?wx_fmt=png
图片

https://github.com/pyloque/captain

位图

掌阅的签到系统做的比较早,当时用户量还没有上来,设计上比较简单,就是将用户的签到状态用 Redis的 hash 结构来存储,签到一次就在 hash 结构里记录一条,签到有三种状态,未签到、已签到和补签,分别是 0、1、2 三个整数值。

hset sign:${user_id} 2019-01-01 1
hset sign:${user_id} 2019-01-02 1
hset sign:${user_id} 2019-01-03 2
...

这时候我们就开始着手解决这个问题,去优化存储。我们选择了使用位图来记录签到信息,一个签到状态需要两个位来记录,一个月的存储空间只需要 8 个字节。这样就可以使用一个很短的字符串来存储用户一个月的签到记录。

优化后的效果非常明显,内存直接降到了 10 个G。因为查询整个月的签到状态 API 调用的很频繁,所以接口的通信量也跟着小了很多。

640?wx_fmt=png
图片

但是位图也有一个缺点,它的底层是字符串,字符串是连续存储空间,位图会自动扩展,比如一个很大的位图 8m 个位,只有最后一个位是 1,其它位都是零,这也会占用1m 的存储空间,这样的浪费非常严重。

所以呢就有了咆哮位图这个数据结构,它对大位图进行了分段存储,全位零的段可以不用存。另外还对每个段设计了稀疏存储结构,如果这个段上置 1 的位不多,可以只存储它们的偏移量整数。这样位图的存储空间就得到了非常显著的压缩。

这个咆哮位图在大数据精准计数领域非常有价值,感兴趣的同学可以了解一下。

https://juejin.im/post/5cf5c817e51d454fbf5409b0

模糊计数

前面提到这个签到系统,如果产品经理需要知道这个签到的日活月活怎么办呢?通常我们会直接甩锅——请找数据部门。但是数据部门的数据往往不是很实时,经常前一天的数据需要第二天才能跑出来,离线计算是通常是定时的一天一次。那如何实现一个实时的活跃计数?

最简单的方案就是在 Redis 里面维护一个 set 集合,来一个用户,就 sadd 一下,最终集合的大小就是我们需要的 UV 数字。但是这个空间浪费很严重,仅仅为了一个数字要存储这样一个庞大的集合似乎非常不值当。那该怎么办?

这时你就可以使用 Redis 提供的 HyperLogLog 模糊计数功能,它是一种概率计数,有一定的误差,误差大约是 0.81%。但是空间占用很小,其底层是一个位图,它最多只会占用 12k 的存储空间。而且在计数值比较小的时候,位图使用稀疏存储,空间占用就更小了。

# 记录用户
pfadd sign_uv_${day} user_id
# 获取记录数量
pfcount sign_uv_${day}

https://github.com/aviggiano/redis-roaring

布隆过滤器

最后我们要讲一下布隆过滤器,如果一个系统即将会有大量的新用户涌入时,它就会非常有价值,可以显著降低缓存的穿透率,降低数据库的压力。这个新用户的涌入不一定是业务系统的大规模铺开,也可能是因为来自外部的缓存穿透攻击。

def get_user_state0(user_id):
  state = cache.get(user_id)
  if not state:
    state = db.get(user_id) or {}
    cache.set(user_id, state)
  return state

def save_user_state0(user_id, state):
  cache.set(user_id, state)
  db.set_async(user_id, state)

我们非常希望 Redis 里面有这样的一个 set,它存放了所有用户的 id,这样通过查询这个 set 集合就知道是不是新用户来了。当用户量非常庞大的时候,维护这样的一个集合需要的存储空间是很大的。这时候就可以使用布隆过滤器,它相当于一个 set,但是呢又不同于 set,它需要的存储空间要小的多。比如你存储一个用户 id 需要 64 个字节,而布隆过滤器存储一个用户 id 只需要 1个字节多点。但是呢它存的不是用户 id,而是用户 id 的指纹,所以会存在一定的小概率误判,它是一个具备模糊过滤能力的容器。

640?wx_fmt=png
图片

当它说用户 id 不在容器中时,那么就肯定不在。当它说用户 id 在容器里时,99% 的概率下它是正确的,还有 1% 的概率它产生了误判。不过在这个案例中,这个误判并不会产生问题,误判的代价只是缓存穿透而已,相当于有 1% 的新用户没有得到布隆过滤器的保护直接穿透到数据库查询,而剩下的 99% 的新用户都可以被布隆过滤器有效的挡住,避免了缓存穿透。

def get_user_state(user_id):
  exists = bloomfilter.is_user_exists(user_id)
  if not exists:
    return {}
  return get_user_state0(user_id)

def save_user_state(user_id, state):
  bloomfilter.set_user_exists(user_id)
  save_user_state0(user_id, state)

640?wx_fmt=png

redis技术分享PPT redis技术分享PPT,针对部分应用场景进行案列分享,对初学者适用 立即下载

相关推荐

MacX DVD Ripper Pro for Mac(DVD解码器) 6.2.120190416免激活版

只需要5分钟即可转档一张DVD光碟!并允许我们在编码之前预览、编辑、裁剪、修剪或扩展视频。第一款也是唯一一款能够支持DVD到MP4,H.264,MOV,FLV,MPEG4等所有格式DVD(新DVD,99-标题DVD,损坏和无法播放的DVD)和翻录DVD / ISO映像的工具,AVI,QT,MP3等。借助350多种预设配置文件MacX DVD Ripper Pro for Mac(DVD解码器) 6...

llhf688的博客 891

使用 redis 做限流的几种方式

限流算法在分布式领域是一个经常被提起的话题,当系统的处理能力有限时,如何阻止计划外的请求继续对系统施压,这是一个需要重视的问题。除了控制流量,限流还有一个应用目的是用于控制用户行为,避免垃圾请求。 滑动窗口 问题:系统要限定用户的某个行为在指定的时间里只能允许发生 N 次,如何使用 Redis 的数据结构来实现这个限流的功能? # 指定用户 user_id 的某个行为 action_key...

Hebe 875

S32DS3.5图形化配置实战:从零构建S32K144通信接口工程

本文详细介绍了如何使用S32DS3.5图形化配置工具从零构建S32K144通信接口工程。通过实战演示引脚配置、时钟树设置、SPI接口搭建等关键步骤,帮助开发者快速掌握NXP S32K系列开发技巧,提升嵌入式开发效率。特别针对S32DS3.5版本的新特性进行了深度解析,包括智能代码生成和调试优化方法。

weixin_26834815的博客 201

【Java开发】Redis位图实现统计日活周活月活

Redis位图是一种特殊的数据结构,它由一系列位组成,每个位只能是0或1。在Redis中,位图可以用来存储和操作二进制数据。位图提供了一些特殊的命令,使得我们可以对位进行操作,如设置、清除、计数和查询等。Redis位图的底层实现采用了稀疏数据结构,这意味着当位图中大部分位都是0时,Redis只会占用很少的内存空间。这使得位图在处理大规模数据时非常高效。简单来说,Redis位图使用二进制减少了统计数据存储的内存,使用大用户规模的情况,理论层面就不多说了,接下来直接讲应用层面吧~

尹煜的博客 1597

Windows Server上OpenVPN 2.4.8双因子认证实战:账号密码+证书,附一键脚本

本文详细介绍了在Windows Server上部署OpenVPN 2.4.8双因子认证(账号密码+证书)的实战方案,包括架构设计、证书体系规划、环境准备、服务器端配置及客户端自动化部署。通过一键脚本和优化配置,提升企业VPN的安全性和运维效率,特别适合金融、医疗等对安全性要求高的行业。

weixin_29231221的博客 467

魔百和CM211-1刷Armbian全流程:从安卓盒子到Linux服务器的完美变身

本文详细介绍了如何将魔百和CM211-1机顶盒刷入Armbian系统,实现从安卓盒子到Linux服务器的完美变身。涵盖硬件兼容性验证、固件选择、刷机流程、系统优化及常见问题解决,特别适合技术爱好者低成本搭建家庭NAS或开发环境。

weixin_30329623的博客 243

redis实现用户签到,统计活跃用户,用户在线状态,用户留存率

redis实现用户签到,统计活跃用户,用户在线状态,用户留存率

资深系统架构,深耕高并发研发与 AI 大模型工程化落地。技术栈以 Python (AI/NLP/RAG/Agent) 与 Golang (高并发架构) 为双核心,兼具 PHP 大型应用经验。专注算法落地、复杂系统设计及团队技术赋能 4409

uniapp+uniCloud实现微信小程序一键登录

(用户唯一标识),用户登录成功后,开发者服务器可以将openid和session_key保存,生成一个自定义登录态的token令牌响应给微信小程序,通过token可以查询openid和session_key,小程序下次请求只要携带着token就可以证明已经登录。这个API就是获取用户信息,每次请求都会弹出授权窗口(这个可能会不弹,这个要看你的版本,根据版本来定,不懂的可以留下评论),用户同意后会返回。到这里就可以实现微信一键登录了,快去试试吧,有问题可以在评论区留言,我看见会尽我知道的为你解答。

lb2917的博客 2578

Redis bitmap、hyperlog、布隆过滤器、RoaringBitmap原理应用场景与日活的统计的具体应用

缺点: 1.空间占用大2.统计逻辑复杂,比如统计最近 30 天用户的累计活跃天(每个用户在 30 天里有 N 天使用 app,N 为 1-30,然后将月活跃用户的 N 天加总)?统计最近 7 天的用户累计使用时长?统计最近 30 天有播放的累计用户数?统计最近 30 天活跃用户有多少在最近 30 天里有连续 3 天及以上活跃?统计 28 天前活跃用户的 1、3、7、14、28 天留存率?3、mysql性能消耗大, 4、以上统计逻辑可扩展性差,由于数据分析经常进行探索性分析,上面传统方案能解决上面几个问题,但

S_ZaiJiangHu的博客 4578

windows搭建IIS(FTP)

适用于参加网络系统管理的学生进行学习与参考

a1119619789的博客 281

OceanBase数据迁移(OMS)深度解析:异构数据库迁移方案、核心原理与实战优化指南

OceanBase迁移服务(OMS)提供异构数据库间全量+增量数据迁移与实时同步能力,核心价值在于保障业务连续性、数据一致性和异构兼容性。其分层架构包含服务接入层、流程编排层和组件链路层,支持Oracle/MySQL/DB2等与OceanBase的数据交互。关键技术包括DBCat引擎处理结构转换、并行分片实现全量迁移、以及日志解析保障增量同步。OMS通过类型映射、批量提交和断点续传等优化手段,确保迁移过程高效可靠,典型应用于去O迁移、数据库升级等场景。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 849

海量数据和高并发下的 Redis 业务优化实践

本文内容是我在 6 月 23 日参加的深圳 GIAC 技术大会上演讲的文字稿。 观众朋友们,我是来自掌阅的工程师钱文品,掘金小册《Redis 深度历险》的作者。今天我带来的是分享主题是:Redis 在海量数据和高并发下的优化实践。Redis 对于从事互联网技术工程师来说并不陌生,几乎所有的大中型企业都在使用 Redis 作为缓存数据库,但是对于绝大多数企业来说只会用到它的最基础的 KV 缓存...

weixin_30258027的博客 390

RK3588 部署 YOLOv5s 实战:多线程加速从 16FPS 飙升到 120FPS(含性能优化)

因为RK3588包含了3个NPU核心,支持3个核心同时工作、双核合作、以及单核工作。我们可以使用线程池来加速。线程池是一种长街的并发编程模型,它用于管理和复用线程,以提高多线程程序的性能和效率。线程池通常包含以下主要组件:1、任务队列:任务队列用于存储待执行的任务。这些任务可以是函数、方法或其他需要多线程环境中执行的操作。2、线程池管理:线程池管理器负责创建、销毁和管理线程。它会监视任务队列中的任务,根据需要创建线程,执行任务,并在任务完成后将线程放回池中以供重用。

FJN110的博客 100

Redis 高并发下的性能优化技术

Redis是一款高性能的键值存储数据库。与传统的数据库相比,Redis拥有更高的读写速度以及更丰富的数据结构支持。尽管Redis拥有出色的性能表现,但在高并发场景下其仍存在着一些性能问题需要我们注意。本文将围绕这些问题进行分析,并提供一些解决方案。Redis采用单进程单线程模型,通过事件驱动机制提高其并发性能。其内部包含多个模块,包括网络连接、命令请求处理、持久化管理等。在高并发下,对于Redis性能优化的关键点是:合理设置连接数、降低操作时间复杂度、开启持久化机制;

BXA 5003

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

使用Redis解决海量数据的日活、月活问题

使用redis统计用户日活、月活(实践版) redis HyperLogLog的使用

Hanyinh的博客 645

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

redis统计用户日活量_使用redis统计用户日活、月活(实践版)

常用方法三种一、set集合(精准、耗费空间)用户登录以后,把用户id添加到redis的set中,set会自动进行去重,类似于这样:127.0.0.1:6379> sadd users_2019_06_17 user1(integer) 1127.0.0.1:6379> sadd users_2019_06_17 user2(integer) 1127.0.0.1:6379> sa...

weixin_39624360的博客 1421

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

【Java开发】Redis位图轻松实现统计用户三日内留存数据

上一篇文章介绍了如何通过位图实现统计日活周活月活,而位图能做的远不止如此,本篇文章将介绍如何实现统计用户连续三日内登录的留存数据,从而更直观的反映软件的运营情况。

尹煜的博客 742

高并发系统缓存优化:Redis 性能调优(内存、线程、持久化)、热点数据处理

本文针对高并发系统中Redis的性能优化问题,从内存、线程和持久化三个维度展开分析。内存优化建议合理选择数据类型、设置内存阈值和淘汰策略;线程优化推荐高并发场景启用多线程模式;持久化调优需根据业务需求平衡RDB与AOF配置。同时提出热点数据处理方案,包括本地缓存、Key分片和读写分离。文章强调通过监控工具持续优化,实现性能与安全的平衡,为高并发系统提供可落地的Redis优化指南。

u010843275的博客 946

python redis 性能测试_性能提升48倍! python redis批量写入大量数据优化过程

1.最原始的版本,直接使用hset,效率很低写30w条完耗时365秒,这样有两个问题:相同的key,写入多条应该用hmset代替hset另外可以用pipeline,避免频繁跟redis服务端交互,大量减少网络ioimage.pngimage.pngimage.pngdef get_conn():r = redis.Redis(host='localhost', port=6379, decode_...

weixin_39881155的博客 736

如何用Redis平衡海量信息推送的实效与体量

前阵子开发了公司领劵中心的项目,这个项目是以Redis作为关键技术落地的。其中有一个功能叫做领劵的订阅推送。什么是领劵的订阅推送?就是用户订阅了该劵的推送,在可领取前的一分钟就要把提醒信息推送到用户的App中。本来这个订阅功能应该是消息中心那边做的,但他们说这个短时间内做不了,所以让我这个负责优惠劵的做了。具体方案就是到具体的推送时间点了,Coupon系统调用消息中心的推送接口,把信息推送出去。下...

weixin_40581617的博客 147

Redis 高并发缓存架构实战与性能优化

面试官很喜欢问的一个问题,你们系统有用 Redis?使用Redis实现了哪些业务场景?如何保证数据的一致性?缓存穿透,缓存击穿(缓存失效),缓存雪崩

gorgor在码农 2122

04.Redis高并发场景优化和规范

Redis高并发场景优化和规范

qq_37824570的博客 414

【SpringBoot DB 系列】Redis 高级特性之 HyperLoglog

【SpringBoot DB 系列】Redis 高级特性之 HyperLoglog hyperloglog 算法,利用非常少的空间,实现比较大的数据量级统计;比如我们前面在介绍 bitmap 的过程中,说到了日活的统计,当数据量达到百万时,最佳的存储方式是 hyperloglog,本文将介绍一下 hyperloglog 的基本原理,以及 redis 中的使用姿势 I. 基本使用 1. 配置 我们使用 SpringBoot 2.2.1.RELEASE来搭建项目环境,直接在pom.xml中添加 redi..

小灰灰blog的专栏 934

基于redis的简单限流

前言 redis的限流基于滑动窗口实现,如下图 构建一个zset数据结构,value存放时间戳 每次请求过来的时候,保留时间窗口内的数据 然后计算保留的数据是否超过了限定的数量 如果超过,则拒绝访问, 如果没超过,则放行 第一种简单的实现 public interface RateChecker { /** * 检查interval时间内请求数是否超过maxRequests * @param key key * @param in...

厚积薄发 1567
上一篇: 布隆过滤器过时了,未来属于布谷鸟过滤器?
下一篇: 面试题 —— 数字幻方
码洞
博客等级 码龄11年 41粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值