前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据服务开发经验

数据服务开发经验

作者头像
lyb-geek
发布2019-03-07 10:28:21
9990
发布2019-03-07 10:28:21
举报
文章被收录于专栏:Linyb极客之路

有状态服务或者说数据服务,上线遇到问题很棘手,回滚无济于事;而且数据加载通常都很慢,部署时间长;最终导致不敢修改代码,谨小慎微;服务质量也是能忍就忍,不愿意深度优化。在我负责顺风车LBS以来,感受愈加强烈;区别于无状态服务,数据服务的几个方面需要格外关注。(此处假设数据服务类似redis基于内存,数据量大到需要磁盘存储,关注点会有所不同。)

  • 架构设计:多主、主从或者主备,关系到数据分片;考虑服务故障、数据一致性、读写效率等;扩容缩容要方便;
  • 数据同步:不同的集群架构,选择不同同步方式,主从同步或上游同步,RPC或者MQ;
  • 数据存储:在线部分关注数据结构和锁粒度设计;持久化需要稳定性,且能支持并发加载,服务快速重启,binlog或leveldb;
  • 数据格式:能随时增删字段,做到新旧版本兼容;尽可能满足多种类型需求;要便于数据校验;

下面挑一些关键点简述。

架构设计

多主架构

多个分区,通过hash桶、一致性哈希等方式做数据分片,将数据映射到不同的分区;每个分区多个主节点,数据全量写入,上层服务主动做负载均衡读;单机服务故障不会影响在线业务。

数据同步

由于分区存在多个角色相同的服务,都接受分区全量数据,数据一致性格外重要;多主架构,上游或者proxy保证数据一致性,如通过RPC请求:

但是RPC会有很大的坑,写请求超时时间难定义,数据部分写入不成功后消息重试容易造成雪崩。这时很容易想到通过mq解耦:

目前顺风车LBS类似这种结构,实际上维护代价也比较高。每台机器都要全量数据,不得不单独定义消费组名(集群消费不保证正常消费);机器数量增多,会有海量consumer group。

如果对数据实时性要求不高,mq同步是非常不错的选择。

主从/多主从

主节点处理写操作,同步数据给从节点,一般从节点处理读请求;数据一致性和实时性可以通过主节点保证。主节点挂掉,需要用raft等重新选主;或者通过配置文件指定主从,人工介入选主。

所谓多主从,是指多个分区,分区内是主从结构;key映射分区如前所述。

数据同步

以redis为例,数据同步通过数据文件和命令操作实现。初次同步master将数据文件完整发送给slave,后者load至内存;随后增量同步,逐命令或者定时同步写操作。

通常master和slave会维护类似binlog offset的偏移量,断线同步时提高速度。如RocketMQ主从同步,主从服务器建立长连接,更新携带offset信息的commitlog数据,维护数据一致。

选主

RocketMQ通过配置文件指定主从,不会有选主这个过程,因此压根不涉及zk、raft等;redis则使用raft选主。

数据存储

数据结构

为了更合理的设计锁,通常都会自研一些数据结构,存储数据,提供快速读写功能。redis由于单线程设计,并没有过多考量,但还是设计了不少优秀的数据结构,如hash、跳表等。

数据往往可以以层次划分,连文件系统和操作系统都做层次化设计。对应数据服务,把锁分散在各层,尽量减少锁等待。

以一个多级hash+跳表结构为例,操作跳表时,锁粒度已经可以非常细。

持久化方法

内存数据和binlog哪个先写?binlog文件多久刷盘?写文件和刷盘是否在一个线程/进程?通常来讲需要先写binlog,确保服务重启时数据正常,然后写内存并返回。

最简单的持久化用leveldb,使用方便,接口清晰,稳定性毋庸置疑;而且leveldb写入速度极快,适合持久化。

自研binlog文件,可以实现更强大的功能:持久化文件配合内存数据结构,预分配+内存映射,快速加载;多种刷盘方式,配合无锁队列,加快写入速度;学习leveldb的merge方法,合并操作文件。

数据格式

服务间通信通常使用thrift/pb(json/http还是略重,不太适合后端服务;且thrift对网络的封装足够好),但是直接拿来用并不好,会对应用产生依赖,后续修改后患无穷。

类似下面要说的功能边界划分,对于数据格式,也要摆脱对上层的依赖;同时需要考虑扩展性,增删字段或者类型变化,上下兼容。加个header是不错的选择:

代码语言:javascript
复制
struct Header {
    int magic;
    int version;
    int nsize;
};

struct Data {
    Header header;
    int dsize;
    void* data;
};

最后

还有两个无状态服务也会面临的重点,功能边界划分线下环境搭建:内部数据服务不同于开源项目,常常会与业务逻辑耦合,提高性能,丰富功能;但是边界模糊最终会导致代码逻辑混乱,层次复杂;清晰的边界划分至关重要。QA喜欢直连线上环境——数据充分,便于发现问题;通过搭建良好的线下环境,避免线上数据被污染,配合数据校验等工具,确保新功能、降低风险。

经常有人问我,为什么不直接用redis?redis作为强大的通用缓存/存储系统,并不能满足特定需求;例如网约车行业,数据检索至少也需要经纬度、时间等。自研数据服务听起来非常高大上,高性能数据存储、分布式架构设计、解决业务痛点,对外宣传的一把好手;实际上只要根据业务场景,合理分析,完成稳定高效的数据服务非常简单。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-02-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 架构设计
    • 多主架构
      • 数据同步
    • 主从/多主从
      • 数据同步
      • 选主
  • 数据存储
    • 数据结构
      • 持久化方法
        • 数据格式
        • 最后
        相关产品与服务
        云数据库 Redis
        腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档