乐闻世界logo
搜索文章和话题

面试题手册

Redis 与 MySQL、MongoDB、Memcached 有什么区别?如何选择?

Redis 与其他数据库(如 MySQL、MongoDB、Memcached)在多个方面存在显著差异,理解这些差异有助于在实际项目中做出正确的技术选型。1. Redis vs MySQL数据存储方式Redis:基于内存存储,数据主要在内存中支持持久化到磁盘(RDB、AOF)适合存储热点数据、缓存数据MySQL:基于磁盘存储,数据主要在磁盘上支持内存表(MEMORY 引擎)适合存储持久化数据、结构化数据数据结构Redis:支持丰富的数据结构:String、Hash、List、Set、ZSet、Bitmap、HyperLogLog、Geo数据结构简单,适合键值对存储不支持复杂的关系查询MySQL:支持关系型数据模型,支持表、索引、外键等支持复杂的 SQL 查询支持事务(ACID)性能特点Redis:读写速度极快,单机可达 10 万+ QPS支持高并发适合读多写少的场景MySQL:读写速度相对较慢,单机几千到几万 QPS支持读写分离、分库分表适合复杂的查询场景适用场景Redis:缓存会话存储计数器排行榜消息队列实时统计MySQL:用户信息订单信息商品信息交易记录复杂查询2. Redis vs MongoDB数据存储方式Redis:基于内存存储支持持久化数据结构简单MongoDB:基于磁盘存储支持内存映射文件文档型数据库数据结构Redis:键值对存储支持多种数据结构不支持复杂查询MongoDB:文档型存储(BSON 格式)支持嵌套文档支持复杂的查询和聚合性能特点Redis:读写速度极快适合简单操作不支持复杂查询MongoDB:读写速度较快支持复杂查询支持索引优化适用场景Redis:缓存实时数据简单的键值对存储MongoDB:文档存储内容管理日志存储大数据存储3. Redis vs Memcached数据存储方式Redis:基于内存存储支持持久化支持数据结构Memcached:基于内存存储不支持持久化只支持简单的键值对数据结构Redis:支持多种数据结构支持复杂操作支持事务Memcached:只支持 String 类型只支持简单的 GET/SET 操作不支持事务性能特点Redis:读写速度极快支持复杂操作支持持久化Memcached:读写速度极快只支持简单操作不支持持久化适用场景Redis:缓存会话存储排行榜计数器消息队列Memcached:简单的缓存对象缓存数据库查询缓存4. 技术选型建议选择 Redis 的场景需要高性能缓存:Redis 的读写速度极快,适合作为缓存层需要丰富的数据结构:Redis 支持多种数据结构,适合复杂的数据操作需要持久化:Redis 支持持久化,数据不会因为重启而丢失需要高可用:Redis 支持主从复制、哨兵模式、集群模式,可以实现高可用需要实时统计:Redis 支持实时统计,如计数器、排行榜等选择 MySQL 的场景需要持久化存储:MySQL 基于磁盘存储,适合持久化数据需要复杂查询:MySQL 支持 SQL 查询,适合复杂的业务逻辑需要事务支持:MySQL 支持 ACID 事务,适合需要事务的场景需要关系型数据:MySQL 支持关系型数据模型,适合关系型数据选择 MongoDB 的场景需要文档存储:MongoDB 是文档型数据库,适合存储文档需要灵活的数据结构:MongoDB 支持灵活的数据结构,适合快速迭代需要大数据存储:MongoDB 支持大数据存储,适合大数据场景需要水平扩展:MongoDB 支持水平扩展,适合大规模数据选择 Memcached 的场景需要简单的缓存:Memcached 只支持简单的键值对,适合简单的缓存场景不需要持久化:Memcached 不支持持久化,适合临时数据不需要复杂操作:Memcached 只支持简单的 GET/SET 操作,适合简单场景5. 混合使用方案在实际项目中,通常会混合使用多种数据库:Redis + MySQLRedis 作为缓存层:缓存热点数据,减轻 MySQL 压力MySQL 作为持久化层:存储持久化数据,保证数据安全读写分离:Redis 处理读操作,MySQL 处理写操作Redis + MongoDBRedis 作为缓存层:缓存热点数据,减轻 MongoDB 压力MongoDB 作为存储层:存储文档型数据,提供灵活的数据结构Redis + MemcachedRedis 作为主缓存:存储需要持久化的数据Memcached 作为辅助缓存:存储临时数据,提高缓存性能总结Redis、MySQL、MongoDB、Memcached 各有优缺点,选择时需要根据具体的业务场景和需求。Redis 适合高性能缓存和实时数据,MySQL 适合持久化存储和复杂查询,MongoDB 适合文档存储和大数据,Memcached 适合简单的缓存场景。在实际项目中,通常会混合使用多种数据库,发挥各自的优势。
阅读 0·2月19日 19:38

Redis 事务、Lua 脚本和分布式锁的实现原理和使用场景是什么?

Redis 事务、Lua 脚本和分布式锁是 Redis 的高级特性,在实际开发中经常使用。1. Redis 事务基本概念:Redis 事务通过 MULTI、EXEC、DISCARD、WATCH 等命令实现,可以一次性执行多个命令,保证这些命令要么全部执行,要么全部不执行。基本用法:# 开启事务MULTI# 执行命令(命令会被放入队列)SET key1 value1SET key2 value2GET key1# 执行事务EXEC特点:原子性:事务中的命令要么全部执行,要么全部不执行隔离性:事务执行过程中,其他客户端的命令不会插入不支持回滚:Redis 事务不支持回滚,如果某个命令执行失败,其他命令仍会执行WATCH 命令:WATCH 命令用于实现乐观锁,在事务执行前监控一个或多个 key,如果在事务执行前这些 key 被其他客户端修改,事务将不会执行。# 监控 keyWATCH balance# 开启事务MULTI# 执行命令DECRBY balance 100# 执行事务(如果 balance 被其他客户端修改,事务将不会执行)EXEC事务的局限性:不支持条件判断不支持循环不支持复杂逻辑2. Lua 脚本基本概念:Lua 脚本可以在 Redis 服务器端执行,支持复杂的逻辑操作,保证原子性。基本用法:# 执行 Lua 脚本EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 mykey myvalue# 加载脚本并返回脚本 SHASCRIPT LOAD "return redis.call('SET', KEYS[1], ARGV[1])"# 使用 SHA 执行脚本EVALSHA <sha> 1 mykey myvalueLua 脚本的优势:原子性:Lua 脚本执行期间,其他客户端的命令不会插入减少网络往返:多个操作可以在服务器端一次性完成支持复杂逻辑:支持条件判断、循环等复杂逻辑复用性:脚本可以重复使用,提高性能Lua 脚本示例:示例一:实现分布式锁-- 获取锁if redis.call("SETNX", KEYS[1], ARGV[1]) == 1 then redis.call("EXPIRE", KEYS[1], ARGV[2]) return 1else return 0end示例二:限流器-- 限流器local key = KEYS[1]local limit = tonumber(ARGV[1])local current = tonumber(redis.call("GET", key) or "0")if current + 1 > limit then return 0else redis.call("INCR", key) redis.call("EXPIRE", key, ARGV[2]) return 1end示例三:原子操作-- 原子操作:只有当 key 的值等于 expected 时才更新local current = redis.call("GET", KEYS[1])if current == ARGV[1] then redis.call("SET", KEYS[1], ARGV[2]) return 1else return 0endLua 脚本的注意事项:Lua 脚本执行时间不能过长,否则会阻塞 RedisLua 脚本中不能使用随机函数,否则会导致脚本在不同节点执行结果不一致Lua 脚本中不能使用阻塞命令3. 分布式锁基本概念:分布式锁用于在分布式系统中实现互斥访问,确保同一时间只有一个客户端能够访问共享资源。实现方式一:SETNX + EXPIREpublic boolean tryLock(String key, String value, int expireTime) { // 使用 SETNX 设置锁 Long result = redis.setnx(key, value); if (result == 1) { // 设置过期时间 redis.expire(key, expireTime); return true; } return false;}public void unlock(String key, String value) { // 只有锁的持有者才能释放锁 String currentValue = redis.get(key); if (value.equals(currentValue)) { redis.del(key); }}实现方式二:SET NX EX(推荐)public boolean tryLock(String key, String value, int expireTime) { // 使用 SET NX EX 命令,原子性设置锁和过期时间 String result = redis.set(key, value, "NX", "EX", expireTime); return "OK".equals(result);}public void unlock(String key, String value) { // 使用 Lua 脚本保证原子性 String script = "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end"; redis.eval(script, Collections.singletonList(key), Collections.singletonList(value));}实现方式三:Redlock 算法Redlock 是 Redis 官方推荐的分布式锁算法,适用于 Redis Cluster 场景。public boolean tryLock(String key, String value, int expireTime) { // 获取多个 Redis 节点的锁 int successCount = 0; for (RedisClient client : redisClients) { if (client.set(key, value, "NX", "EX", expireTime).equals("OK")) { successCount++; } } // 如果大多数节点获取锁成功,则认为获取锁成功 return successCount > redisClients.size() / 2;}分布式锁的注意事项:锁的过期时间:需要设置合理的过期时间,避免死锁锁的续期:对于长时间任务,需要实现锁的续期机制锁的可重入性:同一个线程可以多次获取同一个锁锁的释放:只有锁的持有者才能释放锁Redisson 分布式锁:Redisson 是一个功能强大的 Redis 客户端,提供了完整的分布式锁实现。// 获取锁RLock lock = redisson.getLock("myLock");try { // 尝试获取锁,最多等待 10 秒,锁自动释放时间为 30 秒 boolean locked = lock.tryLock(10, 30, TimeUnit.SECONDS); if (locked) { // 执行业务逻辑 }} finally { // 释放锁 lock.unlock();}4. 事务 vs Lua 脚本 vs 分布式锁| 特性 | 事务 | Lua 脚本 | 分布式锁 ||------|------|----------|---------|| 原子性 | 支持 | 支持 | 支持 || 复杂逻辑 | 不支持 | 支持 | 不支持 || 网络往返 | 多次 | 一次 | 多次 || 适用场景 | 简单批量操作 | 复杂逻辑操作 | 互斥访问 |5. 最佳实践使用事务的场景:需要原子性执行多个简单命令不需要条件判断和循环使用 Lua 脚本的场景:需要原子性执行多个复杂命令需要条件判断和循环需要减少网络往返使用分布式锁的场景:需要在分布式系统中实现互斥访问需要防止并发问题总结Redis 事务、Lua 脚本和分布式锁是 Redis 的高级特性,各有其适用场景。事务适合简单的批量操作,Lua 脚本适合复杂的逻辑操作,分布式锁适合互斥访问。在实际开发中,需要根据具体的业务场景,选择合适的技术方案。同时,需要注意这些技术的局限性和注意事项,确保系统的稳定性和可靠性。
阅读 0·2月19日 19:38

Redis 常见问题有哪些?如何解决这些问题?

Redis 在使用过程中会遇到各种常见问题,了解这些问题及其解决方案对于保证 Redis 的稳定性和性能至关重要。1. Redis 为什么这么快?原因分析基于内存存储:Redis 将所有数据存储在内存中,内存的读写速度远快于磁盘内存访问时间在纳秒级别,而磁盘访问时间在毫秒级别单线程模型:Redis 使用单线程模型处理命令,避免了多线程的上下文切换和锁竞争单线程模型简化了实现,减少了并发问题I/O 多路复用:Redis 使用 I/O 多路复用模型(epoll、kqueue、select),可以同时处理多个客户端连接I/O 多路复用避免了阻塞,提高了并发处理能力高效的数据结构:Redis 使用了高效的数据结构,如 SDS、跳跃表、压缩列表等这些数据结构针对特定场景进行了优化,提高了操作效率优化的命令执行:Redis 的命令执行经过了高度优化,减少了不必要的操作使用了批量操作(Pipeline)减少网络往返2. Redis 为什么选择单线程?优势避免上下文切换:多线程需要频繁的上下文切换,消耗 CPU 资源单线程避免了上下文切换,提高了 CPU 利用率避免锁竞争:多线程需要使用锁来保证数据一致性,锁竞争会降低性能单线程不需要锁,避免了锁竞争带来的性能损失简化实现:单线程模型简化了实现,减少了并发问题的复杂性代码更容易维护和调试内存友好:单线程模型对 CPU 缓存更友好,提高了缓存命中率为什么单线程仍然高性能?Redis 的瓶颈不在 CPU:Redis 的瓶颈主要在网络 I/O 和内存访问,而不是 CPU单线程足以处理网络 I/O 和内存访问I/O 多路复用:Redis 使用 I/O 多路复用,可以同时处理多个客户端连接单线程可以高效地处理多个连接基于内存:Redis 基于内存存储,内存访问速度极快单线程可以充分利用内存的高性能多线程 RedisRedis 6.0 引入了多线程,主要用于网络 I/O 的读写:网络 I/O 多线程:网络 I/O 的读写使用多线程,提高网络处理能力命令执行单线程:命令执行仍然使用单线程,保证数据一致性3. Redis 如何保证数据一致性?缓存一致性问题:缓存和数据库的数据不一致,导致读取到脏数据解决方案:方案一:Cache Aside Pattern// 读操作public User getUserById(Long id) { User user = redis.get("user:" + id); if (user != null) { return user; } user = db.queryUserById(id); redis.set("user:" + id, user, 3600); return user;}// 写操作public void updateUser(User user) { db.updateUser(user); redis.del("user:" + user.getId());}方案二:延时双删public void updateUser(User user) { db.updateUser(user); redis.del("user:" + user.getId()); // 第一次删除 try { Thread.sleep(500); // 延时 } catch (InterruptedException e) { e.printStackTrace(); } redis.del("user:" + user.getId()); // 第二次删除}方案三:订阅 Binlog// 订阅数据库的 Binlog,当数据库变更时,自动更新缓存@CanalEventListenerpublic class CacheUpdateListener { @ListenPoint(destination = "example", schema = "test", table = "user") public void onEvent(CanalEntry.Entry entry) { // 解析 Binlog,更新缓存 User user = parseUserFromBinlog(entry); redis.set("user:" + user.getId(), user, 3600); }}主从一致性问题:主从复制存在延迟,导致从节点读取到旧数据解决方案:方案一:读写分离// 写操作使用主节点public void updateUser(User user) { masterRedis.set("user:" + user.getId(), user);}// 读操作使用从节点public User getUserById(Long id) { return slaveRedis.get("user:" + id);}方案二:强制读主节点// 对于需要强一致性的数据,强制读主节点public User getUserByIdWithConsistency(Long id) { return masterRedis.get("user:" + id);}4. Redis 如何处理大 Key?大 Key 的危害内存占用高:大 Key 占用大量内存,影响其他数据的存储性能问题:大 Key 的读写操作耗时较长,影响 Redis 性能大 Key 的删除操作会阻塞 Redis,导致其他请求等待主从同步慢:大 Key 的主从同步耗时较长,影响主从同步效率解决方案方案一:拆分大 Key// 将大 Key 拆分成多个小 Keypublic void setBigKey(String key, String value) { int chunkSize = 1024; // 每个块 1KB for (int i = 0; i < value.length(); i += chunkSize) { String chunk = value.substring(i, Math.min(i + chunkSize, value.length())); redis.set(key + ":" + i, chunk); }}public String getBigKey(String key) { StringBuilder sb = new StringBuilder(); int i = 0; while (true) { String chunk = redis.get(key + ":" + i); if (chunk == null) { break; } sb.append(chunk); i++; } return sb.toString();}方案二:使用 Hash// 使用 Hash 存储大对象public void setBigObject(String key, Map<String, String> data) { for (Map.Entry<String, String> entry : data.entrySet()) { redis.hset(key, entry.getKey(), entry.getValue()); }}public Map<String, String> getBigObject(String key) { return redis.hgetAll(key);}方案三:异步删除// 使用 UNLINK 命令异步删除大 Keypublic void deleteBigKey(String key) { redis.unlink(key); // 异步删除,不会阻塞 Redis}5. Redis 如何处理热点 Key?热点 Key 的危害单节点压力:热点 Key 集中在某个节点,导致该节点压力过大性能瓶颈:热点 Key 的访问量过大,导致性能瓶颈解决方案方案一:读写分离// 读操作使用从节点public User getUserById(Long id) { return slaveRedis.get("user:" + id);}方案二:本地缓存// 使用本地缓存减少 Redis 访问public User getUserById(Long id) { // 先查本地缓存 User user = localCache.get("user:" + id); if (user != null) { return user; } // 再查 Redis user = redis.get("user:" + id); if (user != null) { localCache.put("user:" + id, user); } return user;}方案三:热点 Key 拆分// 将热点 Key 拆分成多个 Keypublic void setHotKey(String key, String value) { int shardCount = 10; for (int i = 0; i < shardCount; i++) { redis.set(key + ":" + i, value); }}public String getHotKey(String key) { int shard = (int) (Math.random() * 10); return redis.get(key + ":" + shard);}6. Redis 如何实现分布式锁?实现方式方案一:SET NX EXpublic boolean tryLock(String key, String value, int expireTime) { String result = redis.set(key, value, "NX", "EX", expireTime); return "OK".equals(result);}public void unlock(String key, String value) { String script = "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end"; redis.eval(script, Collections.singletonList(key), Collections.singletonList(value));}方案二:Redlockpublic boolean tryLock(String key, String value, int expireTime) { int successCount = 0; for (RedisClient client : redisClients) { if (client.set(key, value, "NX", "EX", expireTime).equals("OK")) { successCount++; } } return successCount > redisClients.size() / 2;}方案三:Redissonpublic void doWithLock(String lockKey, Runnable task) { RLock lock = redisson.getLock(lockKey); try { lock.lock(); task.run(); } finally { lock.unlock(); }}7. Redis 如何实现限流?实现方式方案一:固定窗口public boolean allowRequest(String key, int limit, int expireTime) { String count = redis.get(key); if (count == null) { redis.set(key, "1", expireTime); return true; } int currentCount = Integer.parseInt(count); if (currentCount < limit) { redis.incr(key); return true; } return false;}方案二:滑动窗口public boolean allowRequestSliding(String key, int limit, int windowSize) { long currentTime = System.currentTimeMillis(); long windowStart = currentTime - windowSize; redis.zremrangeByScore(key, 0, windowStart); redis.zadd(key, currentTime, UUID.randomUUID().toString()); long count = redis.zcard(key); return count <= limit;}方案三:令牌桶public boolean allowRequestTokenBucket(String key, int capacity, int rate) { String script = "local tokens = tonumber(redis.call('get', KEYS[1])) or 0" + "tokens = math.min(tokens + ARGV[1], ARGV[2])" + "if tokens >= 1 then" + " redis.call('set', KEYS[1], tokens - 1)" + " return 1" + "else" + " redis.call('set', KEYS[1], tokens)" + " return 0" + "end"; return redis.eval(script, Collections.singletonList(key), Collections.singletonList(rate), Collections.singletonList(capacity)) == 1;}总结Redis 在使用过程中会遇到各种常见问题,包括性能问题、一致性问题、大 Key 问题、热点 Key 问题等。了解这些问题及其解决方案,对于保证 Redis 的稳定性和性能至关重要。在实际应用中,需要根据具体的业务场景,选择合适的解决方案。
阅读 0·2月19日 19:38

Redis 性能优化有哪些策略?如何提高 Redis 的性能?

Redis 性能优化是一个系统工程,需要从多个维度进行优化。以下是 Redis 性能优化的关键策略:1. 内存优化选择合适的数据结构:使用 Hash 存储对象,而不是多个 String使用 ZSet 存储排行榜,而不是 List使用 Bitmap 存储布尔值,而不是 Set使用 HyperLogLog 进行基数统计,而不是 Set控制键的命名:使用简短但有意义的键名,减少内存占用避免过长的键名,如 user:profile:1001:detail:info 可以简化为 u:1001:pf使用压缩列表:Hash 和 List 在元素较少时会自动使用 ziplist调整 hash-max-ziplist-entries 和 hash-max-ziplist-value 参数调整 list-max-ziplist-size 参数设置过期时间:为临时数据设置合理的过期时间,避免内存泄漏使用 EXPIRE、EXPIREAT、TTL 等命令管理过期时间2. 网络优化使用 Pipeline:Pipeline 可以将多个命令打包发送,减少网络往返次数适合批量操作,如批量插入、批量查询# 使用 Pipeline 批量设置echo -e "SET key1 value1\nSET key2 value2\nSET key3 value3" | redis-cli --pipe使用连接池:客户端使用连接池,避免频繁创建和销毁连接合理设置连接池大小,避免连接数过多减少大 Key:大 Key 会导致网络传输慢、内存占用高将大 Key 拆分成多个小 Key使用 Hash 存储大对象,而不是 String禁用 THP(Transparent Huge Pages):echo never > /sys/kernel/mm/transparent_hugepage/enabled3. CPU 优化避免使用 KEYS 命令:KEYS 命令会阻塞 Redis,导致性能问题使用 SCAN 命令替代 KEYS,进行增量迭代# 使用 SCAN 替代 KEYSSCAN 0 MATCH user:* COUNT 100避免使用复杂操作:避免使用大范围的 SORT 操作避免使用 SUNION、SINTER 等大集合操作使用 Lua 脚本减少网络往返使用 Lua 脚本:Lua 脚本在服务器端执行,减少网络往返适合复杂的原子操作-- 使用 Lua 脚本实现原子操作if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1])else return 0end4. 持久化优化合理配置 RDB:调整 RDB 保存频率,避免过于频繁在低峰期进行 RDB 保存关闭 RDB 压缩可以提高性能,但会增加文件大小合理配置 AOF:使用 appendfsync everysec 平衡性能和数据安全调整 auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size在低峰期进行 AOF 重写使用混合持久化:开启 aof-use-rdb-preamble yes,兼顾性能和数据安全5. 集群优化数据分片:使用 Redis Cluster 进行数据分片,提高并发能力合理分配哈希槽,避免数据倾斜读写分离:使用主从复制,将读操作分散到从节点使用哨兵模式实现自动故障转移负载均衡:客户端实现负载均衡,将请求分散到不同节点使用一致性哈希算法,减少节点变更时的数据迁移6. 监控和调优使用 Redis 慢查询日志:# 配置慢查询日志CONFIG SET slowlog-log-slower-than 10000 # 10msCONFIG SET slowlog-max-len 128# 查看慢查询SLOWLOG GET 10使用 INFO 命令监控:# 查看内存使用情况INFO memory# 查看命令执行情况INFO commandstats# 查看连接情况INFO clients使用 Redis Benchmark:# 性能测试redis-benchmark -h 127.0.0.1 -p 6379 -c 50 -n 100007. 操作系统优化调整文件描述符限制:# 临时调整ulimit -n 65535# 永久调整echo "* soft nofile 65535" >> /etc/security/limits.confecho "* hard nofile 65535" >> /etc/security/limits.conf调整 TCP 参数:# 启用 TCP 快速打开echo 3 > /proc/sys/net/ipv4/tcp_fastopen# 调整 TCP 缓冲区大小echo "net.core.rmem_max = 16777216" >> /etc/sysctl.confecho "net.core.wmem_max = 16777216" >> /etc/sysctl.conf8. 客户端优化使用高性能客户端:选择性能好的 Redis 客户端,如 Jedis、Lettuce、Redisson使用异步客户端,提高并发能力合理使用缓存:客户端本地缓存热点数据,减少 Redis 访问使用多级缓存策略,如本地缓存 + Redis 缓存避免 N+1 查询:使用 Pipeline 或 MGET 批量查询使用 Hash 存储相关数据,减少查询次数9. 架构优化使用 Redis Proxy:使用 Twemproxy、Codis 等 Redis Proxy,实现分片和负载均衡减少客户端的复杂度使用 Redis Sentinel:使用哨兵模式实现高可用自动故障转移,提高系统可靠性使用 Redis Cluster:使用集群模式实现水平扩展提高系统的并发能力和数据容量总结Redis 性能优化需要从多个维度进行,包括内存优化、网络优化、CPU 优化、持久化优化、集群优化、监控和调优、操作系统优化、客户端优化和架构优化。在实际应用中,需要根据具体的业务场景和性能瓶颈,选择合适的优化策略。同时,需要持续监控 Redis 的运行状态,及时发现和解决性能问题。
阅读 0·2月19日 19:38

Redis 的主从复制、哨兵模式和集群模式有什么区别?如何选择?

Redis 提供了三种集群方案:主从复制、哨兵模式和集群模式,它们各有不同的适用场景和特点。1. 主从复制(Master-Slave Replication)工作原理:主从复制是指将一个 Redis 节点作为主节点(Master),其他节点作为从节点(Slave)。主节点负责写操作,从节点负责读操作。主节点将数据变更同步到从节点。特点:读写分离:主节点处理写操作,从节点处理读操作,提高系统吞吐量数据备份:从节点是主节点的完整副本,提供数据冗余故障恢复:主节点故障时,需要手动将从节点提升为主节点配置方式:# 在从节点配置文件中添加slaveof <master-ip> <master-port>缺点:主节点故障时需要手动切换,无法自动故障转移主节点的写能力受限,无法水平扩展2. 哨兵模式(Sentinel)工作原理:哨兵模式是在主从复制的基础上,增加了哨兵节点。哨兵节点监控主从节点的运行状态,当主节点故障时,自动将从节点提升为主节点,实现自动故障转移。特点:自动故障转移:主节点故障时,自动选举新的主节点监控:实时监控主从节点的健康状态通知:当主节点故障时,通知管理员配置提供者:客户端可以从哨兵获取当前主节点的地址哨兵工作流程:哨兵定期向主从节点发送 PING 命令检查健康状态如果主节点在指定时间内无响应,哨兵会标记主节点为主观下线当足够多的哨兵都认为主节点下线时,主节点被标记为客观下线哨兵选举出一个领头哨兵,负责故障转移领头哨兵从从节点中选举出新的主节点其他从节点重新配置,指向新的主节点配置方式:# 哨兵配置文件 sentinel.confport 26379sentinel monitor mymaster 127.0.0.1 6379 2sentinel down-after-milliseconds mymaster 30000sentinel parallel-syncs mymaster 1sentinel failover-timeout mymaster 180000缺点:主节点的写能力仍然受限,无法水平扩展哨兵节点本身也可能成为单点故障3. 集群模式(Cluster)工作原理:Redis Cluster 采用去中心化的架构,将数据分片存储在多个节点上。每个节点负责一部分数据,通过哈希槽(Hash Slot)实现数据分片。特点:数据分片:将数据分散到多个节点,实现水平扩展高可用:每个主节点可以有多个从节点,主节点故障时自动故障转移无中心节点:所有节点地位平等,没有单点故障自动故障转移:主节点故障时,从节点自动提升为主节点哈希槽机制:Redis Cluster 共有 16384 个哈希槽(0-16383)每个节点负责一部分哈希槽使用 CRC16(key) % 16384 计算键对应的哈希槽客户端根据哈希槽定位到对应的节点配置方式:# 集群配置文件 redis.confcluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000cluster-require-full-coverage yes创建集群:redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \--cluster-replicas 1缺点:不支持多键操作(除非这些键在同一个哈希槽)客户端需要支持集群协议事务支持有限三种方案对比| 特性 | 主从复制 | 哨兵模式 | 集群模式 ||------|---------|---------|---------|| 数据分片 | 不支持 | 不支持 | 支持 || 自动故障转移 | 不支持 | 支持 | 支持 || 读写分离 | 支持 | 支持 | 支持 || 水平扩展 | 不支持 | 不支持 | 支持 || 复杂度 | 低 | 中 | 高 || 适用场景 | 简单读写分离 | 高可用场景 | 大规模数据 |选择建议数据量小,需要读写分离:使用主从复制数据量小,需要高可用:使用哨兵模式数据量大,需要水平扩展:使用集群模式生产环境推荐:使用哨兵模式或集群模式,根据数据量选择在实际应用中,大多数生产环境会选择哨兵模式或集群模式,以确保系统的高可用性和可扩展性。
阅读 0·2月19日 19:37

Redis 的 RDB 和 AOF 持久化有什么区别?如何选择?

Redis 提供了两种持久化方式:RDB(Redis Database)和 AOF(Append Only File),它们各有优缺点,也可以同时使用。RDB 持久化工作原理:RDB 是在指定的时间间隔内生成数据集的时间点快照。Redis 会 fork 一个子进程,将内存中的数据写入到一个临时文件中,然后用这个临时文件替换旧的 RDB 文件。优点:文件紧凑:RDB 文件是压缩的二进制文件,体积小,适合备份和灾难恢复恢复速度快:RDB 文件的恢复速度比 AOF 快,因为不需要重新执行命令对性能影响小:RDB 是由子进程执行的,对主进程性能影响较小适合冷备份:RDB 文件可以方便地传输到远程服务器进行备份缺点:数据丢失风险:如果 Redis 突然宕机,可能会丢失最后一次快照之后的所有数据fork 操作耗时:当数据量很大时,fork 子进程可能会阻塞主进程实时性差:RDB 是基于时间间隔的,无法做到实时持久化配置参数:save <seconds> <changes>:设置保存条件,如 save 900 1 表示 900 秒内至少有 1 个 key 变化就保存rdbcompression yes:是否压缩 RDB 文件rdbchecksum yes:是否对 RDB 文件进行校验AOF 持久化工作原理:AOF 记录服务器接收到的每一个写操作命令,将这些命令追加到 AOF 文件的末尾。Redis 重启时,会重新执行 AOF 文件中的命令来恢复数据。优点:数据安全性高:AOF 可以配置为每秒同步或每次写操作同步,数据丢失风险低可读性强:AOF 文件是文本格式,可以手动查看和修改自动重写:AOF 文件过大时会自动重写,压缩文件体积缺点:文件体积大:AOF 文件通常比 RDB 文件大恢复速度慢:需要重新执行所有命令,恢复速度比 RDB 慢性能影响大:每次写操作都需要同步到磁盘,对性能影响较大配置参数:appendonly yes:开启 AOF 持久化appendfsync always/everysec/no:同步策略always:每次写操作都同步,最安全但性能最差everysec:每秒同步一次,推荐配置no:由操作系统决定何时同步,性能最好但安全性最差auto-aof-rewrite-percentage 100:AOF 文件重写的增长百分比auto-aof-rewrite-min-size 64mb:AOF 文件重写的最小大小RDB + AOF 混合持久化Redis 4.0 之后支持混合持久化,开启后,AOF 重写时会将 RDB 的内容写入 AOF 文件开头,后续的增量命令继续以 AOF 格式追加。这样既保证了数据安全性,又提高了恢复速度。配置:aof-use-rdb-preamble yes:开启混合持久化选择建议如果对数据安全性要求不高:只使用 RDB,性能更好如果对数据安全性要求很高:只使用 AOF,配置为 appendfsync everysec如果既要性能又要安全性:使用 RDB + AOF 混合持久化如果数据量很大:建议使用 RDB,因为 AOF 的恢复速度太慢在实际生产环境中,通常会同时开启 RDB 和 AOF,或者使用混合持久化,以兼顾性能和数据安全性。
阅读 0·2月19日 19:37

Redis 支持哪些数据结构?它们的使用场景和底层实现是什么?

Redis 支持多种数据结构,每种数据结构都有其特定的使用场景和底层实现:1. String(字符串)底层实现:使用 SDS(Simple Dynamic String)实现,类似于 C 语言的字符串,但增加了长度信息和空间预分配。使用场景:缓存用户信息、配置信息计数器(INCR、DECR 命令)分布式锁Session 存储常用命令:SET、GET、INCR、DECR、MGET、MSET、SETEX 等2. Hash(哈希)底层实现:当元素较少时使用 ziplist(压缩列表),当元素较多时使用 hashtable(哈希表)。使用场景:存储对象(如用户信息)购物车文章点赞数统计常用命令:HSET、HGET、HMGET、HGETALL、HINCRBY、HDEL 等3. List(列表)底层实现:当元素较少时使用 ziplist,当元素较多时使用 linkedlist(双向链表)或 quicklist。使用场景:消息队列最新列表(如最新文章)时间轴栈和队列操作常用命令:LPUSH、RPUSH、LPOP、RPOP、LRANGE、LLEN、LTRIM 等4. Set(集合)底层实现:使用 intset(整数集合)或 hashtable 实现。使用场景:标签系统共同关注/共同好友抽奖系统去重常用命令:SADD、SREM、SMEMBERS、SISMEMBER、SINTER、SUNION 等5. ZSet(有序集合)底层实现:使用 skiplist(跳跃表)和 hashtable 的组合,hashtable 用于快速查找,skiplist 用于排序。使用场景:排行榜延时队列优先级队列范围查询常用命令:ZADD、ZREM、ZRANGE、ZREVRANGE、ZRANK、ZSCORE 等6. Bitmap(位图)底层实现:基于 String 类型实现,每个 bit 位表示一个状态。使用场景:用户签到统计在线用户统计布隆过滤器常用命令:SETBIT、GETBIT、BITCOUNT、BITOP 等7. HyperLogLog(基数统计)底层实现:使用概率算法,占用 12KB 内存。使用场景:网站独立访客统计(UV)大数据去重统计常用命令:PFADD、PFCOUNT、PFMERGE 等8. Geo(地理位置)底层实现:基于 ZSet 实现,使用 Geohash 算法。使用场景:附近的人距离计算位置服务常用命令:GEOADD、GEODIST、GEOPOS、GEORADIUS 等每种数据结构都有其特定的转换阈值,例如 Hash 和 List 在元素数量和大小超过一定阈值时会从 ziplist 转换为更复杂的数据结构,以平衡内存使用和性能。
阅读 0·2月19日 19:37

Redis 是什么?它有哪些主要特点?

Redis 是一个基于内存的键值存储数据库,它的主要特点包括:高性能:Redis 将所有数据存储在内存中,读写速度极快,单机可以达到每秒 10 万次以上的操作。丰富的数据结构:Redis 支持多种数据类型,包括 String(字符串)、Hash(哈希)、List(列表)、Set(集合)、ZSet(有序集合)、Bitmap(位图)、HyperLogLog(基数统计)、Geo(地理位置)等。持久化支持:Redis 提供了两种持久化方式:RDB(Redis Database):在指定的时间间隔内生成数据集的时间点快照AOF(Append Only File):记录服务器接收到的每一个写操作命令原子性操作:Redis 的所有操作都是原子性的,这意味着要么成功执行,要么完全不执行。支持事务:Redis 通过 MULTI、EXEC、DISCARD、WATCH 等命令支持事务功能。主从复制:Redis 支持主从复制,可以实现数据的读写分离和高可用性。集群支持:Redis Cluster 提供了数据分片和自动故障转移功能,支持水平扩展。发布/订阅:Redis 内置了发布/订阅消息系统,可以实现消息的广播。Lua 脚本支持:Redis 支持 Lua 脚本,可以在服务器端执行复杂的操作。内存优化:Redis 使用了多种内存优化技术,如共享对象、压缩列表等,可以有效减少内存使用。Redis 通常被用作缓存、会话存储、消息队列、排行榜、计数器、实时分析系统等场景。由于其高性能和丰富的数据结构,Redis 已经成为现代应用架构中不可或缺的组件之一。
阅读 0·2月19日 19:37

Redis 如何进行安全配置?有哪些安全最佳实践?

Redis 的安全配置是保护 Redis 服务器免受攻击的重要措施,需要从多个维度进行安全加固。1. 网络安全绑定监听地址问题描述:Redis 默认绑定所有网络接口,容易被攻击者扫描和攻击。解决方案:# 配置文件 redis.confbind 127.0.0.1 10.0.0.1# 只监听本地和内网接口# 避免绑定 0.0.0.0使用防火墙问题描述:Redis 端口对外开放,容易被攻击者访问。解决方案:# 使用 iptables 限制访问iptables -A INPUT -p tcp --dport 6379 -s 10.0.0.0/24 -j ACCEPTiptables -A INPUT -p tcp --dport 6379 -j DROP# 使用 firewalld 限制访问firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" port protocol="tcp" port="6379" accept'firewall-cmd --reload使用 SSL/TLS问题描述:Redis 数据传输未加密,容易被中间人攻击。解决方案:# 生成证书openssl genrsa -out redis.key 2048openssl req -new -key redis.key -out redis.csropenssl x509 -req -days 365 -in redis.csr -signkey redis.key -out redis.crt# 配置 Redis 使用 TLStls-port 6380port 0tls-cert-file /path/to/redis.crttls-key-file /path/to/redis.keytls-ca-cert-file /path/to/ca.crt2. 认证安全设置密码问题描述:Redis 默认无密码,任何人都可以访问。解决方案:# 配置文件 redis.confrequirepass your_strong_password# 或使用命令行CONFIG SET requirepass your_strong_password# 连接时使用密码redis-cli -a your_strong_password使用 ACL(Access Control List)问题描述:Redis 6.0 之前只能设置一个密码,无法精细控制权限。解决方案:# 创建用户ACL SETUSER user1 on >password1 ~user:* +@read# 创建管理员用户ACL SETUSER admin on >admin_password ~* +@all# 查看用户列表ACL LIST# 删除用户ACL DELUSER user1禁用危险命令问题描述:Redis 有一些危险命令,如 FLUSHALL、FLUSHDB、CONFIG 等,容易被滥用。解决方案:# 配置文件 redis.confrename-command FLUSHALL ""rename-command FLUSHDB ""rename-command CONFIG ""rename-command SHUTDOWN ""rename-command DEBUG ""# 或重命名命令rename-command FLUSHALL "REALLY_FLUSH_ALL"3. 数据安全启用持久化问题描述:Redis 默认不启用持久化,数据丢失风险高。解决方案:# 启用 RDB 持久化save 900 1save 300 10save 60 10000# 启用 AOF 持久化appendonly yesappendfsync everysec加密持久化文件问题描述:持久化文件未加密,容易被窃取。解决方案:# 使用文件系统加密# Linux 使用 eCryptfs# macOS 使用 FileVault# Windows 使用 BitLocker# 或使用第三方加密工具# 如 cryptsetup、GPG 等定期备份问题描述:没有定期备份,数据丢失后无法恢复。解决方案:# 定期备份 RDB 文件0 2 * * * cp /var/lib/redis/dump.rdb /backup/dump_$(date +\%Y\%m\%d).rdb# 定期备份 AOF 文件0 3 * * * cp /var/lib/redis/appendonly.aof /backup/appendonly_$(date +\%Y\%m\%d).aof# 备份到远程服务器rsync -avz /backup/ user@remote-server:/backup/4. 运行安全使用非特权用户运行问题描述:Redis 使用 root 用户运行,存在安全风险。解决方案:# 创建 Redis 用户useradd -r -s /bin/false redis# 修改 Redis 配置文件所有者chown redis:redis /etc/redis/redis.confchown redis:redis /var/lib/redis# 使用 Redis 用户运行sudo -u redis redis-server /etc/redis/redis.conf限制文件权限问题描述:Redis 配置文件和数据文件权限过大,容易被篡改。解决方案:# 限制配置文件权限chmod 600 /etc/redis/redis.conf# 限制数据文件权限chmod 700 /var/lib/redis# 限制日志文件权限chmod 600 /var/log/redis/redis.log使用 chroot问题描述:Redis 可以访问整个文件系统,存在安全风险。解决方案:# 配置文件 redis.confchroot /var/lib/redisdir /# 或使用 systemd 的 chroot 功能[Service]User=redisGroup=redisExecStart=/usr/bin/redis-server /etc/redis/redis.confProtectSystem=fullReadWritePaths=/var/lib/redis5. 监控安全启用慢查询日志问题描述:慢查询日志未启用,无法发现异常操作。解决方案:# 配置文件 redis.confslowlog-log-slower-than 10000slowlog-max-len 128# 查看慢查询SLOWLOG GET 10监控异常操作问题描述:无法及时发现异常操作,如大量删除、大量查询等。解决方案:# 使用 Redis Exporter 监控# 配置 Prometheus 抓取数据scrape_configs: - job_name: 'redis' static_configs: - targets: ['localhost:9121']# 配置告警规则groups: - name: redis_alerts rules: - alert: RedisSlowQueries expr: rate(redis_slowlog_length[5m]) > 10 for: 5m labels: severity: warning annotations: summary: "Redis slow queries rate is high"审计日志问题描述:Redis 默认不记录审计日志,无法追踪操作。解决方案:# 配置文件 redis.conflogfile /var/log/redis/redis.logloglevel notice# 使用第三方审计工具# 如 Redis-Audit、Redis-Log 等6. 集群安全主从复制认证问题描述:主从复制未设置认证,容易被恶意从节点连接。解决方案:# 主节点配置masterauth your_master_password# 从节点配置requirepass your_slave_passwordmasterauth your_master_password哨兵模式认证问题描述:哨兵模式未设置认证,容易被恶意哨兵节点连接。解决方案:# 哨兵配置文件 sentinel.confsentinel auth-pass mymaster your_master_passwordsentinel down-after-milliseconds mymaster 30000sentinel parallel-syncs mymaster 1sentinel failover-timeout mymaster 180000集群模式认证问题描述:集群模式未设置认证,容易被恶意节点加入集群。解决方案:# 集群配置文件 redis.confcluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000cluster-require-full-coverage yescluster-auth-file /path/to/cluster_auth_file7. 安全最佳实践定期更新 Redis 版本问题描述:使用旧版本 Redis,存在已知漏洞。解决方案:# 定期检查 Redis 版本redis-server --version# 更新 Redisapt-get updateapt-get install redis-server# 或从源码编译wget https://download.redis.io/redis-stable.tar.gztar -xzf redis-stable.tar.gzcd redis-stablemakemake install定期检查安全配置问题描述:安全配置未定期检查,可能存在安全漏洞。解决方案:# 使用 Redis 安全检查工具# 如 redis-audit、redis-safety 等# 定期检查配置redis-cli CONFIG GET "*"# 定期检查用户权限redis-cli ACL LIST使用安全扫描工具问题描述:未使用安全扫描工具,无法发现安全漏洞。解决方案:# 使用 Nmap 扫描 Redis 端口nmap -p 6379 <redis-server-ip># 使用 Redis 安全扫描工具# 如 redis-rogue-server、redis-attack 等总结Redis 的安全配置需要从网络安全、认证安全、数据安全、运行安全、监控安全、集群安全等多个维度进行加固。在实际应用中,需要根据具体的业务场景和安全要求,选择合适的安全配置。同时,需要定期检查和更新安全配置,确保 Redis 的安全性。
阅读 0·2月19日 19:37

Redis 如何进行监控和运维?有哪些关键指标和工具?

Redis 的监控和运维是保证 Redis 稳定运行的重要环节,需要从多个维度进行监控和管理。1. Redis 监控指标基础指标内存使用情况:# 查看内存使用情况INFO memory# 关键指标used_memory:1024000 # 已使用内存used_memory_human:1.00M # 已使用内存(人类可读)used_memory_rss:2048000 # 操作系统分配的内存used_memory_rss_human:2.00M # 操作系统分配的内存(人类可读)used_memory_peak:2048000 # 历史内存使用峰值used_memory_peak_human:2.00M # 历史内存使用峰值(人类可读)maxmemory:1073741824 # 最大内存限制maxmemory_human:1.00G # 最大内存限制(人类可读)mem_fragmentation_ratio:2.00 # 内存碎片率连接情况:# 查看连接情况INFO clients# 关键指标connected_clients:10 # 已连接客户端数blocked_clients:0 # 被阻塞客户端数client_longest_output_list:0 # 最长输出列表client_biggest_input_buf:0 # 最大输入缓冲区命令执行情况:# 查看命令执行情况INFO commandstats# 关键指标cmdstat_get:calls=1000,usec=5000,usec_per_call=5.00cmdstat_set:calls=500,usec=2500,usec_per_call=5.00持久化情况:# 查看持久化情况INFO persistence# 关键指标rdb_last_save_time:1234567890 # 最后一次 RDB 保存时间rdb_changes_since_last_save:100 # 自上次保存以来的变更次数aof_enabled:1 # AOF 是否启用aof_rewrite_in_progress:0 # AOF 重写是否进行中性能指标QPS(每秒查询数):# 计算 QPSINFO stats# 关键指标instantaneous_ops_per_sec:1000 # 当前每秒操作数total_commands_processed:1000000 # 总处理命令数total_connections_received:10000 # 总连接数延迟:# 查看延迟INFO stats# 关键指标instantaneous_input_kbps:100 # 当前输入带宽instantaneous_output_kbps:200 # 当前输出带宽命中率:# 计算命中率keyspace_hits:10000 # 命中次数keyspace_misses:1000 # 未命中次数hit_rate = keyspace_hits / (keyspace_hits + keyspace_misses)2. Redis 监控工具Redis 自带命令INFO 命令:# 查看所有信息INFO# 查看特定信息INFO memoryINFO statsINFO replicationINFO persistenceSLOWLOG 命令:# 查看慢查询SLOWLOG GET 10# 查看慢查询数量SLOWLOG LEN# 清空慢查询SLOWLOG RESETMONITOR 命令:# 实时监控 Redis 命令MONITOR第三方监控工具Redis Exporter:# 安装 Redis Exporterdocker run -d --name redis-exporter \ -e REDIS_ADDR=redis://localhost:6379 \ prom/redis-exporter# 配置 Prometheus 抓取数据scrape_configs: - job_name: 'redis' static_configs: - targets: ['localhost:9121']Grafana + Prometheus:# 使用 Grafana 展示 Redis 监控数据# 导入 Redis Dashboardhttps://grafana.com/grafana/dashboards/11835-redis-dashboard/Redis Insight:# Redis 官方可视化工具# 下载地址https://redis.com/redis-enterprise/redis-insight/3. Redis 运维操作备份与恢复RDB 备份:# 手动触发 RDB 备份SAVE# 或BGSAVE# 备份文件位置/var/lib/redis/dump.rdb# 恢复 RDB 备份# 停止 Redisredis-cli shutdown# 复制备份文件cp dump.rdb /var/lib/redis/dump.rdb# 启动 Redisredis-server /etc/redis/redis.confAOF 备份:# 备份 AOF 文件cp /var/lib/redis/appendonly.aof /backup/appendonly.aof# 恢复 AOF 备份# 停止 Redisredis-cli shutdown# 复制备份文件cp /backup/appendonly.aof /var/lib/redis/appendonly.aof# 启动 Redisredis-server /etc/redis/redis.conf数据迁移主从迁移:# 在从节点配置主节点redis-cli slaveof <master-ip> <master-port># 等待同步完成redis-cli info replication# 取消主从关系redis-cli slaveof no one使用 MIGRATE 命令:# 迁移单个 keyMIGRATE <target-host> <target-port> <key> <target-database> <timeout># 迁移多个 keyMIGRATE <target-host> <target-port> "" <target-database> <timeout> KEYS key1 key2 key3使用 Redis-Shake:# 安装 Redis-Shakewget https://github.com/alibaba/RedisShake/releases/download/v2.0.3/redis-shake-v2.0.3.tar.gztar -xzf redis-shake-v2.0.3.tar.gz# 配置文件cat > shake.conf << EOFsource.type: standalonesource.address: source.redis.com:6379source.password: source_passwordtarget.type: standalonetarget.address: target.redis.com:6379target.password: target_passwordEOF# 启动迁移./redis-shake.linux -type=sync -conf=shake.conf集群扩容添加节点:# 添加新节点redis-cli --cluster add-node <new-node-ip>:<new-node-port> <existing-node-ip>:<existing-node-port># 分配哈希槽redis-cli --cluster reshard <existing-node-ip>:<existing-node-port> \ --cluster-from <node-id> \ --cluster-to <new-node-id> \ --cluster-slots 1000删除节点:# 迁移哈希槽redis-cli --cluster reshard <existing-node-ip>:<existing-node-port> \ --cluster-from <node-id> \ --cluster-to <other-node-id> \ --cluster-slots 1000# 删除节点redis-cli --cluster del-node <existing-node-ip>:<existing-node-port> <node-id>4. Redis 故障排查内存不足问题现象:Redis 报错:OOM command not allowed when used memory > 'maxmemory'Redis 性能下降排查步骤:# 查看内存使用情况INFO memory# 查看大 Keyredis-cli --bigkeys# 查看内存碎片率INFO memory | grep mem_fragmentation_ratio解决方案:# 调整最大内存限制CONFIG SET maxmemory 2gb# 开启内存淘汰策略CONFIG SET maxmemory-policy allkeys-lru# 清理内存碎片MEMORY PURGE连接数过多问题现象:Redis 报错:max number of clients reached客户端连接失败排查步骤:# 查看连接数INFO clients# 查看最大连接数CONFIG GET maxclients解决方案:# 调整最大连接数CONFIG SET maxclients 10000# 关闭空闲连接CONFIG SET timeout 300慢查询问题现象:Redis 响应慢慢查询日志增多排查步骤:# 查看慢查询SLOWLOG GET 10# 查看慢查询配置CONFIG GET slowlog-log-slower-thanCONFIG GET slowlog-max-len解决方案:# 调整慢查询阈值CONFIG SET slowlog-log-slower-than 10000# 优化慢查询命令# 避免 KEYS 命令,使用 SCAN# 避免 O(n) 复杂度的命令# 使用 Pipeline 减少网络往返主从同步延迟问题现象:从节点数据滞后读取到旧数据排查步骤:# 查看主从同步状态INFO replication# 查看同步延迟master_repl_offset:1000000slave_repl_offset:999000解决方案:# 调整复制缓冲区大小CONFIG SET repl-backlog-size 10mb# 调整复制超时时间CONFIG SET repl-timeout 60# 优化网络延迟# 使用更快的网络# 减少主从节点之间的距离5. Redis 性能优化配置优化内存优化:# 设置最大内存maxmemory 2gb# 设置内存淘汰策略maxmemory-policy allkeys-lru# 关闭 THPecho never > /sys/kernel/mm/transparent_hugepage/enabled持久化优化:# RDB 配置save 900 1save 300 10save 60 10000# AOF 配置appendonly yesappendfsync everysecauto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb网络优化:# 设置 TCP backlogtcp-backlog 511# 设置 TCP keepalivetcp-keepalive 300# 设置超时时间timeout 300运维优化定期备份:# 定期备份 RDB 文件0 2 * * * cp /var/lib/redis/dump.rdb /backup/dump_$(date +\%Y\%m\%d).rdb# 定期备份 AOF 文件0 3 * * * cp /var/lib/redis/appendonly.aof /backup/appendonly_$(date +\%Y\%m\%d).aof监控告警:# 配置监控告警# 内存使用率超过 80% 告警# QPS 下降超过 50% 告警# 延迟超过 100ms 告警# 连接数超过 80% 告警总结Redis 的监控和运维是保证 Redis 稳定运行的重要环节。需要从基础指标、性能指标、监控工具、运维操作、故障排查、性能优化等多个维度进行监控和管理。在实际应用中,需要建立完善的监控体系,及时发现和解决问题,确保 Redis 的稳定性和性能。
阅读 0·2月19日 19:37