黑马点评实战篇问题总结

news2024/11/15 11:29:48

缓存穿透

用户查询的数据在缓存和数据库中都不存在
这样的请求每次都会打到数据库上
解决方案:
1.缓存空字符串(额外的内存消耗,可能造成短期的不一致)
2.布隆过滤(内存占用少,没有多余key,实现复杂,存在误判可能)
对于数据库中没有的数据,向缓存中缓存空值,别再访问数据库了,减少压力

缓存一致性问题

更新数据库的时候,先更新数据库,再删除缓存
实现强一致性,需要使用分布式锁控制,修改数据和向缓存存数据使用同一个分布式锁
实现最终一致性,缓存数据要加过期时间
对于实时性要求强的,要实现数据强一致性要尽量避免使用缓存

缓存雪崩

同一时间大量的key失效或者redis宕机
解决方案:
1.过期时间可以设置随机数,如30+(0~5)分钟随机,不要同时过期
2.使用redis集群提高可用性
3.给缓存业务添加降级限流策略
4.给业务添加多级缓存

缓存击穿

热点key问题
某些Key属于极端热点数据,且并发量很大的情况下,如果这个key过期,可能会在瞬间出现大量的并发请求直接打到了数据库
常见解决方案
互斥锁:
线程在重建缓存数据时,进行加锁,其他线程等待重试,直到释放锁之后,其他线程就可以缓存命中了
保证一致性,实现简单
其他线程需要等待,可能有死锁风险
逻辑过期:
对数据加一个过期时间字段,但并不实际设置过期时间,始终在redis当中。
校验发现逻辑时间过期时,获得互斥锁,开新线程去重建缓存数据,本线程返回那个过期的数据
对于其他线程,发现缓存中数据逻辑时间过期时,尝试获取互斥锁失败,就直接返回过期数据。
线程无需等待,不保证一致性
在这里插入图片描述

全局ID生成器

# 全局唯一ID生成策略
UUID
Redis自增
snowflake
数据库自增

在分布式系统下用来生成全局唯一ID的工具
(唯一性,高可用,高性能,递增性,安全性)
Long型,8个字节
在这里插入图片描述

超卖问题

多个线程在操作共享的变量\资源
解决方案:加锁
悲观锁:认为线程安全问题一定会发生,在操作数据之前先获取锁,确保线程串行执行(Synchronized,Lock)
乐观锁:认为线程安全问题不一定会发生,因此不加锁,只在更新数据时去判断有没有其他线程对数据做了修改
常见方案:
1.版本号法
给数据加上一个版本字段
在这里插入图片描述
2.CAS法
在这里插入图片描述

分布式锁

单机情况下由于有锁,所以安全
但是集群模式下,synchronized并不能保证集群并发安全性
需要多进程可见互斥的分布式锁
在这里插入图片描述
在这里插入图片描述

# lua脚本
eval "lua_script" NumberOfKeys key argv

redisson可重入锁原理

"lockName":{
    "threadId": "重入次数"
}
# 利用hash结构记录线程对应的重入次数
获取锁时锁已存在:
看线程标识是否是自己,是自己,锁计数value+1(并且重置有效期),不是自己获取锁失败
获取锁时锁不存在:
获取锁,并添加线程标识,锁计数为1,设置有效期

释放锁时:
线程标识是自己:锁计数减一,且重置有效期(减完如果为0,则释放锁)
线程标识不是自己:说明已经超时释放
-- 获取锁
local key = KEYS[1]; --锁的名字
local threadId = ARGV[1]; --线程标识(fieldName),对应的value是重入次数
local releaseTime = ARGV[2]; -- 过期时间(自动释放)

-- 锁不存在
if(redis.call('exists',key) == 0) then
  redis.call('hset',key,threadId,'1'); -- 将field(threadId)对应的value置为1
  redis.call('expire',key,releaseTime);
  return 1;
end;

-- 锁已存在(且线程标识是自己)
if(redis.call('hexists',key,threadId) == 1) then
  redis.call('hincrby',key,threadId,'1'); -- 重入次数+1
  redis.call('expire',key,releaseTime);
  return 1;
end;

return 0; -- 说明锁已存在但线程标识不是自己,获取锁失败
-- 释放锁
local key = KEYS[1]; -- 锁名
local threadId = ARGV[1]; --线程标识(fieldName),对应的value是重入次数
local releaseTime = ARGV[2]; -- 过期时间(自动释放)

-- 线程标识不是自己(不用管)
if(redis.call('HEXISTS',key,threadId) == 0) then
  return nil;
end;

-- 是自己,重入次数-1
local count = redis.call('HINCRBY',key,threadId,-1);
if(count > 0) then
  redis.call('EXPIRE',key,releaseTime);
  return nil;
else
  redis.call('DEL',key); -- 重入次数为0,则释放锁(删除)
  return nil;
end;

可重试原理:

第一次获取锁失败以后,等待释放锁的消息(redis中pubsub机制),释放锁的时候会发送这样的消息
得到消息后,重新获取锁,再次失败会继续等待消息
会有等待时间,超过时间不会再重试

超时续约问题:

默认的锁释放时间是30s
获取锁成功以后,会开启一个延时定时任务,每隔一段时间,不断的刷新有效期,直到手动释放锁

释放锁的时候:会取消掉定时任务

在这里插入图片描述
解决主从一致性问题(使用multilock,只要有一个主节点没挂,就是安全的)
在这里插入图片描述
在这里插入图片描述

Redis消息队列

redis消息队列和阻塞队列区别
1.消息队列是在JVM内存以外的独立服务,不受JVM内存限制
2.消息队列里的消息会做持久化,不管服务宕机还是重启,数据不会丢失
3.消息投递给消费者以后,要求消费者做消息的确认,没有确认,消息就会在队列中依然存在,确保消息至少被消费一次
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# 发送消息
XADD 队列名 *(表示消息id自动生成) field value [field value ...]
# 创建名为users的队列,发送一条消息{name:jack,age:21},消息id自动生成
XADD users * name jack age 21 

# 消费消息(消息可以被重复消费,并不会删除)
# 阻塞读取一条消息, 阻塞时长1秒, 从users队列中读取消息, $表示读取最新的消息
XREAD COUNT 1 BLOCK 1000 STREAMS users $
消费者组:将多个消费者划分到一个组当中,监听同一队列
有以下特点:
1.队列中的消息会分流给组内不同的消费者, 同一个消费者组内的消费者是竞争关系, 不会重复消费
2.消费者组会维护一个标识,记录最后一个被处理的消息,哪怕消费者宕机重启,还会从标识后读取消息
3.消费者获取消息后,消息处于pending状态,并存入pending-list,处理完成以后需要使用XACK来确认消息,标记已处理,才会从pending-list移除

在这里插入图片描述
在这里插入图片描述

推送Feed流

发布文章时,推送给所有的粉丝
在这里插入图片描述

附近的人

在这里插入图片描述

使用GEO数据结构(基于SortedSet)
# 添加一个地理信息
# GEOADD key longitude latitude member [longitude latitude member ...]
# Add one or more geospatial items in the geospatial index represented using a sorted set
# key是g1,成员是(bjn,bjz,bjx)
GEOADD g1 116.378248 39.865275 bjn 116.42803 39.903738 bjz 116.322287 39.893729 bjx

# bjn和bjx的距离(单位米)
GEODIST g1 bjn bjx
GEODIST g1 bjn bjx km # 单位(km)

# 返回成员bjn的地理坐标
GEOPOS g1 bjn

# 将指定成员的地理坐标转为hash字符串并返回
GEOHASH g1 bjn

# 北京天安门附近10km内的地理坐标信息(升序列出)
GEOSEARCH g1 FROMLONLAT 116.397904 39.909005 BYRADIUS 10 km WITHDIST

用户签到

在这里插入图片描述
在这里插入图片描述

# 用一个二进制串表示本月中的签到情况,每一位表示其中的某一天
setbit bm1 5 1 # 第6天签到(1表示签到,默认是0)
getbit bm1 2 # 查看第3天是否签到
bitcount bm1 # 值为1的位数
bitfield bm1 get u3 0 # 从索引0位开始,查3位,返回值是十进制,u表示无符号

UV统计

UV:Unique Visitor,独立访客量,一天内同一用户多次访问只记录一次
PV:Page View,页面访问量\点击量,每次访问页面,都会记录
# 大用户量的时候,做UV统计要判断是否已统计过,需要存数据,是一个巨大的数据量

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/440634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

访问若依vue版后端api接口

访问若依vue版后端api接口 如何使用Talend API Tester进行访问若依vue-前后端分离版的后端api接口? 方法一: 写好一个后台api接口,启动项目 直接使用Talend API Tester进行访问后台api出现如下错误,原因是因为若依系统有jwt认证…

2023软件测试工程师涨薪攻略,3年如何达到30K?

1.软件测试如何实现涨薪 首先涨薪并不是从8000涨到9000这种涨薪,而是从8000涨到15K加到25K的涨薪。基本上三年之内就可以实现。 如果我们只是普通的有应届毕业生或者是普通本科那我们就只能从小公司开始慢慢往上走。 有些同学想去做测试,是希望能够日…

数据可视化的web工具 apache-superset

文章目录 简介安装window10Ubuntu1804CentOS8 配置连接数据库创建仪表板创建图表图表加入仪表板时间序列折线图 简介 Superset是一款由Airbnb开源的、目前由Apache孵化的,基于Flask-appbuilder搭建的“现代化的企业级BI(商业智能)Web应用程序…

很合适新手入门使用的Python游戏开发包pygame实例教程-02[如何控制飞行]

前面一篇博文,我们让飞机动起来了,但不是那么完美,我们继续来完善我们的游戏代码,本篇博文主要介绍获取按键的方式已经飞行的控制。 文章目录 一、获取按键的三种方式1、通过event.get配合pygame.key枚举2、通过event.get配合ord…

C++入门教程||C++ 文件和流||C++ 异常处理

C 文件和流 C 文件和流 到目前为止,我们已经使用了 iostream 标准库,它提供了 cin 和 cout 方法分别用于从标准输入读取流和向标准输出写入流。 本教程介绍如何从文件读取流和向文件写入流。这就需要用到 C 中另一个标准库 fstream,它定义…

《我的第一本算法书》读书笔记

《我的第一本算法书》读书笔记 作者:宫崎修一 石田保辉 ◆ 1-3 数组 在链表和数组中,数据都是线性地排成一列。在链表中访问数据较为复杂,添加和删除数据较为简单;而在数组中访问数据比较简单,添加和删除数据却比较复…

转行IT,怎么选专业?

转行IT,怎么选专业? 知己知彼,百战不殆 先清楚你自身的基础情况:学历、年龄、是否有基础、学习能力如何、自律性、时间管理能力、有没有生活压力、有没有家要养、车贷、房贷…… 思考的问题越现实,对你的帮助越大 选…

运营商大数据获客是什么,是如何实现精准获客的

长久以来,企业希望自己的产品获得更多的客户,那么就需要花钱做推广和营销。然而随着互联网和自媒体的发展,并不是钱花出去了,就能带来有效的流量和高质量的客户,费效比太高,精准度太差,没有好的…

神经网络初学者的激活函数指南

如果你刚刚开始学习神经网络,激活函数的原理一开始可能很难理解。但是如果你想开发强大的神经网络,理解它们是很重要的。 但在我们深入研究激活函数之前,先快速回顾一下神经网络架构的基本元素。如果你已经熟悉神经网络的工作原理&#xff0c…

STM32+ESP8266+QT客户端上位机显示DHT11温湿度与点灯

目录 1、简介 2、硬件连接 3、上位机源码 3.1 widget.h 3.2 widget.c 3.3 显示图 4、下位机源码 4.1 cubemax配置 4.2 keil源码 1、简介 本文使用STM32F103C8T6单片机使用单片机通过ESP8266WIFI模块与QT设计的上位机进行通讯,ESP8266设置AP模式。实现DHT11传…

跨越DDD从理论到工程落地的鸿沟

DDD作为一种优秀的设计思想,的确为复杂业务治理带来了曙光。然而因为DDD本身难以掌握,很容易造成DDD从理论到工程落地之间出现巨大的鸿沟。就像电影里面的桥段,只谈DDD理论姿势很优美,一旦工程落地就跪了…所以DDD的项目&#xff…

Android实战-RecyclerView+Glide刷新列表的若干bug

文章目录 前言一. RecyclerView中使用Glide出现加载图片闪烁1.1 提出问题1.2 查看源码1.3 ViewTarget和SimpleTarget 二. CustomTarget和CustomViewTarget2.1 onResourceCleared和onLoadCleared2.2 onLoadStarted和onResourceLoading 结束 前言 最近在项目中使用RecyclerViewG…

Java——合并两个排序的链表

题目链接 牛客在线oj题——合并两个排序的链表 题目描述 输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。 数据范围: 0≤n≤1000,−1000≤节点值≤1000 要求:空间复杂…

物联网定位技术|实验报告|实验二 多边定位算法、DV-HOP算法

在WSN定位中常常采用三边定位算法,试画图推导三边定位的计算公式,并表示为矩阵形式。 目录 1. 实验目标 2. 实验要求 3. 算法介绍 3.1基本内容介绍 3.2迭代多边定位算法 3.3 DV-HOP算法 4. 算法实现 4.1迭代多边定位算法 第一步:将数据读入内…

STM32HAL库USART外设配置流程及库函数讲解

HAL库中USART外设配置流程及库函数讲解 一说到串口通信,及必须说一下aRS-232/485协议。232协议标准物理接口就是我们常用的DB9串口线 RS-232电平: 逻辑1:-15~-3 逻辑0: 3~15 COMS电平: 逻辑1:3.3 逻辑0&a…

文件操作【下篇】

文章目录 🗃️5.文件的随机读写📁5.1. fseek📁5.2. ftell📁5.3. rewind 🗃️6.文本文件和二进制文件🗃️7.文件读取结束的判定📁7.1. 被错误使用的 feof 🗃️8.文件缓冲区 &#x1f…

如何使用YOLOv8推荐的Roboflow来制作训练自己的数据集

YOLOv8是Ultralytics开发的YOLO目标检测和图像分割模型的最新版本,相较于之前的版本,YOLOv8可以更快速有效地识别和定位图像中的物体,以及更准确地分类它们。 YOLOv8需要大量的训练数据来实现最佳性能。为了让YOLOv8能够有效地识别自己的应用…

【UE】保存游戏的demo

效果 注意左上角的打印信息,每当我按下k键,值就加1。当我关闭后重进游戏,按下k键,值是从上次退出游戏的值开始累加的。 步骤 1.新建蓝图,父类为“SaveGame” 命名为“MySaveGame”并打开 新建一个整型变量&#xff0c…

ODOO业财一体贸易行业ERP全面管理系统(核心流程简介)

前言: 贸易行业的两大管理难点在: 1.订单的跟踪效率:订单从报价、寄样、采购材料、委外加工、质检、入库、出库、收款,跟踪环节多,信息分散,跟单员难以把握订单执行进度,因此也导致延期交货等…

户外电源强制国标发布或加速行业洗牌 未来产品将往大容量及轻量化发展

一、户外电源行业概述 户外电源是一种内置锂离子电池的低碳绿色小型储能设备,又称“大号充电宝”、“便携式储能”。是电化学储能的分支,优在“便捷”,具有多次循环充放电、适配广泛、安全便捷的特点,在户外各场景中应用广泛受到…