本文内容仅为个人记录,并未记录书中完整内容。更详细的内容请查看本文引用的书籍,书名请查看文末。 1. 分布式锁 分布式应用进行逻辑处理经常会遇到并发问题。一个操作要修改用户的状态,修改状态需要先读出用户的状态,在内存里进行修改,改完了再存回去。 如果这样的操作同时进行,就会出现并发 问题,因为“读取”和“保存状态”这两个操作不是原子操作。这个时候就要使用到分布式锁来限制程序的并发执行 1.1 超时问题 Redis的分布式锁不能解决超时问题,如果在加锁和释放锁之间的逻辑执行太长,以至于超出了锁的限制,就会出现问题。为了避免这个问题,Redis分布式锁不要用于较长时间的任务。如果真的偶尔出现了问题,造成的数据小错乱可能需要人工介入解决。 有一个稍微安全一点的方案是匹配随机参数value和删除key,但这不是一个原子操作,Redis也没提供类似的原子操作指令,这时就需要用Lua脚本处理。但这也不是一个完美的方案,只是相对安全一点,因为如果真的超时了,当前线程逻辑没有执行完,其他线程也会乘虚而入。 2. 延时队列 Rabbitmq和Kafka这两个都是专业的消息队列中间件,特性之多超出了大多数人的理解能力。对于那些只有一组消费者的消息队列,使用Redis可以非常轻松地搞定,需要注意,Redis不是专业的消息队列,没有非常多的高级特性,没有ack保证,如果对消息的可靠性有着极高要求,那么他就不适用。 2.1 异步消息队列 Redis的list常用来作为异步消息队列使用,用rpush和lpush操作入队列,用lpop和rpop操作出队列。 2.2 队列空了怎么办? 如果队列空了,客户端就会陷入pop的死循环,不停pop,没有数据。空轮询不但拉高客户端CPU消耗,Redis的QPS也会被拉高。有以下两种种解决办法。 使用sleep来解决问题,睡个1S就可以了。不但客户端CPU消耗能降下来,Redis的QPS也能降下来; 如果有多个消费者,上面的就会导致消息延迟增大。使用阻塞读就是更好的解决方案,阻塞读在队列没数据时会立即进入休眠状态,一旦数据进来,就会立即醒来,消息的延迟几乎为零。blpop/brpop替代lpop/rpop。 阻塞读有可能造成空闲连接问题,所以编写客户端消费者时,如果捕获到异常,还要重试。 2.3 锁冲突处理 客户端在处理请求加锁没成功怎么办?一般有以下三种策略来处理加锁失败。 直接抛出异常,通知客户稍后重试;...
Continue reading...
Robin
Here are some articles about life and technology. Most of IT, of course. Because You are reading a story about a programmer. 😄
-
Apache Tomcat Web Application Server - Robin Liu says:[…] JVM内存模型可以参考此文《JVM运行时数据区》 […]
-
Three Dirty Teens On Webcam says:
-
Robin says:
-
Robin says:
-
Robin says:
- AVL Tree Binary Tree Bitcoin Blockchain BSN concurrency docker Ethereum FISCO-BCOS Go Golang Go map grpc grpc-go JVM Mybatis mysql Nginx OAuth2 redis module redis solutions Solidity Spring Spring Cloud OAuth2 Spring IoC SpringMVC tomcat tree WeIdentity wireshark ZooKeeper 内建命令 分布函数 外包 外包公司 大厂面经 奇偶性校验 应用架构 离散概率 面经
Open Source Community
-
January 1, 2021