解决方案-如何优雅地重试
参考文献
如何优雅地重试
解决方案-数据库缓存不一致问题
参考文献
数据库缓存数据不一致
一致性
“⼀致性”包含了两种情况:
缓存中有数据,那么,缓存的数据值需要和数据库中的值相同;
缓存中本⾝没有数据,那么,数据库中的值必须是最新值.
产生的原因
数据库缓存不一致问题通常是由于缓存和数据库的数据更新不同步或者同步出现问题导致的.
并发更新:在多个并发线程同时更新数据时,可能会出现数据不一致的问题.例如,一个线程更新了数据库中的数据,但是缓存中的数据并没有及时更新,这时另一个线程读取缓存中的数据就会与数据库中的数据不一致.
缓存更新失败:在更新缓存时,如果由于网络或其他原因导致缓存更新失败,就可能会导致缓存和数据库中的数据不一致.
数据库更新失败:在更新数据库时,如果由于网络或其他原因导致数据库更新失败,就可能会导致缓存和数据库中的数据不一致.
缓存过期:在缓存中存储的数据可能会因为时间到期或者缓存空间不足等原因被清除,但是数据库中的数据仍然存在,这时就会出现缓存和数据库中的数据不一致.
缓存穿透:如果请求一个不存在的数据,就会导致缓存中没有该数据,但是每次请求都会访问数据库,这就会出现缓存和数据库中的数据不一致.
解决方 ...
RabbitMQ-如何保证消息不丢失
参考文献
RabbitMQ如何保证消息不丢失?
确保消息到MQ
生产者配置(结合Spring)
在 Spring 中,通过 RabbitTemplate 来发送消息到 RabbitMQ,可以通过配置 RabbitTemplate 的 ConfirmCallback 和 ReturnCallback 来实现消息的确认机制。
ConfirmCallback 是消息发送确认的回调函数接口,该接口方法如下:
12345678910public interface ConfirmCallback { /** * 消息确认回调方法 * @param correlationData 相关数据 * @param ack 消息是否成功到达交换机 * @param cause 失败原因 */ void confirm(CorrelationData correlationData, boolean ack, String cause);}
ReturnCallback 是消息发送失败后的回调函数接口,该接口方法如下:
12 ...
RabbitMQ-死信队列
参考文献
死信队列
RabbitMQ中的死信队列(Dead Letter Queue,DLQ)是一种特殊的队列,用于接收那些未能被消费者正确处理的消息.当一条消息被认为“死亡”时(如过期、被拒绝、超出队列限制等),RabbitMQ会将其路由到预先设定的死信队列中,以便后续进一步处理.
死信队列的作用
容错处理:当某些消息无法正常处理时,可以将其转发至死信队列,以免影响整个消息队列的正常运行.
调试方便:死信队列可以用于存储消费者处理失败的消息,方便开发人员进行问题排查和调试.
业务逻辑处理:死信队列也可以作为一个处理逻辑的触发点,例如当某些消息无法被正确处理时,可以将其路由到死信队列中触发其他业务逻辑的处理.
死信队列的创建步骤
创建一个普通队列,并设置相关参数(如队列名、交换机、路由键等).
设置队列的死信参数(如死信交换机、死信路由键等),以便将“死亡”的消息路由到指定的死信队列中.这些参数可以在创建队列时进行设置,也可以在之后通过队列属性进行修改.
创建一个死信队列,用于接收那些未能被消费者正确处理的消息.同样需要设置相关参数(如队列名、交换机、路由键等).
...
RabbitMQ-处理消息积压
参考文献
消息积压对RabbitMQ的影响
系统性能下降:如果消息队列中的消息没有及时处理,会导致队列变得越来越长,消费者从队列中获取消息的速度会减缓,从而影响整个系统的性能.
内存消耗增加:消息队列中的消息如果一直没有被消费,将一直占用内存.如果队列中积压的消息很多,将会占用大量的内存资源,导致内存消耗增加.
系统崩溃:如果 RabbitMQ 中的消息积压到一定程度,可能会导致系统崩溃.
消息丢失:当 RabbitMQ 中的消息积压到一定程度,可能会导致一些消息被直接删除,从而导致消息丢失的情况.
RabbitMQ处理消息积压
增加消费者数量
可以通过增加消费者数量来提高消息的处理速度.可以在消费者端通过增加线程数或者增加消费者实例数来实现
设置消息过期时间
RabbitMQ 设置消息过期时间是一种处理消息积压的方案,可以通过让已经过期的消息自动被删除,从而减轻队列负担,提高队列的处理能力.具体的操作步骤如下:
设置队列的过期时间
首先,需要在队列声明时设置队列的过期时间,即 x-message-ttl 参数,表示消息的存活时间.当队列中的消息存活时间超过指定时间 ...
Java并发编程-面试题(一)
参考文献
Java中线程的实现方式?
继承Thread类,重写run方法
实现Runnable接口,重写run方法
实现Callable接口,重写call方法,配合FutureTask
Callable一般用于有返回结果的非阻塞的执行方法
同步非阻塞
线程的状态
NEW
RUNNABLE
READY
RUNNING
WAITING
TIMED_WAITING
BLOCKED
TERMINATED
并发编程的三大特性
原子性
问题存在的原因: 分时复用机制引起
使用synchroinzed和Lock接口实现的锁
使用CAS
有序性
问题存在的原因: 重排序引起
使用volatile
使用synchroinzed和Lock接口实现的锁
Happens-Before
可见性
问题存在的原因: CPU缓存引起
使用volatile
使用synchroinzed和Lock接口实现的锁
使用final
Happens-Before原则
程序次序规则
管程锁定规则
volatile变量规则
线程启动规则
线程终止规则
线程中断规则
对象终结规则
Java锁的分 ...
Linux工具-awk
参考文献
AWK 简明教程
AWK
awk是逐行处理的,逐行处理的意思就是说,当awk处理一个文本时,会一行一行进行处理,处理完当前行,再处理下一行,awk默认以”换行符”为标记,识别每一行,也就是说,awk跟我们人类一样,每次遇到”回车换行”,就认为是当前行的结束,新的一行的开始,awk会按照用户指定的分割符去分割当前行,如果没有指定分割符,默认使用空格作为分隔符。
内建变量
变量
说明
$0
当前记录(这个变量中存放着整个行的内容)
$1~$n
当前记录的第n个字段,字段间由FS分隔
FS
输入字段分隔符 默认是空格或Tab
NF
Number of Field,当前行的字段的个数(即当前行被分割成了几列),字段数量
NR
行号,当前处理的文本行的行号
FNR
各个文件自己的行号
RS
输入的记录分隔符, 默认为换行符
OFS
输出字段分隔符, 默认也是空格
ORS
输出的记录分隔符,默认为换行符
FILENAME
当前输入文件的名字
ARGC
命令行参数的个数
ARGV
数组,保存的是命令行所在给定的各个参数
...
Linux工具-sed
参考文献
sed
sed 会根据脚本命令来处理文本文件中的数据,这些命令要么从命令行中输入,要么存储在一个文本文件中,此命令执行数据的顺序如下:
每次仅读取一行内容;
根据提供的规则命令匹配并修改数据.注意,sed 默认不会直接修改源文件数据,而是会将数据复制到缓冲区中,修改也仅限于缓冲区中的数据;
将执行结果输出.
当一行数据匹配完成后,它会继续读取下一行数据,并重复这个过程,直到将文件中所有数据处理完毕.
12345678910111213141516171819202122232425262728293031323334353637➜ ~ sedUsage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... -n, --quiet, --silent suppress automatic printing of pattern space -e script, --expression=script a ...
Redis-Cluster
参考文献
为什么引入Redis Cluster
Cluster(集群)模式的出现是解决了Redis单机容量有限的问题,解决了大数据量存储导致的各种慢问题,同时也便于横向拓展.该种模式会将Redis中数据按照一定规则划分到多台机器上.这种模式有两个特点:
能够在多个节点之间自动拆分数据集.
当节点的子集遇到故障或无法与群集的其余部分通信时,能够继续操作.
两种方案对应着 Redis 数据增多的两种拓展方案: 垂直扩展(scale up)、水平扩展(scale out).
垂直拓展: 升级单个 Redis 的硬件配置,比如增加内存容量、磁盘容量、使用更强大的 CPU.
水平拓展: 横向增加 Redis 实例个数,每个节点负责一部分数据.
Redis Cluster数据迁移
Redis Cluster迁移数据的整个过程可以分成五个大步骤,分别是:
标记迁入、迁出节点;
获取迁出的 keys;
源节点实际迁移数据;
目的节点处理迁移数据;
标记迁移结果.
Redis-最佳实践
参考文献
黑马Redis
Redis键值设计
Redis的Key虽然可以自定义,但最好遵循下面的几个最佳实践约定:
遵循基本格式:[业务名称]:[数据名称]:[]
长度不超过44字节
不包含特殊字符
好处:
可读性强
避免key冲突
方便管理
更节省内存: key是string类型,底层编码包含int、embstr和raw三种。embstr在小于44字节使用,采用连续内存空间,内存占用更小。当字节数大于44字节时,会转为raw模式存储,在raw模式下,内存空间不是连续的,而是采用一个指针指向了另外一段内存空间,在这段空间里存储SDS内容,这样空间不连续,访问的时候性能也就会收到影响,还有可能产生内存碎片
拒绝BigKey
BigKey通常以Key的大小和Key中成员的数量来综合判定,例如:
Key本身的数据量过大:一个String类型的Key,它的值为5 MB
Key中的成员数过多:一个ZSET类型的Key,它的成员数量为10,000个
Key中成员的数据量过大:一个Hash类型的Key,它的成员数量虽然只有1,000个但这些成员的Value(值)总大小为 ...