深圳 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,针对部分应用场景进行案列分享,对初学者适用 立即下载

相关推荐

高并发与高可用实战.docx

nginx.

使用 redis 做限流的几种方式

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

Hebe 875

IBIS模型中的Pullup和Pulldown曲线详解:如何避免信号完整性设计中的常见错误

本文深入解析IBIS模型中Pullup和Pulldown曲线的关键作用,揭示其在信号完整性设计中的黄金法则。通过详细分析曲线特性、常见误区及验证方法,帮助工程师避免设计错误,优化高速PCB设计。文章还展示了曲线数据在动态终端匹配、串扰预测和电源完整性分析中的高级应用,提升设计效率和可靠性。

weixin_30275415的博客 447

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

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

尹煜的博客 1596

Cesium实战:全球海洋动态水面与自定义区域波浪效果实现

本文详细介绍了在Cesium中实现全球海洋动态水面与自定义区域波浪效果的实战方法。通过解析核心概念Primitive与Geometry,并深入讲解Water材质的关键参数调节,指导开发者快速创建逼真的动态海洋。文章重点阐述了如何利用多边形坐标定义不规则图形区域,实现精准的局部水域波浪效果,并提供了性能优化与视觉提升的实用技巧。

weixin_29256771的博客 494

【HALCON+C#实战】3D点云测量系统开发全攻略:从源码解析到工业应用

本文详细介绍了基于HALCON和C#开发3D点云测量系统的全流程,从环境搭建、核心算法实现到工业应用优化。通过源码解析和实战技巧,帮助开发者解决点云数据处理、几何测量及系统集成中的常见问题,提升工业检测的精度与效率。

brown的博客 209

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

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

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

Docker网络冲突?手把手教你解决Dify社区版无法访问172.18.0.0网段的问题

本文详细解析了在部署Dify社区版时,因Docker默认网段与局域网冲突导致无法访问172.18.0.0网段的问题。通过剖析Docker网络原理,提供了修改Docker守护进程默认地址池的根治方案,并介绍了在Compose文件中指定自定义网络等备选方法,帮助用户彻底解决网络冲突,保障服务稳定运行。

p8q9r0的博客 484

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的博客 4574

Clawdbot安装教程:从零开始到接入飞书

这几天,Clawdbot把整个科技圈都刷屏了。就是这个胖逼小龙虾🦞。不过现在改名叫Moltbot了。原因很简单:被Anthropic告了。Anthropic觉得Clawdbot这名字太像Claude Code的延伸产品,要求改名。真的,Anthropic你这家伙…更离谱的是,因为Clawdbot太火,Mac Mini都被抢断货了。无数人为了用它,疯狂买Mac Mini。我刚打开美团外卖,发现居然没货了???

Maynor的博客 2178

【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法

相比C文本类编程语言,Simulink图形化编程语言的优势是逻辑思路和数据流清晰了很多,劣势是程序执行的时序不明确,而且各个模块的配置使编程的灵活度下降了不少,在使用习惯上面总感觉有各种限制。本文就是拆解Simulink中最基础的几个编程模块,发扬它的优势,避开劣势。

Mr.Cssust的博客 3849

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

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

BXA 5003

OsgEarth —— 笔记6 - 开发阶段加入漫游飞行(附源码)

效果      视频地址   源码 源码下载请私信   代码      代码相关内容:           OSG —— 笔记1 - 指令调用模型           OsgEarth —— 笔记1 - 创建地球的earth文件           OsgEarth —— 笔记2 - Qt窗口加载earth地球(附源码)           OsgEarth —— 笔记3 - 为地

1895

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

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

weixin_30258027的博客 389

SAP:QUERY中SQ02增加选择屏幕权限控制

【代码】SAP:QUERY中SQ02增加选择屏幕权限控制。

weixin_43734184的博客 2325

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

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

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

Hanyinh的博客 644

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

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

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

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

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

u010843275的博客 945

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

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

小灰灰blog的专栏 933

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

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

尹煜的博客 742

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

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

gorgor在码农 2122

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

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

weixin_40581617的博客 147

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的博客 735

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

Redis高并发场景优化和规范

qq_37824570的博客 414

基于redis的简单限流

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

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值