软件设计之缓存使用

本文主要讨论分布式环境下,缓存如何在软件设计作用、原理、实现方式及注意问题。

缓存的作用

  • 减小原始数据访问压力
  • 提高资源利用率

缓存的原理

局部性原理

缓存的实现方式

查询算法

  • 散列算法,Hash 、 MD5 等
  • B数、二叉树、有序二分查找等

存储

  • 只将访问量最高的部分数据放入缓存
  • 将数据放到比原始IO速率更高的存储介质中

缓存资源回收

  • RUL 算法
  • 定时清理
  • 设置资源有效时间

缓存的存储介质

  • CPU 寄存器
  • 内存
  • 本地文件
  • 分布式系统(Memcache 、 Redis)
  • 数据库缓存数据表

缓存设计注意的问题

缓存的一致性,Cache coherence

  • 避免数据脏读
  • 多级缓存的一致性协议

系统的鲁棒性

  • 在缓存系统停止服务,但仍能保证整体系统正常运行。因此在使用缓存之前,检查提供缓存系统的有效性。

单机缓存

  • 单机缓存是指,将系统资源存放于每个单台服务器上,而不是集中存储与分布式缓存系统中。 缺陷是,如果原数据发生更改,为保证一致性,则必须调用每一台服务器清理或更新缓存。

后台自动任务设计和编码总结

资源预估

  • 预估数据量、算法的时间、空间复杂度
  • 依据预估的结果分配合理的资源(内存,CPU),避免资源不够用。

避免数据脏读

自动脚本处理大量数据速度快,尤其有写操作的任务,数据一致性在分布式环境下往往难以保证。这种情况下应该避免数据脏读,比如数据库会有主从复制同步延迟的现象,这时应该强制连接数据库主库。

幂等性

有写操作的脚本,需要考虑脚本执行的幂等性,即在输入相同参数多次运行与运行一次的结果相同。 保证幂等性具体应该考虑一下几点:

  • 逻辑上,检查待处理数据的状态,已经处理过的数据不再处理。
  • 禁止并发运行,不允许运行多个进程同步运行同一任务。如何保证?信号量、Memcache加锁。

参数控制

  • 在设计阶段,应该通过参数控制,限制脚本的操作范围。参数可以是时间,自动脚本周期运行,每次运行,只处理相应周期范围内的数据。
  • 注意默认参数的参数值。

读并发

自动脚本处理速度快,在和其他系统进行交互时,会对其他系统产生大量而密集的请求。

  • 要考虑其他系统的抗并发能力
  • 合理限制单位时间对其他系统的访问次数
  • 尽量将数据集中做批量请求,减少请求次数
  • 在本地做缓存,消除重复的请求。

容错 和 错误处理

  • 容错 自动脚本往往批量处理大量数据,循环处理每条数据。在单次循环中的错误或异常,应该全部捕获,并记下日志,让脚本继续运行。
  • 日志 记录重要操作,包括info、warning、error等级所有日志,形式可以是文本记录或数据库,便于追查和报警。

备灾和数据修复

  • 在不可抗拒因素(断电,其他原因宕机)等引起任务中途突然停止,应该依据日志定位、和追查处理到哪一阶段。修复错误数据。
  • 在保证脚本幂等性的前提下,重复执行脚本可自动处理未完成的工作。

优化

随着业务增长,任务处理数据量越来越大,可能会出现,任务超时,内存不够用的情况,应该及时对自动任务进行优化,优化的方案可以从算法、业务架构上考虑。