DevilKing's blog

冷灯看剑,剑上几分功名?炉香无需计苍生,纵一穿烟逝,万丈云埋,孤阳还照古陵

0%

Cache Strategy

高性能服务架构思路

Agenda:

  • 缓存策略的概念和实例

  • 缓存策略的难点:不同特点的缓存数据的清理机制

  • 分布策略的概念和实例

  • 分布策略的难点:共享数据安全性与代码复杂度的平衡

缓存

缓存策略

性能问题表现:

  • 并发数不足,也就是同时请求的客户过多,服务器的内存耗尽

  • 处理延迟过长,CPU占用满100%

抽象资源:

  • 时间资源:CPU和磁盘读写

  • 空间资源:内存和网卡带宽

缓存策略,其实是用内存的空间,换取磁盘的读写空间

网络游戏的服务端程序,所有的写操作都先去写内存中的结构,然后定期再由服务器主动写回到数据库中,这样可以把多次的写数据库操作变成一次写操作,也能节省很多写数据库的消耗。这种做法也是用空间换时间的策略。

缓存的本质,除了让“已经处理过的数据,不需要重复处理”以外,还有“以快速的数据存储读写,代替较慢速的存储读写”的策略

对缓存数据的编程处理,采用序列化的方式,也可以采用深拷贝的方式,

一般来说,缓存的数据越解决使用时的内存结构,其转换速度就越快,在这点上,Protocol Buffer采用TLV编码,就比不上直接memcpy的一个C结构体,但是比编码成纯文本的XML或者JSON要来的更快。因为编解码的过程往往要进行复杂的查表映射,列表结构等操作

缓存难点-缓存清理

  • 使用命令清理相关内存

  • 使用字段逻辑判断,根据一些特征数据,判断是否有不一致的地方,

静态的缓存

以及运行时变化的缓存数据,

  • 按照重要级来分割

  • 按照使用部分分割

分布

分布策略

划分多个进程的架构,一般会有两种策略:一种是按功能来划分,比如负责网络处理的一个进程,负责数据库处理的一个进程,负责计算某个业务逻辑的一个进程。另外一种策略是每个进程都是同样的功能,只是分担不同的运算任务而已

在调用多进程服务的策略上,我们也会有一定的策略选择,其中最著名的策略有三个:一个是动态负载均衡策略;一个是读写分离策略;一个是一致性哈希策略。

多进程技术

多线程技术,内存使用不可控,对于同一数据的使用,需要考虑复杂的”锁”问题

select/epoll, 非阻塞操作,

多线程和异步的例子,最著名就是Web服务器领域的Apache和Nginx的模型。Apache是多进程/多线程模型的,它会在启动的时候启动一批进程,作为进程池,当用户请求到来的时候,从进程池中分配处理进程给具体的用户请求,这样可以节省多进程/线程的创建和销毁开销,但是如果同时有大量的请求过来,还是需要消耗比较高的进程/线程切换。而Nginx则是采用epoll技术,这种非阻塞的做法,可以让一个进程同时处理大量的并发请求,而无需反复切换。对于大量的用户访问场景下,apache会存在大量的进程,而nginx则可以仅用有限的进程(比如按CPU核心数来启动),这样就会比apache节省了不少“进程切换”的消耗,所以其并发性能会更好。

分布式编程复杂度

多线程部分

  • 基于回调

  • 基于协程

lamda表达式,闭包,promise手段

  • 动态多进程fork——同质的并行任务

  • 多线程——能明确划的逻辑复杂的并行任务

  • 异步并发回调——对性能要求高,但中间会被阻塞的处理较少的并行任务

  • 协程——以同步的写法编写并发的任务,但是不合适发起复杂的动态并行操作。

  • 函数式编程——以数据流为模型的并行处理任务

函数式编程的语言,比如LISP或者Erlang,其核心数据结果是链表——一种可以表示任何数据结构的结构。我们可以把所有的状态,都放到链表这个数据列车中,然后让一个个函数去处理这串数据,这样同样也可以传递程序的状态。这是一种用栈来代替堆的编程思路,在多线程并发的环境下,非常的有价值。

分布式数据通信

消息队列

分布式缓存策略

利用哈希表来解决缓存的数据同步

我们的“表”要有能把数据在A、B两个进程间同步的能力。因此我们一般会用三种策略:租约清理、租约转发、修改广播

  • 租约清理

  • 租约转发

这样无需清理,

  • 修改广播

dns的缓存策略