Redis 数据安全

1. 前言

       这里所说的数据安全并不是像Java语言中,多个线程修改一个变量如i++,造成结果错误。我们知道Redis是单线程的,即使有在多的客户端进行i++操作,结果也总是符合预期。而这里的数据安全更多的是指缓存数据不符合我们的预期。

2. 缓存与数据库双写时的数据一致性

       对于缓存和数据库的操作是两个操作,并不是原子性的,所以如果没有合适的方法去保证,一定会带来数据不一致性的情况。

2.1 cache aside pattern

       最经典的缓存+数据库读写的模式,cache aside pattern

  • 读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取出数据后放入缓存,同时返回响应。
  • 更新的时候,先删除缓存,然后再更新数据库。

       为什么选择删除缓存而不是先更新缓存,或者说是更新数据库成功后,在将删除的缓存进行重新保存?

       首先说一下第一种方案的缺陷:

       如果我们先更新缓存,但是如果更新数据库失败,那么此时便造成数据库与缓存状态不一致。

       第二种方案的缺陷:

       该方案相当于我们每进行一次数据的更新,就保存一次缓存,那么这些缓存是否一定是热点数据呢?如果不是的话,其不仅浪费内存,而且缓存并不仅仅是数据库中的数据,更有可能需要经过大量的计算才能保存到缓存中。

       如我之前写的一个视频排行榜程序,需要进行全表扫描,根据视频的播放量和评论数计算热度。如果视频的播放量每播放一次,便进行一次热度计算,毫无疑问,很浪费资源。

       而选择只删除缓存,不进行缓存数据重新更新,是一种懒加载的思想,当我们需要缓存的时候再重新保存。

2.2 cache aside pattern 一定能保证数据一致性吗

       考虑如下场景,序号代表执行过程,注意并不意味着请求先到来,其先来的请求一定先于后来的请求执行完毕。

在这里插入图片描述
       可以看到,即使采用cache aside pattern,在请求A更新完数据库之后,数据库中的数据与缓存中的数据依然处于不一致的状态。

       该情况通常只会出现在只有在对一个数据在并发的进行读写的时候,才可能会出现这种问题。并且如果并发量很低的话,特别是读并发很低,每天访问量就1万次,那么很少的情况下,会出现刚才描述的那种不一致的场景。但如果每天的是上亿的流量,每秒并发读是几万,每秒只要有数据更新的请求,就可能会出现上述的数据库+缓存不一致的情况。

2.3 数据库与缓存更新与读取操作进行异步串行化

       为解决上述的问题,我们可以采用数据库与缓存更新与读取操作进行异步串行化的方案。

在这里插入图片描述
       我们在JVM针对该商品创建一个内存队列,只有前面的请求结束才可以轮到后面的请求执行,如此便可以做到缓存与数据库的一致性。

       但是如果我们对于每一个读请求,都将其加入到内存队列中,毫无疑问是比较浪费时间的。我们可以用过一个volatile变量维护当前内存队列中写请求的个数,只有写请求个数不为0时,才将其加入队列,否则直接进行读取操作即可。

       在上面我们仅仅是创建了一个内存队列,倘若我们有多个商品,只使用一个内存队列显然并发性非常有限,可以针对每一种或每一类商品创建一个内存队列,这样粒度降低,并发性便可以提供。

在这里插入图片描述

       上述方案在多服务实例部署时,有这样一种情况,即对于同一个商品的操作被路由分发的不同的实例中,因为内存队列是基于JVM的,所以依然有可能造成数据的不一致。

       解决方案:通过nginx进行路由分流时,同一个商品使其分流到一台实例中。

3. redis 的并发竞争问题该如何解决

       多客户端同时并发写一个key,可能本来应该先到的数据后到了,导致数据版本错了。或者是多客户端同时获取一个key,修改值之后再写回去,只要顺序错了,数据就错了。

在这里插入图片描述
       Redis中的数据变化可能有如下几种情况:

	v0 --> v1 --> v2 -- v3
	v0 --> v2 --> v1 -- v3
	v0 --> v3 --> v1 -- v2
	......

       如果我们想让数据按时间的先后顺序进行保存,即数据变化的方式为v0 --> v1 --> v2 -- v3,可以采用时间戳+CAS的方式。

       如果当前的时间戳大于缓存中的数据库才允许操作。

在这里插入图片描述
       如此便可以保证缓存中的数据符合我们最终的目标数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis提供了多种机制来保障数据的安全性: 1. 密码认证:通过设置密码,只有提供正确的密码才可以访问和修改Redis的数据。可以在配置文件中设置密码,或者使用命令`CONFIG SET requirepass <password>`来设置密码。 2. 网络隔离:为了保护Redis服务器不受到未经授权的远程访问,可以通过配置文件中的`bind`选项来绑定只允许特定IP地址访问Redis服务器。也可以使用防火墙来限制访问。 3. 数据持久化:Redis提供了两种方式来持久化数据,即RDB快照和AOF日志。RDB快照是将数据保存到磁盘上的一个二进制文件中,AOF日志则是将所有写操作追加到一个日志文件中。这样即使Redis服务器意外宕机,也可以通过加载快照文件或者重放AOF日志来恢复数据。 4. 数据备份:可以使用Redis的主从复制功能来实现数据的备份和高可用性。通过将一个Redis服务器配置为主服务器,其他服务器配置为从服务器,并定期将主服务器上的数据复制到从服务器上,从而实现数据的备份和故障转移。 5. 安全限制:通过配置文件中的`rename-command`选项,可以重命名或者禁用某些危险命令,从而限制对Redis服务器的非授权访问和操作。 6. 客户端访问控制:可以通过配置文件中的`requirepass`选项来设置客户端密码,并使用`ACL`命令来设置和管理客户端访问控制列表,从而限制特定IP地址或者用户的访问权限。 7. 网络加密:可以通过使用SSL/TLS协议来加密Redis客户端和服务器之间的通信,从而保护数据在传输过程中的安全性。 总的来说,通过以上的安全机制,Redis可以保障数据的安全性,避免未经授权的访问和恶意操作。但是在实际应用中,还需要根据具体情况综合考虑安全策略,并采取其他安全措施来增强数据的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值