nosql性能测试,浅谈nosql技术及应用论文
如何根据性能选择内存NoSQL数据库
本文主要内容是测试了不同NoSQL数据库在测试工具YCSB中的表现。我们选取了3款流行的内存(in-memory)数据库管理系统:Redis,Tarantool 以及 CouchBase,还有缓存系统Memchached。Memchached虽然不属于数据库管理系统但常作为快速存储系统使用。
10年积累的成都做网站、成都网站建设经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先做网站设计后付款的网站建设流程,更有香河免费网站建设让你可以放心的选择与我们合作。
测试环境由4台在Microsoft Azure Cloud中的虚拟机组成的计算机组组成。这些虚拟机同属于一个数据中心。nosql-1和nosql-2用作测试Tarantool和CouchBase,nosql-3和nosql-4用作测试Redis,Azure Redis Cache 以及 Memcached。这些机器都安装和配置了相应数据库和测试项目。虚拟机的配置为4核A3 CPU,7GB RAM,120GB硬盘。
数据库及设置
内存数据库管理系统会存储所有在主内存中的数据并在磁碟上进行持续更新操作;透过日志记录每个数据的修改以确保连贯性。由于是以append-only方式进行日志写入,因此它很少遇到瓶颈问题;读取/写入都不会造成频繁的磁碟头移动。
Redis在2009推出,目前的最新版本是3.0.5。我们这里使用的版本是3.0.4,以append-only(只附加)方式进行数据管理,与其配合使用的是Microsoft Azure Redis Cache工具。
Tarantool是一款开源NoSQL数据库管理系统。我们使用的是Tarantool 1.6.7-126-gb35aff9,日志采用write-ahead(先写)模式。Memcached是一款分布式内存缓存系统,这里使用是Memcached 1.4.14-0ubuntu9。
Couchbase Server是开源分布式NoSQL面向文档数据库,这里使用的版本是Couchbase 4.0.0-4047-1。
YCSB测试工具
Yahoo! Cloud Serving Benchmark(YCSB)是功能强大的NoSQL数据库性能测试工具,它提供了6种主要的负载工作类型,以字母A到F来区分。
负载A负责更新操作,极值是50/50的读写操作,如用于进行新近操作记录。负载B负责读取操作,极值是95/5的读写操作,如用于进行图片标签管理,多进行标签读取操作。负载C负载100%的读取操作,如用于进行用户属性获取。负载D以先进先出方式进行插入操作,如用户进行最新数据读取。负载E负责小范围记录读取而不是单个记录读取,如线程会话。负载F负责记录的读取,修改和写入,如用户信息管理。
我们对配置文件作了两处参数修改:数据条目recordcount设为200000,操作条目operationcount设为5000000。YCSB是多线程工具,我们将以8, 16, 32, 64, 128 及256 线程来进行测试。详细的测试脚本请点击这里进行下载。
下列测试结果图以颜色进行测试对象区分,
Tarantool (HASH) (蓝)
Tarantool (TREE)(浅蓝)
Redis (红)
Azure Redis Cache (橙)
Memcached (绿)
CouchBase(黑)
更多图片请点击[这里]查看。
结论
Tarantool在所有负载类型测试中皆取得了最优成绩。它创建了一个无锁内存引擎,以协同多任务方式进行操作而不是互斥或并行处理方式。根据以下性能图表现,我们的结论是Tarantool的高吞吐量处理是其最大优势之一。因此在多数场合下,Tarantool是用户的最佳选择。
ssdb、minio性能测试c
项目上需要找一个硬盘型的NoSQL,用于将 Redis 中的冷数据落入硬盘。初步选型了几款 key-value 类型的NoSQL,分别有 levelDB、 rocksDB、 TiDB、 SSDB、swapDB、 Kvrocks、Tikv 。均为基于 levelDB 开发的几款NoSQL。其中因为 levelDB、rocksDB 无网络接口,不方便做分布式和高可用。, TiDB 过重,还有 swapDB 社区不够活跃且相关client API不完备。暂时选型 SSDB 。
项目需要存储的其实是一个略长的二进制字符串,初步认为,使用 对象存储 方案其实也可以替代NoSQL,所以压测对象添加当前非常火的云原生对象存储 MinIO
硬件名|配置 系统| Ubuntu(基于win10 wsl版的docker启动) 内存| 16GB(实际可用6.08G) CPU| Intel i5-8400
测试项目: 1. 写50M数据100次 2. 随机读取任意key 100次(对LRU机制不友好)
写
数据导入成功!
数据序列化成功!
a 数据大小:50.99295234680176 MB
第1次写入总用时: 797 ms
第2次写入总用时: 848 ms
第3次写入总用时: 3621 ms
第4次写入总用时: 813 ms
第5次写入总用时: 1862 ms
第6次写入总用时: 838 ms
第7次写入总用时: 2235 ms
第8次写入总用时: 836 ms
第9次写入总用时: 900 ms
第10次写入总用时: 1027 ms
第11次写入总用时: 1101 ms
第12次写入总用时: 880 ms
第13次写入总用时: 1956 ms
第14次写入总用时: 866 ms
第15次写入总用时: 2422 ms
第16次写入总用时: 852 ms
第17次写入总用时: 4511 ms
第18次写入总用时: 875 ms
第19次写入总用时: 2736 ms
第20次写入总用时: 814 ms
第21次写入总用时: 7172 ms
第22次写入总用时: 891 ms
第23次写入总用时: 7820 ms
第24次写入总用时: 836 ms
第25次写入总用时: 22103 ms
第26次写入总用时: 877 ms
第27次写入总用时: 2712 ms
第28次写入总用时: 841 ms
第29次写入总用时: 1928 ms
第30次写入总用时: 916 ms
第31次写入总用时: 839 ms
第32次写入总用时: 826 ms
第33次写入总用时: 7759 ms
第34次写入总用时: 843 ms
第35次写入总用时: 10670 ms
第36次写入总用时: 843 ms
第37次写入总用时: 9361 ms
第38次写入总用时: 821 ms
第39次写入总用时: 810 ms
第40次写入总用时: 794 ms
第41次写入总用时: 13281 ms
第42次写入总用时: 833 ms
第43次写入总用时: 811 ms
第44次写入总用时: 798 ms
第45次写入总用时: 18843 ms
第46次写入总用时: 911 ms
第47次写入总用时: 9428 ms
第48次写入总用时: 898 ms
第49次写入总用时: 17582 ms
第50次写入总用时: 903 ms
第51次写入总用时: 831 ms
第52次写入总用时: 800 ms
第53次写入总用时: 14602 ms
第54次写入总用时: 827 ms
第55次写入总用时: 5898 ms
第56次写入总用时: 856 ms
第57次写入总用时: 5693 ms
第58次写入总用时: 1050 ms
第59次写入总用时: 882 ms
第60次写入总用时: 1020 ms
第61次写入总用时: 15060 ms
第62次写入总用时: 902 ms
第63次写入总用时: 1062 ms
第64次写入总用时: 915 ms
第65次写入总用时: 7572 ms
第66次写入总用时: 823 ms
第67次写入总用时: 9649 ms
第68次写入总用时: 832 ms
第69次写入总用时: 10403 ms
第70次写入总用时: 907 ms
第71次写入总用时: 978 ms
第72次写入总用时: 789 ms
第73次写入总用时: 2111 ms
第74次写入总用时: 947 ms
第75次写入总用时: 4675 ms
第76次写入总用时: 944 ms
第77次写入总用时: 8592 ms
第78次写入总用时: 832 ms
第79次写入总用时: 2940 ms
第80次写入总用时: 842 ms
第81次写入总用时: 19835 ms
第82次写入总用时: 862 ms
第83次写入总用时: 7646 ms
第84次写入总用时: 873 ms
第85次写入总用时: 1002 ms
第86次写入总用时: 842 ms
第87次写入总用时: 9057 ms
第88次写入总用时: 801 ms
第89次写入总用时: 5117 ms
第90次写入总用时: 918 ms
第91次写入总用时: 798 ms
第92次写入总用时: 853 ms
第93次写入总用时: 7728 ms
第94次写入总用时: 810 ms
第95次写入总用时: 3969 ms
第96次写入总用时: 814 ms
第97次写入总用时: 2050 ms
第98次写入总用时: 819 ms
第99次写入总用时: 9566 ms
第100次写入总用时: 833 ms/pre
随机读
第1次读取 15总用时: 2251 ms
第2次读取 73总用时: 2045 ms
第3次读取 98总用时: 1548 ms
第4次读取 20总用时: 2683 ms
第5次读取 46总用时: 1156 ms
第6次读取 69总用时: 1160 ms
第7次读取 46总用时: 1520 ms
第8次读取 51总用时: 1381 ms
第9次读取 48总用时: 1000 ms
第10次读取 69总用时: 1400 ms
第11次读取 82总用时: 1236 ms
第12次读取 22总用时: 1140 ms
第13次读取 36总用时: 864 ms
第14次读取 66总用时: 843 ms
第15次读取 47总用时: 922 ms
第16次读取 17总用时: 885 ms
第17次读取 14总用时: 864 ms
第18次读取 64总用时: 888 ms
第19次读取 74总用时: 815 ms
第20次读取 33总用时: 866 ms
第21次读取 36总用时: 822 ms
第22次读取 78总用时: 975 ms
第23次读取 40总用时: 1186 ms
第24次读取 54总用时: 857 ms
第25次读取 92总用时: 963 ms
第26次读取 43总用时: 955 ms
第27次读取 38总用时: 853 ms
第28次读取 47总用时: 926 ms
第29次读取 62总用时: 877 ms
第30次读取 70总用时: 890 ms
第31次读取 88总用时: 895 ms
第32次读取 15总用时: 937 ms
第33次读取 3总用时: 993 ms
第34次读取 99总用时: 892 ms
第35次读取 76总用时: 818 ms
第36次读取 30总用时: 1020 ms
第37次读取 89总用时: 863 ms
第38次读取 99总用时: 819 ms
第39次读取 62总用时: 818 ms
第40次读取 1总用时: 871 ms
第41次读取 66总用时: 809 ms
第42次读取 68总用时: 847 ms
第43次读取 72总用时: 910 ms
第44次读取 50总用时: 1128 ms
第45次读取 47总用时: 898 ms
第46次读取 26总用时: 909 ms
第47次读取 35总用时: 872 ms
第48次读取 30总用时: 826 ms
第49次读取 79总用时: 904 ms
第50次读取 66总用时: 863 ms
第51次读取 2总用时: 885 ms
第52次读取 65总用时: 900 ms
第53次读取 67总用时: 1023 ms
第54次读取 16总用时: 934 ms
第55次读取 63总用时: 892 ms
第56次读取 9总用时: 894 ms
第57次读取 71总用时: 896 ms
第58次读取 20总用时: 947 ms
第59次读取 89总用时: 865 ms
第60次读取 57总用时: 872 ms
第61次读取 62总用时: 856 ms
第62次读取 14总用时: 881 ms
第63次读取 19总用时: 950 ms
第64次读取 14总用时: 876 ms
第65次读取 86总用时: 968 ms
第66次读取 12总用时: 911 ms
第67次读取 93总用时: 877 ms
第68次读取 59总用时: 886 ms
第69次读取 79总用时: 878 ms
第70次读取 49总用时: 869 ms
第71次读取 91总用时: 964 ms
第72次读取 38总用时: 838 ms
第73次读取 73总用时: 915 ms
第74次读取 8总用时: 875 ms
第75次读取 96总用时: 827 ms
第76次读取 98总用时: 826 ms
第77次读取 95总用时: 892 ms
第78次读取 36总用时: 843 ms
第79次读取 44总用时: 872 ms
第80次读取 89总用时: 863 ms
第81次读取 24总用时: 883 ms
第82次读取 89总用时: 804 ms
第83次读取 49总用时: 876 ms
第84次读取 81总用时: 873 ms
第85次读取 72总用时: 914 ms
第86次读取 68总用时: 861 ms
第87次读取 73总用时: 893 ms
第88次读取 4总用时: 880 ms
第89次读取 3总用时: 987 ms
第90次读取 76总用时: 896 ms
第91次读取 16总用时: 1010 ms
第92次读取 73总用时: 903 ms
第93次读取 83总用时: 933 ms
第94次读取 52总用时: 945 ms
第95次读取 48总用时: 901 ms
第96次读取 26总用时: 942 ms
第97次读取 37总用时: 883 ms
第98次读取 44总用时: 866 ms
第99次读取 89总用时: 921 ms
第100次读取 61总用时: 896 ms/pre
写
数据导入成功!
第1次写入总用时: 956 ms
第2次写入总用时: 912 ms
第3次写入总用时: 1241 ms
第4次写入总用时: 1564 ms
第5次写入总用时: 942 ms
第6次写入总用时: 3666 ms
第7次写入总用时: 1629 ms
第8次写入总用时: 1712 ms
第9次写入总用时: 977 ms
第10次写入总用时: 1515 ms
第11次写入总用时: 911 ms
第12次写入总用时: 1009 ms
第13次写入总用时: 1024 ms
第14次写入总用时: 1206 ms
第15次写入总用时: 984 ms
第16次写入总用时: 943 ms
第17次写入总用时: 954 ms
第18次写入总用时: 1033 ms
第19次写入总用时: 1008 ms
第20次写入总用时: 1121 ms
第21次写入总用时: 963 ms
第22次写入总用时: 949 ms
第23次写入总用时: 889 ms
第24次写入总用时: 1066 ms
第25次写入总用时: 1289 ms
第26次写入总用时: 1125 ms
第27次写入总用时: 1111 ms
第28次写入总用时: 953 ms
第29次写入总用时: 964 ms
第30次写入总用时: 1125 ms
第31次写入总用时: 998 ms
第32次写入总用时: 1993 ms
第33次写入总用时: 926 ms
第34次写入总用时: 920 ms
第35次写入总用时: 926 ms
第36次写入总用时: 1169 ms
第37次写入总用时: 1325 ms
第38次写入总用时: 1170 ms
第39次写入总用时: 1074 ms
第40次写入总用时: 1011 ms
第41次写入总用时: 931 ms
第42次写入总用时: 984 ms
第43次写入总用时: 1563 ms
第44次写入总用时: 905 ms
第45次写入总用时: 944 ms
第46次写入总用时: 1147 ms
第47次写入总用时: 1429 ms
第48次写入总用时: 934 ms
第49次写入总用时: 1133 ms
第50次写入总用时: 912 ms
第51次写入总用时: 953 ms
第52次写入总用时: 1127 ms
第53次写入总用时: 1065 ms
第54次写入总用时: 1323 ms
第55次写入总用时: 1003 ms
第56次写入总用时: 1489 ms
第57次写入总用时: 1377 ms
第58次写入总用时: 940 ms
第59次写入总用时: 1317 ms
第60次写入总用时: 912 ms
第61次写入总用时: 898 ms
第62次写入总用时: 934 ms
第63次写入总用时: 1005 ms
第64次写入总用时: 1729 ms
第65次写入总用时: 983 ms
第66次写入总用时: 1684 ms
第67次写入总用时: 908 ms
第68次写入总用时: 895 ms
第69次写入总用时: 1171 ms
第70次写入总用时: 1372 ms
第71次写入总用时: 1261 ms
第72次写入总用时: 1024 ms
第73次写入总用时: 1048 ms
第74次写入总用时: 904 ms
第75次写入总用时: 941 ms
第76次写入总用时: 928 ms
第77次写入总用时: 1806 ms
第78次写入总用时: 1052 ms
第79次写入总用时: 1030 ms
第80次写入总用时: 1092 ms
第81次写入总用时: 1117 ms
第82次写入总用时: 950 ms
第83次写入总用时: 933 ms
第84次写入总用时: 928 ms
第85次写入总用时: 935 ms
第86次写入总用时: 1908 ms
第87次写入总用时: 994 ms
第88次写入总用时: 1097 ms
第89次写入总用时: 930 ms
第90次写入总用时: 1052 ms
第91次写入总用时: 1119 ms
第92次写入总用时: 958 ms
第93次写入总用时: 987 ms
第94次写入总用时: 973 ms
第95次写入总用时: 2036 ms
第96次写入总用时: 891 ms
第97次写入总用时: 954 ms
第98次写入总用时: 951 ms
第99次写入总用时: 1044 ms
第100次写入总用时: 1366 ms/pre
随机读
第1次读取 46总用时: 40 ms
第2次读取 8总用时: 36 ms
第3次读取 28总用时: 26 ms
第4次读取 80总用时: 10 ms
第5次读取 77总用时: 13 ms
第6次读取 27总用时: 49 ms
第7次读取 86总用时: 20 ms
第8次读取 0总用时: 45 ms
第9次读取 54总用时: 34 ms
第10次读取 24总用时: 153 ms
第11次读取 78总用时: 29 ms
第12次读取 0总用时: 17 ms
第13次读取 91总用时: 56 ms
第14次读取 5总用时: 99 ms
第15次读取 23总用时: 138 ms
第16次读取 37总用时: 120 ms
第17次读取 40总用时: 156 ms
第18次读取 88总用时: 41 ms
第19次读取 76总用时: 32 ms
第20次读取 49总用时: 102 ms
第21次读取 20总用时: 179 ms
第22次读取 40总用时: 68 ms
第23次读取 6总用时: 215 ms
第24次读取 36总用时: 197 ms
第25次读取 37总用时: 30 ms
第26次读取 68总用时: 154 ms
第27次读取 14总用时: 314 ms
第28次读取 27总用时: 91 ms
第29次读取 51总用时: 255 ms
第30次读取 66总用时: 166 ms
第31次读取 86总用时: 140 ms
第32次读取 29总用时: 374 ms
第33次读取 96总用时: 235 ms
第34次读取 68总用时: 72 ms
第35次读取 74总用时: 264 ms
第36次读取 11总用时: 334 ms
第37次读取 55总用时: 316 ms
第38次读取 31总用时: 287 ms
第39次读取 93总用时: 233 ms
第40次读取 44总用时: 499 ms
第41次读取 26总用时: 312 ms
第42次读取 76总用时: 33 ms
第43次读取 11总用时: 31 ms
第44次读取 86总用时: 191 ms
第45次读取 96总用时: 217 ms
第46次读取 20总用时: 145 ms
第47次读取 1总用时: 772 ms
第48次读取 69总用时: 477 ms
第49次读取 9总用时: 320 ms
第50次读取 46总用时: 42 ms
第51次读取 34总用时: 823 ms
第52次读取 76总用时: 115 ms
第53次读取 62总用时: 635 ms
第54次读取 99总用时: 596 ms
第55次读取 64总用时: 657 ms
第56次读取 66总用时: 97 ms
第57次读取 18总用时: 461 ms
第58次读取 91总用时: 247 ms
第59次读取 46总用时: 147 ms
第60次读取 12总用时: 702 ms
第61次读取 79总用时: 545 ms
第62次读取 47总用时: 956 ms
第63次读取 17总用时: 853 ms
第64次读取 97总用时: 771 ms
第65次读取 74总用时: 368 ms
第66次读取 84总用时: 790 ms
第67次读取 72总用时: 866 ms
第68次读取 82总用时: 742 ms
第69次读取 93总用时: 313 ms
第70次读取 57总用时: 917 ms
第71次读取 61总用时: 1185 ms
第72次读取 66总用时: 162 ms
第73次读取 5总用时: 168 ms
第74次读取 68总用时: 275 ms
第75次读取 43总用时: 1108 ms
第76次读取 74总用时: 281 ms
第77次读取 65总用时: 955 ms
第78次读取 22总用时: 1169 ms
第79次读取 88总用时: 501 ms
第80次读取 80总用时: 1685 ms
第81次读取 92总用时: 1286 ms
第82次读取 89总用时: 1680 ms
第83次读取 30总用时: 1537 ms
第84次读取 41总用时: 1576 ms
第85次读取 2总用时: 2193 ms
第86次读取 52总用时: 1817 ms
第87次读取 8总用时: 323 ms
第88次读取 81总用时: 1409 ms
第89次读取 40总用时: 577 ms
第90次读取 88总用时: 598 ms
第91次读取 19总用时: 2324 ms
第92次读取 75总用时: 2275 ms
第93次读取 29总用时: 668 ms
第94次读取 77总用时: 2773 ms
第95次读取 62总用时: 484 ms
第96次读取 84总用时: 883 ms
第97次读取 32总用时: 2945 ms
第98次读取 44总用时: 884 ms
第99次读取 66总用时: 631 ms
第100次读取 38总用时: 2739 ms/pre
非常奇怪的是 MinIO 整体性能略优于 SSDB 但是理论上不太应该, SSDB 怎么说也是半内存半硬盘的NoSQL不应该比纯硬盘的 MinIO 性能要差,有可能是 SSDB 写到一定数据量后把本机内存写爆了,导致读写非常慢。但这变相验证了 SSDB 在极端情况下的不稳定。
分库分表 VS newsql数据库
最近与同行 科技 交流,经常被问到分库分表与分布式数据库如何选择,网上也有很多关于中间件+传统关系数据库(分库分表)与NewSQL分布式数据库的文章,但有些观点与判断是我觉得是偏激的,脱离环境去评价方案好坏其实有失公允。
本文通过对两种模式关键特性实现原理对比,希望可以尽可能客观、中立的阐明各自真实的优缺点以及适用场景。
首先关于“中间件+关系数据库分库分表”算不算NewSQL分布式数据库问题,国外有篇论文pavlo-newsql-sigmodrec,如果根据该文中的分类,Spanner、TiDB、OB算是第一种新架构型,Sharding-Sphere、Mycat、DRDS等中间件方案算是第二种(文中还有第三种云数据库,本文暂不详细介绍)。
基于中间件(包括SDK和Proxy两种形式)+传统关系数据库(分库分表)模式是不是分布式架构?我觉得是的,因为存储确实也分布式了,也能实现横向扩展。但是不是"伪"分布式数据库?从架构先进性来看,这么说也有一定道理。"伪"主要体现在中间件层与底层DB重复的SQL解析与执行计划生成、存储引擎基于B+Tree等,这在分布式数据库架构中实际上冗余低效的。为了避免引起真伪分布式数据库的口水战,本文中NewSQL数据库特指这种新架构NewSQL数据库。
NewSQL数据库相比中间件+分库分表的先进在哪儿?画一个简单的架构对比图:
这些大多也是NewSQL数据库产品主要宣传的点,不过这些看起来很美好的功能是否真的如此?接下来针对以上几点分别阐述下的我的理解。
这是把双刃剑。
CAP限制
想想更早些出现的NoSQL数据库为何不支持分布式事务(最新版的mongoDB等也开始支持了),是缺乏理论与实践支撑吗?并不是,原因是CAP定理依然是分布式数据库头上的颈箍咒,在保证强一致的同时必然会牺牲可用性A或分区容忍性P。为什么大部分NoSQL不提供分布式事务?
那么NewSQL数据库突破CAP定理限制了吗?并没有。NewSQL数据库的鼻主Google Spanner(目前绝大部分分布式数据库都是按照Spanner架构设计的)提供了一致性和大于5个9的可用性,宣称是一个“实际上是CA”的,其真正的含义是 系统处于 CA 状态的概率非常高,由于网络分区导致的服务停用的概率非常小 ,究其真正原因是其打造私有全球网保证了不会出现网络中断引发的网络分区,另外就是其高效的运维队伍,这也是cloud spanner的卖点。详细可见CAP提出者Eric Brewer写的《Spanner, TrueTime 和CAP理论》。
完备性 :
两阶段提交协议是否严格支持ACID,各种异常场景是不是都可以覆盖?
2PC在commit阶段发送异常,其实跟最大努力一阶段提交类似也会有部分可见问题,严格讲一段时间内并不能保证A原子性和C一致性(待故障恢复后recovery机制可以保证最终的A和C)。完备的分布式事务支持并不是一件简单的事情,需要可以应对网络以及各种硬件包括网卡、磁盘、CPU、内存、电源等各类异常,通过严格的测试。之前跟某友商交流,他们甚至说目前已知的NewSQL在分布式事务支持上都是不完整的,他们都有案例跑不过,圈内人士这么笃定,也说明了 分布式事务的支持完整程度其实是层次不齐的。
但分布式事务又是这些NewSQL数据库的一个非常重要的底层机制,跨资源的DML、DDL等都依赖其实现,如果这块的性能、完备性打折扣,上层跨分片SQL执行的正确性会受到很大影响。
性能
传统关系数据库也支持分布式事务XA,但为何很少有高并发场景下用呢? 因为XA的基础两阶段提交协议存在网络开销大,阻塞时间长、死锁等问题,这也导致了其实际上很少大规模用在基于传统关系数据库的OLTP系统中。
NewSQL数据库的分布式事务实现也仍然多基于两阶段提交协议,例如google percolator分布式事务模型,
采用原子钟+MVCC+ Snapshot Isolation(SI),这种方式通过TSO(Timestamp Oracle)保证了全局一致性,通过MVCC避免了锁,另外通过primary lock和secondary lock将提交的一部分转为异步,相比XA确实提高了分布式事务的性能。
但不管如何优化,相比于1PC,2PC多出来的GID获取、网络开销、prepare日志持久化还是会带来很大的性能损失,尤其是跨节点的数量比较多时会更加显著,例如在银行场景做个批量扣款,一个文件可能上W个账户,这样的场景无论怎么做还是吞吐都不会很高。
虽然NewSQL分布式数据库产品都宣传完备支持分布式事务,但这并不是说应用可以完全不用关心数据拆分,这些数据库的最佳实践中仍然会写到,应用的大部分场景尽可能避免分布式事务。
既然强一致事务付出的性能代价太大,我们可以反思下是否真的需要这种强一致的分布式事务?尤其是在做微服务拆分后,很多系统也不太可能放在一个统一的数据库中。尝试将一致性要求弱化,便是柔性事务,放弃ACID(Atomicity,Consistency, Isolation, Durability),转投BASE(Basically Available,Soft state,Eventually consistent),例如Saga、TCC、可靠消息保证最终一致等模型,对于大规模高并发OLTP场景,我个人更建议使用柔性事务而非强一致的分布式事务。关于柔性事务,笔者之前也写过一个技术组件,最近几年也涌现出了一些新的模型与框架(例如阿里刚开源的Fescar),限于篇幅不再赘述,有空再单独写篇文章。
HA与异地多活
主从模式并不是最优的方式,就算是半同步复制,在极端情况下(半同步转异步)也存在丢数问题,目前业界公认更好的方案是基于paxos分布式一致性协议或者其它类paxos如raft方式,Google Spanner、TiDB、cockcoachDB、OB都采用了这种方式,基于Paxos协议的多副本存储,遵循过半写原则,支持自动选主,解决了数据的高可靠,缩短了failover时间,提高了可用性,特别是减少了运维的工作量,这种方案技术上已经很成熟,也是NewSQL数据库底层的标配。
当然这种方式其实也可以用在传统关系数据库,阿里、微信团队等也有将MySQL存储改造支持paxos多副本的,MySQL也推出了官方版MySQL Group Cluster,预计不远的未来主从模式可能就成为 历史 了。
需要注意的是很多NewSQL数据库厂商宣传基于paxos或raft协议可以实现【异地多活】,这个实际上是有前提的,那就是异地之间网络延迟不能太高 。以银行“两地三中心”为例,异地之间多相隔数千里,延时达到数十毫秒,如果要多活,那便需异地副本也参与数据库日志过半确认,这样高的延时几乎没有OLTP系统可以接受的。
数据库层面做异地多活是个美好的愿景,但距离导致的延时目前并没有好的方案。 之前跟蚂蚁团队交流,蚂蚁异地多活的方案是在应用层通过MQ同步双写交易信息,异地DC将交易信息保存在分布式缓存中,一旦发生异地切换,数据库同步中间件会告之数据延迟时间,应用从缓存中读取交易信息,将这段时间内涉及到的业务对象例如用户、账户进行黑名单管理,等数据同步追上之后再将这些业务对象从黑名单中剔除。由于双写的不是所有数据库操作日志而只是交易信息,数据延迟只影响一段时间内数据,这是目前我觉得比较靠谱的异地度多活方案。
另外有些系统进行了单元化改造,这在paxos选主时也要结合考虑进去,这也是目前很多NewSQL数据库欠缺的功能。
Scale横向扩展与分片机制
paxos算法解决了高可用、高可靠问题,并没有解决Scale横向扩展的问题,所以分片是必须支持的。NewSQL数据库都是天生内置分片机制的,而且会根据每个分片的数据负载(磁盘使用率、写入速度等)自动识别热点,然后进行分片的分裂、数据迁移、合并,这些过程应用是无感知的,这省去了DBA的很多运维工作量。以TiDB为例,它将数据切成region,如果region到64M时,数据自动进行迁移。
分库分表模式下需要应用设计之初就要明确各表的拆分键、拆分方式(range、取模、一致性哈希或者自定义路由表)、路由规则、拆分库表数量、扩容方式等。相比NewSQL数据库,这种模式给应用带来了很大侵入和复杂度,这对大多数系统来说也是一大挑战。
这里有个问题是NewSQL数据库统一的内置分片策略(例如tidb基于range)可能并不是最高效的,因为与领域模型中的划分要素并不一致,这导致的后果是很多交易会产生分布式事务。 举个例子,银行核心业务系统是以客户为维度,也就是说客户表、该客户的账户表、流水表在绝大部分场景下是一起写的,但如果按照各表主键range进行分片,这个交易并不能在一个分片上完成,这在高频OLTP系统中会带来性能问题。
分布式SQL支持
常见的单分片SQL,这两者都能很好支持。NewSQL数据库由于定位与目标是一个通用的数据库,所以支持的SQL会更完整,包括跨分片的join、聚合等复杂SQL。中间件模式多面向应用需求设计,不过大部分也支持带拆分键SQL、库表遍历、单库join、聚合、排序、分页等。但对跨库的join以及聚合支持就不够了。
NewSQL数据库一般并不支持存储过程、视图、外键等功能,而中间件模式底层就是传统关系数据库,这些功能如果只是涉及单库是比较容易支持的。
NewSQL数据库往往选择兼容MySQL或者PostgreSQL协议,所以SQL支持仅局限于这两种,中间件例如驱动模式往往只需做简单的SQL解析、计算路由、SQL重写,所以可以支持更多种类的数据库SQL。
SQL支持的差异主要在于分布式SQL执行计划生成器,由于NewSQL数据库具有底层数据的分布、统计信息,因此可以做CBO,生成的执行计划效率更高,而中间件模式下没有这些信息,往往只能基于规则RBO(Rule-Based-Opimization),这也是为什么中间件模式一般并不支持跨库join,因为实现了效率也往往并不高,还不如交给应用去做。
存储引擎
传统关系数据库的存储引擎设计都是面向磁盘的,大多都基于B+树。B+树通过降低树的高度减少随机读、进而减少磁盘寻道次数,提高读的性能,但大量的随机写会导致树的分裂,从而带来随机写,导致写性能下降。NewSQL的底层存储引擎则多采用LSM,相比B+树LSM将对磁盘的随机写变成顺序写,大大提高了写的性能。不过LSM的的读由于需要合并数据性能比B+树差,一般来说LSM更适合应在写大于读的场景。当然这只是单纯数据结构角度的对比,在数据库实际实现时还会通过SSD、缓冲、bloom filter等方式优化读写性能,所以读性能基本不会下降太多。NewSQL数据由于多副本、分布式事务等开销,相比单机关系数据库SQL的响应时间并不占优,但由于集群的弹性扩展,整体QPS提升还是很明显的,这也是NewSQL数据库厂商说分布式数据库更看重的是吞吐,而不是单笔SQL响应时间的原因。
成熟度与生态
分布式数据库是个新型通用底层软件,准确的衡量与评价需要一个多维度的测试模型,需包括发展现状、使用情况、社区生态、监控运维、周边配套工具、功能满足度、DBA人才、SQL兼容性、性能测试、高可用测试、在线扩容、分布式事务、隔离级别、在线DDL等等,虽然NewSQL数据库发展经过了一定时间检验,但多集中在互联网以及传统企业非核心交易系统中,目前还处于快速迭代、规模使用不断优化完善的阶段。
相比而言,传统关系数据库则经过了多年的发展,通过完整的评测,在成熟度、功能、性能、周边生态、风险把控、相关人才积累等多方面都具有明显优势,同时对已建系统的兼容性也更好。
对于互联网公司,数据量的增长压力以及追求新技术的基因会更倾向于尝试NewSQL数据库,不用再考虑库表拆分、应用改造、扩容、事务一致性等问题怎么看都是非常吸引人的方案。
对于传统企业例如银行这种风险意识较高的行业来说,NewSQL数据库则可能在未来一段时间内仍处于 探索 、审慎试点的阶段。基于中间件+分库分表模式架构简单,技术门槛更低,虽然没有NewSQL数据库功能全面,但大部分场景最核心的诉求也就是拆分后SQL的正确路由,而此功能中间件模式应对还是绰绰有余的,可以说在大多数OLTP场景是够用的。
限于篇幅,其它特性例如在线DDL、数据迁移、运维工具等特性就不在本文展开对比。
总结
如果看完以上内容,您还不知道选哪种模式,那么结合以下几个问题,先思考下NewSQL数据库解决的点对于自身是不是真正的痛点:
如果以上有2到3个是肯定的,那么你可以考虑用NewSQL数据库了,虽然前期可能需要一定的学习成本,但它是数据库的发展方向,未来收益也会更高,尤其是互联网行业,随着数据量的突飞猛进,分库分表带来的痛苦会与日俱增。当然选择NewSQL数据库你也要做好承担一定风险的准备。
如果你还未做出抉择,不妨再想想下面几个问题:
如果这些问题有多数是肯定的,那还是分库分表吧。在软件领域很少有完美的解决方案,NewSQL数据库也不是数据分布式架构的银弹。相比而言分库分表是一个代价更低、风险更小的方案,它最大程度复用传统关系数据库生态,通过中间件也可以满足分库分表后的绝大多数功能,定制化能力更强。 在当前NewSQL数据库还未完全成熟的阶段,分库分表可以说是一个上限低但下限高的方案,尤其传统行业的核心系统,如果你仍然打算把数据库当做一个黑盒产品来用,踏踏实实用好分库分表会被认为是个稳妥的选择。
很多时候软件选型取决于领域特征以及架构师风格,限于笔者知识与所属行业特点所限,以上仅为个人粗浅的一些观点,欢迎讨论。
为什么PostgreSQL比MongoDB还快
PostgreSQL9.4带来了全新的NoSQL特性,并且根据EnterpriseDB的测试,其加载,插入和查询的性能都已经几倍于MongoDB了。
虽然我是PG的铁杆粉丝,但是关系数据库背负了ACID的重型装甲,在性能上居然能打败轻装上阵的NoSQL数据库总觉得有点离谱。
所以我在自己的环境里验证了一下EnterpriseDB的测试结果,并且小探一下PG取胜的原因。
1. EnterpriseDB的测试结果
以下是EnterpriseDB的测试结果(数据量为5000万)
(还可以参考这篇译文: )
2. 我的验证结果
测试观点
为了使测试结果更加单纯,我准备单纯比拼CPU消耗(尽量排除IO和网络的干扰),设定以下测试条件。
1)所有数据都要放进内存
2)C/S都跑在同一台单机上
所以,只在单机上进行10万条小数据量的测试。
注)EnterpriseDB的测试环境是32G内存的Amazon Web Services M3.2XLARGE实例,总数据量超过内存了。
测试环境
测试环境为个人PC上的VMware虚拟机
PC
CPU:Intel Core i5-3470 3.2G(4核)
MEM:6GB
SSD:OCZ-VERTEX4 128GB(VMware虚拟机所在磁盘,非系统盘)
OS:Win7
VMware虚拟机
CPU:4核
MEM:1GB
OS:CentOS 6.5
PG:PostgreSQL 9.4.0(shared_buffers = 428MB,其他是默认值)
MG:MongoDB 3.0.2
测试步骤
测试步骤非常简单,可以参考:
但是,在测试前,有些东西要改。
1)把数据量减小到10万
pg_nosql_benchmark-master/pg_nosql_benchmark:
declare -a json_rows=(10000000)
==
declare -a json_rows=(100000)
2)修改mongo的一处脚本(注)
pg_nosql_benchmark-master/lib/mongo_func_lib.sh:
collectionsize="$(echo ${output}|awk -F"," '{print $5}'|cut -d":" -f2)"
==
collectionsize="$(echo ${output}|awk -F"," '{print $6}'|cut -d":" -f2)"
注)pg_nosql_benchmark原来是基于MongoDB 2.6设计的,MongoDB 3.0的db.json_tables.stats()输出可能变了,所以这边要修改一下。
Renix Perf IP网络性能测试工具及测试用例参数详解
1.1基于软件的网络及应用服务性能测试工具
双臂测试
单臂测试
1.2通过测试端点产生网络流量对网络性能进行测量
TCP、UDP、PING
语音、视频、HTTP、FTP、MAIL、组播
1.3测试端点软件可以免费安装部署
局域网公网
2.1控制端(TestConsole)
●安装于Windows7(64位)
●4核CPU,8GB内存以上
150GB硬盘
2.2测试端点(TestPoint)
●软件测试端点支持Linux、Windows、Android、VxWorks、各种国产OS
●硬件测试端点
3.1专有硬件盒子
3.2支持的OS
Windows;Linux;Android;国产OS
3.3支持的CPU架构x86;PCPU;ARM;MIPS;Alpha
3.4网络接口 以太网;WiFi;3G、4G、5G
真实的协议栈,有状态的Layer3-7应用流量的产生和分析
测试端点支持计算平台广泛,支持高效的客户定制化开发
支持大数据量存储,超长时间的不间断测试
Windows控制端、SQL及NoSQL数据存储
运行于64位 Windows测试管理测试端点资源;测试端点映射;测试用例测试报告
TestPoint输入测试控制端IP运行后注册到测试控制端显示每个TestPoint主机名、IP等信息
创建逻辑(虚拟)测试端点
将测试端点资源中测试端点映射到逻辑测试端点
测试资源与测试配置解耦合
测试配置可分享
无真实测试端点可预先做测试配置
更换测试端点后,无需重新再配置
定义测试用例名称与测试时长用例依次串行方式执行
测试链路配置协议,测试端点1和测试端点2,以及协议参数
1.1通过PC或者手机的WLAN接口包围无线CPE,TestPoint产生流量执行CPE性能测试,
1.2常见测试项目:
无线基准性能测试
无线衰减测试
天线方向性测试
无线信道测试
信道竞争测试
无线并发测试
无线远近距离测试
稳定性测试
环境适应性测试
2.1 在虚拟化平台的VM中部署TestPoint,测试vSwitch的交换性能
2.2常见测试指标:吞吐量;时延;丢失率;乱序
3.1在服务器不同类型OS中部署TestPoint,通过多对一的方式测试服务器网络性能
3.2常见测试指标:吞吐量TCP业务交易速率\交易时间UDP业务交易速率\交易时间
在网络端到端两头部署TestPoint,通过一对一的方式测试网络的承载指标常见测试指标:TCP\UDP吞吐量;单向延迟;抖动;乱序
新闻标题:nosql性能测试,浅谈nosql技术及应用论文
本文URL:http://azwzsj.com/article/dsicgsh.html