当先锋百科网

首页 1 2 3 4 5 6 7

Redis

(1)       数据模型:Redis是KeyValue型数据库,除了常规的数值或字符串,还支持:Lists列表、Sets集合、Sorted sets有序集合、Hashes哈希表。

(2)       持久化:使用快照,将内存中的数据不断写入磁盘;或使用类似MySQL的日志方式,记录每次更新的日志。

Memcached

       高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载,减少读取数据库的次数。它使用libevent库(封装Linux的poll、BSD类操作系统的kqueue等事件),由于使用全内存模式,当重启Memcached或重启操作系统会导致数据消失;当内存容量达到指定值基于LRU算法自动删除不使用的缓存。Memcached不考虑数据的持久化问题。

MongoDB

       基于分布式文件存储的数据库,旨在为Web应用提供可扩展的高性能数据存储解决方案。它主要面向集合存储,支持动态查询,支持完全索引,支持复制和故障恢复,使用高效的二进制数据存储,自动处理碎片,支持云计算层次的扩展性。

区别:Redis中并不是所有数据都存储在内存中,这是和Memcached最大的区别!Memcached数据结构单一,Redis较丰富,MongoDB最类似关系型数据库,支持的查询语言非常丰富。Redis适合数据量较小的运算;Memcached用于动态系统中减少数据库负载,适合读多写少,数据量较大时常采用sharding技术;MongoDB主要解决海量数据的访问效率问题!

Memcached:通过缓存数据库查询结果,减少数据库访问次数,提高动态Web应用的速度,提高可扩展性。(Memcached运行图)

Slab Allocation分配机制:将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分组(chunk的集合)→导致内存浪费、碎片化



惰性过期技术:memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期→memcached不会在过期监视上耗费CPU时间

基于键值对的hashmap结构+分布式+全内存+缓存+服务器+LRU替换策略(页面置换算法)+RDBMS(首次请求从RDBMS中获取数据,RDBMS中的数据存放在Memcached,之后的请求先从Memcached中匹配。若匹配成功则返回查询结果;否则继续从RDBMS中进行查询)

内部hash机制:memcached采用拉链法解决冲突

Redis:一个KeyValue存储系统,与Memcached类似,但是它会周期性地把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并在此基础上实现Master-Slave同步!


Slave在连接Master时,Master会进行内存快照,然后将整个快照文件发送给Slave!该模式下,Master提供数据读写服务,而Slave只提供读服务,客户端通过一致性hash算法选择要访问的Slave缓存服务节点。

Sharding技术解析(分片技术解析)

       Sharding是水平扩展(Scale out,亦或横向扩展、向外扩展)的解决方案,主要目的是为突破单节点数据库服务器的I/O能力限制,解决数据库扩展性问题!

Sharding与数据库分区Partition的区别:数据库分区基本上是数据对象基本的处理,比如表和索引的分区,每个子数据集上能够有不同的物理存储属性,还是单个数据库范围内的操作;而Sharding是能够跨数据库,甚至跨越物理机器的!


Sharding的基本思想即把一个数据块切分成多个部分放到不同的数据库server上,从而缓解单一数据库的性能问题。例如:对于海量数据的数据库,若因为表多而数据多,此时适合使用垂直切分,把关系紧密的表切分出来放在一个server上;若表并不多,但每张表的数据非常多,此时适合水平切分,将表的数据按某种规则(比如按ID散列)切分到多个数据库server上。

       垂直切分的最大特点是规则简单,实施方便,尤其适合各业务之间的耦合度非常低,相互影响很小业务逻辑非常清晰的系统!此时可将不同业务模块所使用的表分拆到不同的数据库中,这就是所谓的“share nothing”。


水平切分是将同一个表中的不同数据拆分到不同的数据库中,拆分规则较复杂,后期的数据维护也较困难。


多数系统会将垂直和水平切分联合,先对系统做垂直切分再针对每一小搓表的情况选择性地做水平切分,从而将整个数据库切分成一个分布式矩阵:垂直切分(表名)+水平切分(数据)

切分策略:

切分一般是按先垂直切分再水平切分的步骤进行:垂直切分的结果正好为水平切分做好了铺垫。垂直切分的思路就是分析表间的聚合关系,把关系紧密的表放在一起。多数情况下可能是同一个模块,或者是同一“聚集”。在垂直切分出的表聚集内,找出“根元素”(这里的“根元素”就是领域驱动设计里的“聚合根”),按“根元素”进行水平切分,也就是从“根元素”开始,把所有和它直接与间接关联的数据放入一个shard里。这样出现跨shard关联的可能性就非常的小。应用程序就不必打断既有的表间关联。比如:对于社交网站,几乎所有数据最终都会关联到某个用户上,基于用户进行切分就是最好的选择。再比如论坛系统,用户和论坛两个模块应该在垂直切分时被分在了两个shard里,对于论坛模块来说,Forum显然是聚合根,因此按Forum进行水平切分,把Forum里所有的帖子和回帖都随Forum放在一个shard里是很自然的。

对于共享数据,如果是只读的字典表,每个shard里维护一份应该是一个不错的选择,这样不必打断关联关系。如果是一般数据间的跨节点的关联,就必须打断。

需要特别说明的是:当同时进行垂直和水平切分时,切分策略会发生一些微妙的变化。比如:在只考虑垂直切分的时候,被划分到一起的表之间可以保持任意的关联关系,因此你可以按“功能模块”划分表格,但是一旦引入水平切分之后,表间关联关系就会受到很大的制约,通常只能允许一个主表(以该表ID进行散列的表)和其多个次表之间保留关联关系,也就是说:当同时进行垂直和水平切分时,在垂直方向上的切分将不再以“功能模块”进行划分,而是需要更加细粒度的垂直切分,而这个粒度与领域驱动设计中的“聚合”概念不谋而合,甚至可以说是完全一致,每个shard的主表正是一个聚合中的聚合根!这样切分下来你会发现数据库被切分地过于分散了(shard的数量会比较多,但是shard里的表却不多),为了避免管理过多的数据源,充分利用每一个数据库服务器的资源,可以考虑将业务上相近,并且具有相近数据增长速率(主表数据量在同一数量级上)的两个或多个shard放到同一个数据源里,每个shard依然是独立的,它们有各自的主表,并使用各自主表ID进行散列,不同的只是它们的散列取模(即节点数量)必需是一致的。