基于redis的缓存系统设计

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cheungmine/article/details/87171775

1. 缓存的目的

使用缓存系统的目的是为高并发的访问提供高质量的、实时的反馈。一般的缓存系统,都是按照 key-value 去查询缓存层(如 redis),如果 key 不存在,就应该去后端持久层DB(如 HBase,MySQL)中查找 。这个时候,如果请求的并发量很大,就会对后端的DB系统造成很大的压力。这就叫做缓存穿透。

造成的原因

1.业务自身代码或数据出现问题
2.一些恶意攻击、爬虫造成大量空的命中,此时会对数据库造成很大压力
3.缓存崩溃

解决方法

如果一个查询返回的数据为空,不管是数据不存在还是系统故障,我们仍然把这个结果进行缓存,但是设置一个较短的过期时间。

2. 缓存系统设计

这里假定使用 redis 作为缓存层,hbase 作为 DB 层,kafka 作为队列层。每层的软件正好符合其特性。以下分写入和读取2个客户端的操作加以说明。由于业务的不同,对数据持久化的强度要求也不同。比如充值,购买等行为,要求强持久性(2.2),对速度和性能的要求就相应降低。而对话,聊天,游戏互动等行为,要求强实时性(2.1),对速度要求极高,相应地对持久化可靠性要求就可以低一些。

(更安全的设计是保证数据的强一致性,这是通过关系数据库的分布式事务来实现的:即在某个帐号的一笔事务期间,同时只能出现一个操作。不在本讨论范围。)

2.1 强实时性系统的设计

强实时性侧重于数据读写的高并发和高速,允许少量的脏写和脏读。比如操作某个用户的游戏道具。分为写入和读取2个场景讨论。

写入 key

  • 服务进程W写入key-value 到 redis,同时将 key 记录到 kafka 的某个 topic(A1)。

另外的进程P订阅 kafka 的 topic(A1) 消息,得到 key,然后从 redis 里面取出 key-value,写入 hbase。可以设置一个小的时间段,合并相同的 key,批处理写入 hbase。

由于hbase中的k-v值与redis的k-v值存在不一致的可能,此时成为脏写,即允许持久层中的数据依极小的概率与缓存层不一致。

读取 key

  • 服务进程读 redis 某个 key-value,如果存在 key,直接返回其 value 给调用者。
  • 服务进程读 redis 某个 key-value,如果不存在 key,将 key 记录到 kafka 的某个 topic(A2)。可以返回null给调用者或者直接到hbase中读取(缓存穿透,一般当key不存在时,需要穿透一次)。

另外的进程Q订阅 kafka 的 topic(A2) 消息,得到 key,然后到 hbase 里取 key-value,将其写入 redis。 (如果 hbase中不存在这样的key,也要写入redis,并设置一个较短的过期时间,如 5 分钟。)

强实时性的设计存在的问题

如果同时写入和读取某个 key,由于进程Q也包含了写入redis操作,会造成写入不一致的情况(多个进程同时写同一个 key 到 redis 中)。需要对W和Q 的 key 写入操作设置事务隔离,而 redis 支持基于 key 的事务操作(watch->multi->…->exec/discard)。

2.2 强持久性系统的设计

强持久性侧重于数据落地稳定可靠,允许少量的误读。比如操作某个用户的积分。依旧分为写入和读取2个场景讨论。

写入 key

  • 服务进程更改key-value 到后端hbase存储中。同时将 key 记录到 kafka 的某个 topic(B1)。

另外的进程X订阅 kafka 的 topic(B1) 消息,得到 key,然后从 hbase 里面取出 key-value,写入 redis。

读取 key

  • 服务进程读 redis 某个 key-value,如果存在 key,直接返回其 value 给调用者。此时读到的 value 也许和 hbase中存储的不一致,称为脏读
  • 服务进程读 redis 某个 key-value,如果不存在 key,将 key 记录到 kafka 的某个 topic(B2)。可以返回null给调用者或者直接到hbase中读取(缓存穿透,一般当key不存在时,需要穿透一次)。

另外的进程Y订阅 kafka 的 topic(B2) 消息,得到 key,然后从 hbase 里面取出 key-value,写入 redis。

强持久性设计存在的问题
强持久性要求永久保存的数据一定是准确无误的。尽管可以读取错误,但是数据本身一定是正确的。写入的效率依赖后端的性能。

3. C语言参考

下面列出了用 C/C++ 语言调用kafka、redis、hbase的开源库。

librdkafka
hiredis
libhbase2

猜你喜欢

转载自blog.csdn.net/cheungmine/article/details/87171775