存储需要考虑以下两个场景下的性能,并发量大,查询的时候数据量大导致查询慢。并发大的解决思路是复制;查询慢的解决思路是数据分片,而数据分片了还需要考虑数据可靠性。
- redis redis是内存数据库,数据保存在内存中,单机能抗很大的并发。redis中的数据分片是整个集群划分成固定的16 * 1024=16384个槽,这些槽分布在集群的各个节点上,每个节点也都会存储一份元数据例如某个槽在某个节点上等。客户端请求获取某个key,节点会先查看槽是否在自己的节点上,如果是就读取并返回,如果不是就把槽在的节点信息告诉客户端让其自己再去请求。元数据在每一个节点上都会存在,大多数情况下是不变的,但是当更新的时候,使用的是gossip协议。
为了保证数据分片的可靠性,防止某一台机器宕机后该机器存储的槽们丢失,redis设计了slave节点复制master节点上的数据。旧版本中为全复制策略(SYNC),即slave设置成某个master的从节点,master上调用BGSAVE命令生成RDB文件,同时将此过程中的命令存储在缓冲区,并将RDB发送到slave,将缓冲区的命令也发送到slave,从而达到复制。但是这种方法的问题是,slave与master节点都正常的情况下,下一次的复制请求只需要复制增量部分即可,但是却把全量都复制了,生成RDB文件需要消耗机器的CPU和存储,传输文件也耗费网络资源,因此全量复制会造成很大的系统资源浪费。因此,新版本的复制采用PSYNC,slave向master发送psync命令的时候,会带上一次同步的master的server id,master节点在校验身份后,如果server id是自己,那么执行增量复制,slave会将自己保存的offset告诉master,master与自己保存的复制积压缓冲区中的offset比较,如果slave的offset存在,则将剩下的部分发送给slave,如果不存在,则执行全量复制。如果server id不是自己,也执行全量复制。当master宕机,其他的master节点会从slave中选举出新的master。
- kafka kafka是分布式消息系统,不仅用作消息队列,其也可用作海量数据的存储系统,在流式计算领域中有较大作用,但是适用于不需要永久存储的流失点击数据,例如某几个月内的日志,埋点等。
首先是高并发,支持每秒上百万的写入,kafka采用write append log顺序写与零拷贝技术保证高并发。
同样,kafka采用partition将topic中的数据分片,同时用replication机制保证高可用,细节可以见之前写的文章。但是kafka不是无限的可以横向扩容的,当单台broker上的partition已满,此时新增一台broker,如何进行路由也是要考虑的。
-
mysql mysql实际上是单机存储系统,设计并不是可水平扩展的,因此放弃了数据分片。mysql的主从复制保证了高可用以及读多写少场景下的读写分离。具体可见之前写的文章。
-
总结 不同场景适用不同技术,也有不同的取舍,对于分布式存储来说,关注的更多的是海量数据的存储,如何能横向扩展,存储更多的数据就是思考的重点,数据分片是基本思想,那么就需要设计数据分片算法,如何路由到节点,一般的做法有哈希法或者查表法。这类数据库能存储海量的数据,但是对于数据的可靠性与数据一致性需要自己考虑。而mysql这类的单机存储来说,关注更多的在数据的事务与可靠性,因此当数据一直增长的时候,可能就要考虑分库分表,而分库分表又是最后的下下策。因此,使用不同的存储技术需要根据这些存储的特点来选择。