redis solutions

Redis之应用解决方案记录

本文内容仅为个人记录,并未记录书中完整内容。更详细的内容请查看本文引用的书籍,书名请查看文末。 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...