Redis 总结

本文详细介绍了Redis的核心数据结构如string、list等,以及在数据缓存、计数器等场景的应用。还深入讨论了持久化策略,包括RDB、AOF及混合模式的优缺点。此外,分析了Redis的集群架构,包括主从、哨兵和Cluster模式,并提到了常见的缓存问题和分布式锁的实现。最后,强调了使用Redis时的一些注意事项,如避免大value和过多元素,以及利用Redission和Lua脚本增强功能。

核心数据结构

  • string
  • list
  • set
  • sorted set
  • hash

应用场景

  • 数据缓存
  • 计数器
  • 分布式锁
  • 分布式session
  • 全局序号生成器
  • 购物车
hset cart:userid goodsid nums   #加入商品到购物车
hincrby cart:userid goodsid  #调整商品数量
hlen cart:userid  #获取商品总数量
hdel cart:userid goodsid #删除购物车中的商品
hgetall cart:userid #获取所有商品
  • 抽奖
sadd key userid #参与抽奖
smemebers key #查看所有参与者
srandmember key count/spop key count #抽奖
  • 排行榜
zincrby hotnews20191112  1 news01  #一次点击,score + 1
zrevrange hotnews20191112 0 10 withscore # 倒序取点击量在前10的news

#合并多天的数据
zunionstore hotnews_20191112-20191113 hotnews20191112 hotnews20191113
#获取合并后的前10名
zrevrange hotnews_20191112-20191113 0 10 withscores 

-分布式锁

#加锁
set lockkey 0 ex 5 nx 
#解锁
del lockkey 

持久化策略

redis提供了三种持久化策略,分别是:RDB、AOF和混合持久化模式。

RDB是通过数据快照的方式进行数据持久化的,可以通过修改配置文件的save参数来指定持久化策略:

# 900秒内有一次修改
save 900 1
#300秒内有10次修改
save 300 10
#60秒内有1000次修改
save 60 1000

RDB的持久化方式产生的rdb文件是二进制格式,体积比较小,利用rdb文件进行数据恢复的时候速度会比较快,但是,由于是间隔性执行,所以会造成数据丢失,使用的时候还要看业务上能否接收。

AOF持久化方式是通过记录写命令来实现的,通过以下的配置来开启AOF持久化策略:

appendonly yes    #开启aof持久化
appendsync always  #实时记录没一个写命令
appendsync everysec  #每秒钟记录一次(最常用)
appendsync no  #不主动记录,交给操作系统?
auto-aof-written-min-size 64m   #aof文件重写策略-按照aof文件大小来触发重写
auto-aof-written-percentage 100  #按照文件的增长率来触发aof文件重写

AOF这种持久化策略的好处是不会造成数据丢失,但是aof文件一般会比rdb文件大很多,所有,redis也提供了aof文件重写功能,可以对aof文件中可以进行合并的命令进行合并。但是使用aof文件进行数据恢复的速度要比rdb文件要慢。

混合持久化模式是综合了RDB和AOF各自优势,当触发aof重写时,会将内存中的数据以rdb的格式写入aof文件,在下次aof重写之前,所有的写操作都会以命令行的方式追加到aof文件中。

集群架构

redis的常见集群架构主要有三种,分别是:主从模式、哨兵模式和Cluster模式,这三种架构的结构图大概如下图所示:
在这里插入图片描述
其中,master-slave模式类似于mysql的主备模式,可以用来做数据备份和读写分离,但是,由于redis集群通常要求HA,所以这种主从模式很少引用,主从数据复制的过程如下:

  • slave加入到集群,向master发起数据同步请求;
  • master节点fork主子线程对当前内存数据做rdb快照,并缓存期间接收到的写请求命令;
  • master将rdb快照文件发送给slave,slave完成数据回放后,master在将增量数据发给slave;
  • 后续slave进入增量同步;

哨兵模式是在主从模式的基础上改进而来的,在主从模式下引入哨兵,来监控主从集群的状态,客户端通过哨兵集群来获取master节点的链接信息,然后再去与master节点进行数据交互,如果master节点宕机,那么,哨兵会通过修改配置文件+重启的方式来切换集群的master节点,修改后的master节点能够通过哨兵被客户端感知到,但是在哨兵模式下,将slave拉到master的过程比较慢,会造成redis集群一段时间的不可用,如果业务流量比较大的话,缓存集群不可用是很可怕的,要根据业务特点谨慎选择。

集群模式是目前比较推荐的redis高可用架构,这种架构内部又一个个小的master-slave组成,节点互为主备,同时,每个节点会被redis划分成若干个槽位,然后采用一致性hash的方式来存取数据,这又两个好处,一是redis集群可以水平扩展,不像哨兵模式下服务能力受master节点的限制,二是可以最大程度上减小由于节点宕机造成的影响,因为cluster内部的一个master-slave只存储了一部分数据,即使某一个master宕机并进程master-slave切换的过程中,也不会对所有key产生影响。redis默认将所有master划分成16384个槽位,但这个数量可以通过配置进行调整。

常见问题

  • 缓存穿透
缓存穿透指的是请求那些在数据库中不存在、在缓存中也不存在的数据,解决这个问题的方式通常有两种:
- 对请求参数进行校验,过滤一部分不合法的数据
- 对null值做缓存,并设置一个过期时间,防止后续有有数据了,比如请求一个id=50的商品信息,
  此时没有,但后续管理员增加了一个id=50的商品。
  • 缓存击穿
缓存击穿指的是某一个热点key在某个时间失效了,导致大量请求透过缓存打到数据库上,这种问题可以从缓存和业务代码
两个方面来解决
- 将热点key设置为永不过期
- 通过加锁的方式将并发请求这个key的线程进行同步处理,确保只有一个线程会去查数据库并对缓存进行重建
  • 缓存雪崩
缓存雪崩指的是大片的缓存数据在同一时刻失效了,导致大量请求打到数据库,把数据库压块,最终造成整个系统不可用
- 可以随机设置key的过期时间,避免同时失效(个人觉得这个解决方案比较好)
- 可以根据数据的特点进行分区存储,例如按照地域或类别等
- 设置永久过期

Redis分布式锁

参考:https://blog.youkuaiyun.com/kongtiao5/article/details/102659153

  • 加锁
public boolean lock(String value)
    {
    	//这里的setnx和expire可以合并成一条指令
        if (jedisTemplate.setnx(LOCK_KEY, value))
        {
            jedisTemplate.expire(LOCK_KEY,5,TimeUnit.SECONDS);
            return true;
        }
        
        return false;
}
  • 解锁
public boolean unlock(String value)
    {         
        String script =
                "if redis.call('get',KEYS[1]) == ARGV[1] then" +
                        "   return redis.call('del',KEYS[1]) " +
                        "else" +
                        "   return 0 " +
                        "end";
        try 
        {
            Object result = jedis.eval(script, Collections.singletonList(LOCK_KEY), 
                                    Collections.singletonList(value));
            if("1".equals(result.toString()))
            {
                return true;
            }
            return false;
        }
        catch(Exception e)
        {
            return false;
        }
        finally 
        {
            jedis.close();
        } 
    }

一些使用上的注意事项

  • 保证key的可读性,做到见名思意;
  • 保证key的简介,避免过长,会占用redis内存;
  • key值不要包含特殊字符;
  • 避免value体积过大,例如list中元素太多货哈希中field的太多;
  • 避免调用耗时操作,例如keys,或在大value上调用类似hgetall 这种操作;
  • string类型的value建议不要超过10kb;
  • list中的元素尽量不要超过5000个;

由于redis是单线程模型,大value或耗时的操作会导致后续操作被阻塞。

其他

Redision
Lua脚本

### Redis 实训总结与经验分享 Redis 是一种高性能的内存数据库,广泛应用于缓存、消息队列、分布式锁等场景。以下是对 Redis 实训中关键点的总结和经验分享。 #### 1. Redis 的安全问题 在实际项目中,Redis 的安全性是一个不可忽视的问题。如果配置不当,可能会导致数据泄露、拒绝服务攻击或数据篡改等问题[^1]。因此,在使用 Redis 时需要特别注意以下几点: - **访问控制**:通过设置密码(`requirepass` 配置项)限制对 Redis 服务器的访问。 - **限流防护**:启用 Redis 的限流机制,防止恶意请求导致的服务中断。 - **数据加密**:对于敏感数据,可以采用数据加密技术确保其完整性。 #### 2. Redis 的性能优化 Redis 的高性能主要得益于其基于内存的操作模式以及简单的键值存储结构。在实际应用中,可以通过以下方式进一步提升 Redis 的性能[^2]: - **缓存策略**:将热点数据存储到 Redis 中,减少对后端数据库(如 MySQL)的直接访问压力。例如,让 80% 以上的查询走缓存,20% 以下的查询走数据库。 - **持久化配置**:根据业务需求选择合适的持久化方式(RDB 或 AOF)。RDB 提供快照式持久化,适合数据恢复;AOF 提供更高的数据安全性,但可能会影响性能。 - **分片与集群**:当单机 Redis 的容量或性能无法满足需求时,可以考虑使用 Redis 分片或 Redis 集群来扩展存储能力和并发处理能力。 #### 3. Redis 的备份与恢复 为了确保数据的安全性和可靠性,定期进行 Redis 数据备份是非常重要的[^1]。以下是备份与恢复的最佳实践: - **自动备份**:通过配置定时任务(如 `cron`)定期生成 RDB 文件。 - **增量备份**:结合 AOF 日志实现增量备份,减少全量备份带来的性能开销。 - **灾难恢复**:在主从架构中,确保从节点的数据同步正常,以便在主节点故障时快速切换。 #### 4. 权限管理与可视化范围 在某些项目中,Redis 的数据可能需要根据不同角色的权限进行访问控制。例如,在一个微信小程序开发项目中,不同用户角色可以查看不同的数据范围[^3]。类似地,可以在 Redis 中实现类似的权限管理逻辑: - **命名空间隔离**:为不同角色的数据设置独立的命名空间前缀,避免数据冲突。 - **ACL 控制**:Redis 6.0 及以上版本支持 ACL(Access Control List),可以为不同用户分配特定的命令权限和键空间访问权限。 #### 5. Maven 项目中的 Redis 集成 在基于 Maven 的 Spring Boot 项目中集成 Redis 时,可以通过以下步骤完成配置[^4]: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 同时,需要在 `application.yml` 或 `application.properties` 文件中配置 Redis 连接信息: ```yaml spring: redis: host: localhost port: 6379 password: your_password timeout: 5000ms lettuce: pool: max-active: 8 max-idle: 8 min-idle: 0 ``` #### 6. 常见问题与解决方法 在 Redis 实训过程中,可能会遇到以下常见问题: - **内存不足**:可以通过调整 `maxmemory` 和 `maxmemory-policy` 参数来解决。 - **网络延迟**:检查 Redis 服务器与客户端之间的网络连接是否正常。 - **数据丢失**:确保持久化配置正确,并定期测试数据恢复流程。 --- ### 示例代码:Redis 缓存操作 以下是一个简单的 Redis 缓存操作示例: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; @Service public class CacheService { @Autowired private StringRedisTemplate redisTemplate; public void setCache(String key, String value) { redisTemplate.opsForValue().set(key, value); } public String getCache(String key) { return redisTemplate.opsForValue().get(key); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值