Redis分布式

Redis分布式 一、 Redis分布式概述 1. 什么是Redis分布式 Redis分布式是指将Redis数据分布到多个Redis节点上,通过集群方式提供更高性能、更大容量和更好可用性的解决方案。 1.2 为什么需要Redis分布式 数据量增长:单机内存容量有限 高并发需求:单机性能瓶颈 高可用性:避免单点故障 可扩展性:支持业务动态扩容 1.3 Redis分布式方案对比 方案 优点 缺点 使用场景 主从复制 部署简单,读写分离 写操作单点,故障需手动切换 读多写少,数据备份 Redis Sentinel 自动故障转移,高可用 配置复杂,扩容不便 生产环境高可用 Redis Cluster 数据分片,自动故障转移 客户端兼容性要求,迁移复杂 大数据量,高并发 二、 Redis分布式方案搭建 2.1 主从复制搭建 配置文件示例 主节点 (master.conf): port 6379 daemonize yes pidfile /var/run/redis_6379.pid logfile "/var/log/redis_6379.log" 从节点 (slave.conf): port 6380 daemonize yes pidfile /var/run/redis_6380.pid logfile "/var/log/redis_6380.log" slaveof 127.0.0.1 6379 启动命令 # 启动主节点 redis-server master.conf # 启动从节点 redis-server slave.conf 2.2 Redis Sentinel搭建 Sentinel配置文件...

2024年03月12日 · 3 min · Leanku

Redis的一些常见题

Redis的一些常见题 redis数据类型及应用场景 见 Redis的五种数据类型及使用场景 redis持久化及过期策略 见 Redis持久化及过期删除策略 redis 常见问题及解决方案 缓存雪崩:同一时间大量缓存失效,导致请求直接查询数据库,数据库内存和CPU压力增加甚至宕机 解决: 热点数据永不过期或者分布到不同实例,降低单机故障问题 缓存时间添加随机数,防止大量缓存同时失效 做二级缓存或者双缓存,A为原始缓存 短时效,B为备份缓存 ,长期有效。更新时候双写缓存 缓存穿透:缓存和数据库都没有数据,大量请求下,所有请求直接击穿到数据库,导致宕机。 解决: 布隆过滤器:长度为m的位向量或者位列表组成(仅包含0或1位值的列表) 使用多个不用的hash函数,产生多个索引值,填充对应多个位置的值为1 布隆过滤器可以检查值是 “可能在集合中” 还是 “绝对不在集合中” 可能误判但是基础过滤效率高 极端情况,当布隆过滤器没有空闲位置的时候每次查询返回true 空缓存(短时效) 业务层参数过滤 缓存击穿:数据库中有数据,但是缓存突然失效之后发生大量请求导致数据库压力增加甚至打垮宕机 解决: 热点数据永不过期 互斥锁:获取锁之后不管成功还是失败都要释放锁 Redis主从复制原理 Redis 在复制时底层采用的是 psync 命令完成的数据主从同步,同步主要分为:全量复制和增量复制两种 全量复制:顾名思义也就是一次性把主节点数据全部发送给从节点,所以这种情况下,当数据量比较大时,会对主节点和网络造成很大的开销。 部分复制:用于处理主从复制时因网络中断等原因造成数据丢失的场景。当从节点再次和主节点连接时,主节点会补发丢失的数据。因为是补发,所以在发送的数据量一定是小于全量的数据。 详细见 Redis的一些常见题 Redis缓存和数据库数据一致性问题: 读数据 尝试查询缓存,存在缓存则直接返回数据 缓存不存在时则查询数据库,并保存到缓存(合适设置过期时间),返回数据 写数据 先更新缓存再更新数据库 或者 先删除缓存再更新数据库 先更新数据库再更新缓存 或者 先更新数据库再删除缓存 使用删除还是更新? 这里无非是删除还是更新Redis,直接删除的方式比较简单,在下一次查询时会生成缓存(更推荐);更新缓存则相较复杂 先操作Redis还是先操作数据库? 先操作数据库 (推荐) 流程:先更新数据库,再删除缓存 问题:比如线程1执行写操作(修改数据库->删除缓存),线程2执行读操作(查询缓存->旧数据),就会出现旧数据返回,或者删除缓存失败也会返回旧数据 先操作缓存 流程:修改操作先删除缓存再修改数据库 问题: 比如线程1去执行写操作: (删除缓存->更新数据库)同时有线程2执行读操作(查询缓存(未查到缓存)->查数据库->保存到缓存)因为数据库更新有可能网络延迟等问题,这里保存到缓存的数据就是旧的数据,只有再过期之后才会读到新数据 解决方案: (延迟双删)在数据库更新之后再进行一次缓存删除(加适当延迟,比如延迟500ms),这时再有查询过来也会查询到数据库并保存到缓存。但是线程2在这个删除缓存500ms内请求仍然可能会出现一次获取到旧数据 (推荐方式)

2024年02月20日 · 1 min · Leanku

Redis的数据类型及使用场景

Redis的数据类型及使用场景 一、基本数据类型 1.字符串(String) string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。 string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。 string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。 常用命令: SET key value 设置指定 key 的值。 GET key 获取指定 key 的值。 应用场景: String 是最常用的一种数据类型,普通的 key/value 存储都可以归为此类,即可以完全实现目前 Memcached 的功能,并且效率更高。还可以享受 Redis 的定时持久化,操作日志及 Replication 等功能。除了提供与 Memcached 一样的 get、set、incr、decr 等操作外,Redis 还提供了下面一些操作: 获取字符串长度 往字符串 append 内容 设置和获取字符串的某一段内容 设置及获取字符串的某一位(bit) 批量设置一系列字符串的内容 使用场景: 常规 key-value 缓存应用。常规计数:微博数,粉丝数。 实现方式: String 在 redis 内部存储默认就是一个字符串,被 redisObject 所引用,当遇到 incr,decr 等操作时会转成数值型进行计算,此时 redisObject 的 encoding 字段为 int...

2023年09月01日 · 7 min · Leanku

Redis事务和锁

Redis事务 事务是指一个完整的动作,要么全部执行,要么什么也没有做。Redis 事务不是严格意义上的事务,只是用于帮助用户在一个步骤中执行多个命令。单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。 Redis 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。 Redis 的事务不是原子性,但是Redi执行每一个命令都是原子性的 举例:INCR在redis中是自增,即使多个客户端对同一个密钥发出INCR,也永远不会进入竞争状态。例如,客户机1读取“10”,客户机2同时读取“10”,两者都增加到11,并将新值设置为11,这样的情况永远不会发生。最终的值将始终是12。 这个案例是官网提出来的:https://redis.io/docs/data-types/tutorial/ 事务一般都是为原子性而生,既然Redis事务没有原子性,那他存在的意义是什么? redis事务的主要作用就是串联多个命令防止 别的命令插队。 官网介绍:https://redis.com.cn/redis-transaction.html Redis事务 - 基本使用 Redis 在形式上看起来也差不多,MULTI、EXEC、DISCARD这三个指令构成了 redis 事务处理的基础: MULTI:用来组装一个事务,从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,redis会将之前的命令依次执行。 EXEC:用来执行一个事务 DISCARD:用来取消一个事务 所有的指令在 exec 之前不执行,而是缓存在服务器的一个事务队列中,服务器一旦收到 exec 指令,才开执行整个事务队列,执行完毕后一次性返回所有指令的运行结果。因为 Redis 的单线程特性,不用担心自己在执行队列的时候被其它指令打搅,可以保证他们能得到的有顺序的执行。 取消事务,放弃执行事务块内的所有命令。 组队中某个命令出现了错误报告,执行时整个队列中所有的命令都会被取消。 命令组队的过程中没有问题,执行中出现了错误会导致部分成功部分失败。 悲观锁&乐观锁 悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人拿到这个数据就会block直到它拿到锁。传统的关系型数据库里面就用到了很多这种锁机制,比如行锁、表锁、读锁、写锁等,都是在做操作之前先上锁。 乐观锁(Optimistic Lock),顾名思义,就是很乐观,每次去那数据的时候都认为别人不会修改,所以不会上锁,但是在修改的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。redis就是使用这种check-and-set机制实现事务的。 watch监听 WATCH:在执行multi之前,先执行watch key1 [key2 …],可以监视一个或者多个key,若在事务的exec命令之前这些key对应的值被其他命令所改动了,那么事务中所有命令都将被打断,即事务所有操作将被取消执行。 unwatch:取消 WATCH 命令对所有 key 的监视。如果在执行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行UNWATCH 了。 简单示例秒杀场景 <?php // 连接Redis $redis = new Redis(); $redis->connect('127.0.0.1',6379); $redis->watch('sales'); $sales = $redis->get('sales'); $store = 10; if($sales >= $store){ exit('结束'); } // 事务 $redis->multi(); $redis->incr('sales'); $res = $redis->exec(); if($res){ // 库存更新....

2023年05月28日 · 1 min · Leanku