(译)Beyond Relational Databases:A Focus on Redis, MongoDB, and ClickHouse


percona的什么白皮书,我看就是一堆吐槽

关系型数据库不是万金油,用错反而是瓶颈

数据模型万金油,反而限制了扩展能力

sql好用但是不够灵活,json人人爱

ACID很重要,但是代价也很大,这也是关系型数据库的采用点

由于保证事务可靠,也就限制了扩展能力,数据模型简单不要求事务,上内存kv数据库

mysql也能存大数据,但是能存不能用,没啥意义,所以去掉索引,去掉关系限制,列式数据库诞生了


KV数据库

最开始的目的是做个数据库前端无状态缓存

要快,一般都是hashtable。不是为了替代关系型数据库,只是一项中间件技术

后来KV数据库发展成有简单协议的有命令有状态的服务了。不得不提redis

个人认为 redis能打败memcache,社区好,功能性强,memcache就是单纯的做无状态中间件。这种东西mysql内部也做小型cache,比如2Q啥的。不如一个组件强。但是组件本身也要考虑淘汰以及热点击穿的问题。这就是另一个话题了

典型代表redis提供了一些很好的特性,能让业务更简化,比如TTL, list,比如lua支持,LRU淘汰策略,多key事务,阻塞命令等等

做mysql前端最好不过,做个纯粹的数据库也可以(不落盘不停机)


文档数据库

最早来自邮件存储需求

json对象,sparse index 不存在的key就不要,非常灵活

灵活模式不等于没有模式

典型代表 mongodb 不止提供文档接口,还提供了分片管理,方便水平扩展,加钱上机器就行了

还有一些牛逼特性,比如聚合动作方便map-reduce ,geo相关功能,以及可插拔引擎(wiretiger/rocksdb)

劣势

嵌套表效率低

多表join查询

多表事务


列式存储

只要几列数据为什么不用覆盖索引?

  • 查询灵活难道要每一列都建索引吗?不现实
  • 插入要改动索引,复杂度爆炸延迟爆炸

作者没用Cassandra和hbase举例,而是用了clickhouse

  • 兼容大多数SQL
  • 也有索引,针对MergeTree引擎,支持主键,支持range查
  • Dictionaries 查表不用join
  • 低延迟,查询不用担心阻塞
  • 近似估计等等特殊特性

对于读敏感的大数据集,十分好用

OLTP


ref
  1. https://learn.percona.com/hubfs/ExpertOpinion/Beyond%20Relational%20Databases.pdf

看到这里或许你有建议或者疑问或者指出我的错误,请留言评论或者邮件mailto:wanghenshui@qq.com, 多谢!

觉得写的不错可以点开扫码赞助几毛 微信转账
Read More

改造glog 提供日志轮转


这个是同事的修改经验,写的挺有意思的,我直接抄过来了

glog是写日志的。选型pika使用,没改。存在的弊端

  • 没有日志删除。最新glog是按照日志轮转的,而不是按照个数/大小轮转
    • glog支持按照大小来切割轮转,但是不支持清理,清理,一个unlink的事儿。
  • 各种日志级别的信息是区分保存的,对于查看来说很不方便

我的同事在这两点上根据pika已有的结构来进行优化,优化的很巧妙:

  • 加上日志个数的glog接口,暴露出来,也就是实现一个接口来unlink
    • 对应的,所有的日志名字要保留到一个数组里。那这个数组的更新也要加锁
      • LogFileObject::CreateLogfile 更新数组,新增接口里改数组
    • 不能频繁检查。放到epoll时间时间里,定时触发
  • 对于第二点,在LogFileObject::Write里有具体的格式,level,去掉就行。LogDestination::FlushLogFilesUnsafe里去掉不同level的flush,改成一个

LogFileObject是具体的操作 LogDestination是底层具体的写入,会持有LogFileObject对象,所有接口从LogMessage暴露

总之挺巧妙的。学习一波经验

ref

  1. https://github.com/google/glog

看到这里或许你有建议或者疑问或者指出我的错误,请留言评论或者邮件mailto:wanghenshui@qq.com, 多谢!

觉得写的不错可以点开扫码赞助几毛 微信转账
Read More

改造pika如何去掉key锁


这个是同事的修改经验,虽然是针对业务而言的,但是这个思路十分的降维打击,我直接抄过来了

现有模型是slot-proxy-shard结构,上层有代理来转发,shard节点,也就是pika,只负责一部分数据

但是pika本身是有key锁的

比如https://github.com/Qihoo360/blackwidow/blob/ae38f5b4c5c01c7f8b9deec58db752e056659264/src/redis_lists.cc#L273

Status RedisLists::LInsert(const Slice& key,
                           const BeforeOrAfter& before_or_after,
                           const std::string& pivot,
                           const std::string& value,
                           int64_t* ret) {
  *ret = 0;
  rocksdb::WriteBatch batch;
  ScopeRecordLock l(lock_mgr_, key);
  std::string meta_value;
  Status s = db_->Get(default_read_options_, handles_[0], key, &meta_value);
  if (s.ok()) {
    ParsedListsMetaValue parsed_lists_meta_value(&meta_value);
    if (parsed_lists_meta_value.IsStale()) {
      return Status::NotFound("Stale");
    } else if (parsed_lists_meta_value.count() == 0) {
      return Status::NotFound();
    } else {
        ...

前面已经有一层proxy转发了,这层转发是根据hash来算还是根据range来算不重要,重要的是到计算节点,已经缩小了key范围了,还要加锁,这层锁是可以优化掉的

  • 保证落到这个db的key的顺序,也就是说,相同hash/range用同一个连接,保证了命令的顺序,就不会有锁的问题,锁也就可以省掉。从上层来解决掉这个锁的问题
    • shard节点的命令处理线程,要保证hash/range相同的用同一个连接线程工作。多一点计算,省掉一个锁。

pika单机版,用的是同一个db,同一个db是很难去掉key锁的。要想应用上面的改造,也要改成多db模式,把db改成slot,然后根据slot划分线程,然后根据线程来分配命令,保证命令的顺序,省掉锁。

省掉key锁的收益是很大的。尤其是一个命令里有很多次get,get很吃延迟,导致锁占用很长,导致积少成多的影响


看到这里或许你有建议或者疑问或者指出我的错误,请留言评论或者邮件mailto:wanghenshui@qq.com, 多谢!

觉得写的不错可以点开扫码赞助几毛 微信转账
Read More

rocksdb涉及到关闭开启的时间优化


这个是同事调参的经验,我直接抄过来了

不少都是经常提到的

rocksdb配置:

  • compaction加速设置compaction_readahead_size 很常规。值可以改改试试,16k 256k都有
  • wal日志调小 max_manifest_file_size, max-total-wal-size
  • close db的时候停掉compaction
    • rocksdb里有compaction任务,可能还会耗时,能停掉就更好了
  • close会主动flush flush可能触发compaction和write stall。先跳过
  • open会读wal恢复memtable,所以最好不要有wal,close的时候刷掉
  • targetbase和放大因子要根据自身的存储来调整 比如写入hdfs,设置60M就比较合适,不会频繁更新元数据

打开rocksdb文件过多 GetFileSize时间太长

  • 看到一个PR https://github.com/facebook/rocksdb/pull/6353/files 6.8版本在open阶段规避调用 GetFileSize

  • 我们这边同事的解决方案是hack OnAddFile调用的地方,改成多线程cv来添加。

这两个优化点位置不一样,一个在打开 恢复校验阶段,一个在打开阶段,这个打开阶段OnAddFile有GetFileSize,所以在OnAddFile之前,调用一把查文件大小,避开GetFileSize

    std::vector<LiveFileMetaData> metadata;

    impl->mutex_.Lock();
    impl->versions_->GetLiveFilesMetaData(&metadata);
    impl->mutex_.Unlock();

后面OnAddFile阶段就不用查size了,通过这里拿到的metadata,但是有的文件查不到,这里,原生rocksdb用的是GetFileSize,同事是用多线程异步去查,相比原生一个一个查能加速一点


看到这里或许你有建议或者疑问或者指出我的错误,请留言评论或者邮件mailto:wanghenshui@qq.com, 多谢!

觉得写的不错可以点开扫码赞助几毛 微信转账
Read More


学习/探索mongo


ppt地址 ,资料都是整理

macos上安装和演示

#安装
brew tap mongodb/brew
brew install mongodb-community@4.4
#拉起
brew services start mongodb-community@4.4
#停止
brew services stop mongodb-community@4.4
# mongo shell
mongo 127.0.0.1:27017

mongo 和sql对应概念 区分

SQL术语/概念 MongoDB 术语/概念
database database
table collection
row documentBSON document
column field
index index
table joins (表联接) $lookup, embedded documents (嵌入式文档)
primary key 指定任何唯一的列或者列组合作为主键 primary key 在 MongoDB 中, 主键自动设置为 _id 字段
aggregation (如:group by) aggregation pipeline (聚合管道)参考:SQL to Aggregation Mapping Chart
SELECT INTO NEW_TABLE $out 参考: SQL to Aggregation Mapping Chart
MERGE INTO TABLE $merge (从MongoDB 4.2开始可用) 参考:SQL to Aggregation Mapping Chart
transactions transactions

二进制对应关系

  MongoDB MySQL
数据库服务端 mongod mysqld
数据库客户端 mongo mysql
复制日志 oplog binlog
恢复用日志 journal redolog
最新 oplog 时间戳 snapshot 状态
t0 snapshot0 committed
t1 snapshot1 uncommitted
t2 snapshot2 uncommitted
t3 snapshot3 uncommitted

ref

  • https://www.runoob.com/mongodb/mongodb-osx-install.html
  • https://aotu.io/notes/2020/06/07/sql-to-mongo-1/index.html

看到这里或许你有建议或者疑问或者指出我的错误,请留言评论或者邮件mailto:wanghenshui@qq.com, 多谢!

觉得写的不错可以点开扫码赞助几毛 微信转账
Read More

threads safety annotations 以及std::priority_queue的一个小用法


我是随便浏览某个时间队列看到的类似的代码

  mutable mutex mu_;
  condition_variable cv_;
  std::thread timer_thread_;
  std::atomic<bool> stop_{false};
  std::priority_queue<RCReference<TimerEntry>,
                      std::vector<RCReference<TimerEntry>>,
                      TimerEntry::TimerEntryCompare>
      timers_ TFRT_GUARDED_BY(mu_);

这个GUARDED_BY让人好奇,简单查证了一番,发现是clang的工具

简单说就是clang编译器带的一个多线程的帮手,线程安全注解,原理是拓展 __attribute__

比如 __attribute__(guarded_by(mutex))

这样指明依赖关系,更能方便定位问题

使用的话编译带上 -Wthread-safety-analysis就可以了

没发现gcc有类似的工具。可惜。

另外这些时间队列的实现用的 std::priority_queue 很有意思,都指定了容器参数(因为不是内建的类型,没有实现operator <)

我看rocksdb的timequeue长这样

  // Inheriting from priority_queue, so we can access the internal container
  class Queue : public std::priority_queue<WorkItem, std::vector<WorkItem>,
                                           std::greater<WorkItem>> {
   public:
    std::vector<WorkItem>& getContainer() { return this->c; }

直接把容器参数暴漏出来。挺新颖的。这个数据结构设计保留了c就是为了这样暴露吧。


ref

  • https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
    • 可以直接把这个宏抄过去 http://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
      • https://github.com/tensorflow/runtime/blob/1f60e4778e91d9932ac04647769a178a9646c0a7/include/tfrt/support/thread_annotations.h 直接抄的
  • 原理论文 https://research.google.com/pubs/archive/42958.pdf
  • ppt介绍 https://llvm.org/devmtg/2011-11/Hutchins_ThreadSafety.pdf
  • 用法 1 https://stackoverflow.com/questions/40468897/clang-thread-safety-with-stdcondition-variable
  • 用法 2 https://zhuanlan.zhihu.com/p/47837673
  • std::priority_queue 看成员对象那一小节https://en.cppreference.com/w/cpp/container/priority_queue
  • 定时器实现总结 https://www.ibm.com/developerworks/cn/linux/l-cn-timers/index.html 文章写得很棒

重点关注最小堆(优先队列) 来维护定时器组,以及时间轮

  • https://www.zhihu.com/question/68451392 管理定时器,不一定需要timerqueue 暴力扫也不是不可以 只要timer不多
  • kafka中的时间轮 https://club.perfma.com/article/328984
  • https://www.cnblogs.com/zhongwencool/p/timing_wheel.html 他这个博客做的不错。。。

看到这里或许你有建议或者疑问或者指出我的错误,请留言评论或者邮件mailto:wanghenshui@qq.com, 多谢!

觉得写的不错可以点开扫码赞助几毛 微信转账
Read More

六月待读 need review

我发现越攒越多了这东西

https://github.com/YongjunHe/corobase

https://hal.inria.fr/file/index/docid/555588/filename/techreport.pdf

oatpp

https://github.com/oatpp/oatpp#api-controller-and-request-mapping

continuable

https://naios.github.io/continuable/

https://chubaofs.github.io/chubaodb/zh-CN/config.html

https://hammertux.github.io/slab-allocator

coroutine

https://luncliff.github.io/coroutine/articles/combining-coroutines-and-pthread_create/

https://www.jianshu.com/u/bb58761c6c04

分布式

https://cloud.tencent.com/developer/article/1015442

network

https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/#

https://blog.packagecloud.io/eng/2017/02/06/monitoring-tuning-linux-networking-stack-sending-data/

crdt

https://techbeacon.com/app-dev-testing/how-simplify-distributed-app-development-crdts

https://redislabs.com/redis-enterprise/technology/active-active-geo-distribution/

mongo

https://mongoing.com/archives/6102

https://blog.csdn.net/baijiwei/article/details/78070355

https://blog.csdn.net/baijiwei/article/details/78303200

https://zhuanlan.zhihu.com/c_1047791597869199360

redis延迟分析

https://github.com/moooofly/MarkSomethingDown/blob/master/Redis/Redis%20%E8%AE%BF%E9%97%AE%E5%BB%B6%E8%BF%9F%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90.md

brpc

https://zhuanlan.zhihu.com/p/113427004

hbase结构介绍

https://niyanchun.com/hbase-introduction-extend.html

我比较关系高可用,负载均衡(range server分裂,怎么做的),以及强一致性的实现

大多是怎么用的文档

bluestore

https://zhuanlan.zhihu.com/p/45084771

https://zhuanlan.zhihu.com/p/46362124

making tcp fast

应该有中文文档

https://netdevconf.info/1.2/papers/bbr-netdev-1.2.new.new.pdf

network 101

https://hpbn.co/building-blocks-of-udp/#null-protocol-services

brendan gregg博客分享

抓tcp

http://www.brendangregg.com/blog/2018-03-22/tcp-tracepoints.html

bpf

http://www.brendangregg.com/bpf-performance-tools-book.html

nginx 延迟高吞吐 分享ppt

https://www.nginx.com/blog/optimizing-web-servers-for-high-throughput-and-low-latency/

大页内存和tlb

https://www.mnstory.net/2016/06/30/qemu-hugepages/

还是透明大页

https://www.percona.com/blog/2019/03/06/settling-the-myth-of-transparent-hugepages-for-databases/

针对写放大的kv sifrdb

https://nan01ab.github.io/2019/02/LSM-Trees(2).html

jungle

btree + lsm https://www.usenix.org/system/files/hotstorage19-paper-ahn.pdf

https://www.usenix.org/sites/default/files/conference/protected-files/hotstorage19_slides_ahn.pdf

写个快的json parser

https://chadaustin.me/2017/05/writing-a-really-really-fast-json-parser/

https://chadaustin.me/2013/01/sajson-why-the-parse-tree-is-big-enough/

smfrpchttps://smfrpc.github.io/smf/

years watching https://nwat.xyz/blog/2018/01/15/systems-research-im-watching-for-in-2018/

linux性能调优指南

https://lihz1990.gitbooks.io/transoflptg/content/01.%E7%90%86%E8%A7%A3Linux%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/1.1.Linux%E8%BF%9B%E7%A8%8B%E7%AE%A1%E7%90%86.html

一个leetcode套路题

https://lucifer.ren/blog/2020/06/13/%E5%88%A0%E9%99%A4%E9%97%AE%E9%A2%98/

深入理解iostat

https://bean-li.github.io/dive-into-iostat/

为什么就没有个一图剩千言的模板图呢?

十分钟教会看top

https://juejin.im/post/5d590126f265da03db0776b6

为什么就没有个一图剩千言的模板图呢??

tcpdump

https://danielmiessler.com/study/tcpdump/

为什么就没有个一图剩千言的模板图呢???

boltdb介绍

https://lrita.github.io/2017/05/21/boltdb-overview-0/

常见db比较

https://cloud.tencent.com/developer/article/1067439

SILT – A Memory-Efficient, High-Performance Key-Value Store

https://nan01ab.github.io/2018/04/SILT.html

再议silt

http://blog.foool.net/2012/06/%E5%86%8D%E8%AE%AEsilt-a-memory-efficient-high-performance-key-value-store/

faster and cpr

https://nan01ab.github.io/2019/05/FASTER.html

taurus db https://nan01ab.github.io/2020/06/Taurus.html

evendb

热点优化

https://www.jianshu.com/p/bc6a5ee0d3db

https://nan01ab.github.io/2020/06/KV-Store(2).html

这个人博客不错

https://www.jianshu.com/u/bb58761c6c04

https://sekwonlee.github.io/files/nvmw20_splitfs.pdf

看到这里或许你有建议或者疑问或者指出我的错误,请留言评论或者邮件mailto:wanghenshui@qq.com, 多谢!

觉得写的不错可以点开扫码赞助几毛 微信转账
Read More

(cppcon)一些老的编程规范的反思

goto harmful?

goto更像汇编一点。

感觉是老生长谈了,常用的goto场景还算处理错误码退出,还列了论文,高德纳的

goto 在c++:可能那个跳过构造函数,漏掉初始化(编译不过/编译告警),注意(setjmp是不是也这样)

循环中提前退出, goto版本更高效 (why??)

switch里用goto c++里没有对应的应用,类似 duff’s device????? 手动展开循环 别手写,让编译器干这个活

用switch就算用goto了

讨论了其他语言中的使用套路 pattern, 没记录 只记录c++相关的

  • 不能跳过复杂类型初始化?non-vacuous怎么翻译?我大概理解就算没有默认构造的
  • 不能跳出/跳入函数
  • 不能用在constexpr函数
  • 不能跳入try catch,跳出没事儿(都try-catch了还用goto感觉有点分裂)

函数退出集中起来。

(确实,多路返回的代码让人痛苦,我也写过那种。。 不清晰)

上面讨论的for循环return 低效,可以把for中间判断限制一下,提前break,起到goto效果

返回值复杂,比如variant 使用overload trick,variant的switch

几种例外,能省构造等等。各取所需

成员变量private访问权限

封装 不变量 提前设计 即使你用不到 需要c#那种proprity? class封装和struct那种透明的语义就不一样了。还是哪句话,用不到不要过度设计

声明就初始化

可能写成函数声明了,ecpp有一条 某些场景没必要非得初始化 你不用的,不要多付出

还有在函数开头声明,这是c的习惯,可能用不到,白白浪费构造 其他语言也是一样,什么时候用什么时候声明 两部初始化,工厂模式

ref

  1. https://www.bilibili.com/video/BV1pJ411w7kh?p=12
  2. ppt 在这里 https://github.com/CppCon/CppCon2019/blob/master/Presentations/some_programming_myths_revisited/some_programming_myths_revisited__patrice_roy__cppcon_2019.pdf

看到这里或许你有建议或者疑问或者指出我的错误,请留言评论或者邮件mailto:wanghenshui@qq.com, 多谢!

觉得写的不错可以点开扫码赞助几毛 微信转账
Read More

(cppcon)当零抽象失败 怎么把编译器问题解决掉?

这个演讲者写了个python to c++的程序 pythran,牛逼阿 这个演讲是pythran生成代码有个bug,抓bug的故事,涉及到llvm

演示了一个简单的add代码,性能差很多,编译器问题(怎么定界的这么快)

首先找最小复现代码片 c的实现是向量化的,但是llvm生成的ir没有向量化

用clang的 -Rpass-missed=loop-vectoreze -Rpass-analysis=loop-vectorize

分析得到没有循环优化

然后看llvm的代码,编译debug版本看打印

PHI node检测有问题

看checker的条件

inttoptr <=> ptrtoint 逻辑有问题?

这里我就跟不太上了,llvm不了解。得看一下llvm相关的东西

作者做了个去掉的patch,验证,结果向量化了

深层问题 SROA 已经提bug修了

回到标题,零成本抽象是牛逼的,但是需要编译器来达成这个优化

编译器有没有保证的最低程度优化?没。所以需要了解这个东西,了解优化程度 作者的建议就是看ir结果,对比,跑omit, analyze,以及了解c 的llvm ir。简单

ref

  1. https://github.com/serge-sans-paille/pythran
  2. https://www.bilibili.com/video/BV1pJ411w7kh?p=154
  3. PPT没找到

todo

看看llvm的资料


看到这里或许你有建议或者疑问或者指出我的错误,请留言评论或者邮件mailto:wanghenshui@qq.com, 多谢!

觉得写的不错可以点开扫码赞助几毛 微信转账
Read More

^