微服务实践目录
,可以参见连接。
缓存系列包括:
1.微服务管理-11.缓存概述
1.微服务管理-11.缓存-0.技术
1.微服务管理-11.缓存-1.多级缓存设计
1.微服务管理-11.缓存-2.典型缓存架构设计
1.微服务管理-11.缓存-3.实践
[1.微服务管理-11.缓存-4.总结]()
背景
随着互联网的普及,内容信息越来越复杂,用户数和访问量越来越大,我们的应用需要支撑更多的并发量。对于一个计算机系统来说输入、输出、计算、存储都需要不断的扩展,从原来的单台机器扩展到多台机器以增强系统的输入、输出、计算、存储能力。在硬件上以多台廉价机器替换单台的昂贵服务器的趋势已经从GFS、云计算领域的兴起而不断的被应用在实践中。相对于硬件基础设施来说,软件基础设施也跟随者小型化、廉价化的趋势在不断的分裂发展。从软件基础层面上有使用分布式的方式解决输入、输出、计算、存储能力的问题。
软件基础设施方面的输入可以使用
OpenResty
这种可以高度定制化的接入服务,输出可以使用CDN、P2P这样的分发网络进行。计算可以使用微服务,分布式计算解决差异化、大批量计算的问题。存储方面的发展对于其他方面来说相对比较缓慢。近些年不断提出存储方面的特定场景解决方案:大数据存储与计算方案,NewSql的关系型存储解决方案,文档型存储解决方案等。但业内对于非关系型数据库的研究与应用还是处于不是很稳定的阶段,菲关系型数据库一方面解决存储性能的问题,一方面有被CAP所限制。所以出现了BASE这种对CAP进行权衡的方式。
从存储的基本理论(ACID,CAP,BASE)可以得出存储的可伸缩性、性能等方面是有理论约束的。不能将系统所要求的并发量、响应时间等压在数据库的能力上,所以缓存技术再一次被提上桌面。
数据库每秒能接受的请求次数也是有限的(或者文件的读写也是有限的),但是我们不可能把我们的持久化技术不不实用数据库。所以,如何能够有效利用有限的资源来提供尽可能大的吞吐量?就成为数据库在软件系统中的最主要责任。一个有效的办法就是引入缓存,打破标准流程,每个环节中请求可以从缓存中直接获取目标数据并返回,从而减少计算量,有效提升响应速度,让有限的资源服务更多的用户。
技术对比
我们这里讨论的缓存技术是针对数据管理与数据存储方面的技术。不包括像浏览器缓存,cdn缓存,nginx缓存这样的技术。从这个角度说,所有的内存式数据库都可以作为缓存使用。下图为google查询缓存技术的趋势图:
在缓存技术刚出现的那几年,memcache和redis是不相上下的。后来redis异军突起,其他的缓存技术已经不可与redis同日而语。但对于技术来说,不同的技术有不同的侧重点有自己所适用的场景。所以对于每项技术都需要有一些了解。
对于缓存技术有一些通用的特性,还有一些自己的特点。所以本文会从通用的角度对比几个现在可以看到的,会从不同的方面进行对比。具体指标有:客户端,分布式支撑,命中率,最大元素数,换入换出策略,数据类型,持久化,监控管理,缓存穿透支持,标准规范(JSR-107 JAVA缓存规范)
Redis
是一个开源(BSD许可)的内存数据结构存储,用作数据库、缓存和消息代理。它支持数据结构,如字符串、哈希、列表、集合、带范围查询的排序集合、位图、超日志、带半径查询的地理空间索引和流。Redis具有内置的复制、Lua脚本、LRU逐出、事务和不同级别的磁盘持久性,并通过Redis Sentinel和带有Redis集群的自动分区提供高可用性。
Redis能读的速度是110000次/s,写的速度是81000次/s 。Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。Redis还支持 publish/subscribe, 通知, key 过期等等特性。可以使用命令行进行非常容易的操作。Redis支持Lua脚本扩展功能。
key-value型,远程服务。
多种宿主语言客户端支持,客户端还可以支持JSR-107标准。可以参见:
https://redis.io/clients
Redis最大支持的Key大小、Value大小都为512MB。最多可以建立2^32个key,经过实践测试,每个实例至少可以处理2.5亿个key。每个hash,list,set和sort set都可以容纳2^32个元素。可以参见:
https://redis.io/topics/data-types-intro
https://redis.io/topics/faq
支持String、Hash、List、Set、Sorted Set、Geo、Stream、HyperLogLog。每种都可以有多种用法。
Redis支持三种持久化方式:AOF,RDB,禁止持久化。可以参见:
https://redis.io/topics/persistence
换出策略支持多种:lru,lfu,fifo。可以参见:
https://redis.io/topics/lru-cache
Redis原生支持多种监控方式。可以使用redis-cli中的monitor,info,time命令行参数可以获取信息。从命令上可以获得多种类型的原始数据包括很多redis的指标型数据。还有多种类型的界面化监控软件Prometheus--redis_exporter,RedisLive等都可以很好的满足监控的要求。
redis本身是未支持的缓存穿透与缓存同步的功能,需要使用第三方组建完成。可以使用阿里的canal。
Redis支持复制(replication)、Sentinel 和集群(cluster)三个多机功能。可以支持一致性Hash算法进行数据的分片工作。
Memcached
是免费开放源代码、高性能、分布式内存对象缓存系统,本质上是通用的,但旨在通过减轻数据库负载来加速动态web应用程序。Memcached是内存中的键值存储,用于存储数据库调用、API调用或页面呈现结果中的任意小块数据(字符串、对象)。Memcached简单但功能强大。它的简单设计促进了快速部署,易于开发,并解决了大型数据缓存面临的许多问题。它的API可用于大多数流行语言。
Memcached 是单进程多线程的工作模式,请求到达时,主线程会将请求分发给多个工作线程,因此必须要做数据的互斥。memcached每秒可以轻松处理200,000+个请求。使用libevent提供事件驱动能力。资料比较难找。
key-value型,远程服务。
多种宿主语言客户端支持。
Memcached单个key-value大小有限,一个value最大只支持1MB。MemCache中可以保存的item数据量是没有限制的,只要内存足够。MemCache单进程在32位机中最大使用内存为2G,这个之前的文章提了多次了,64位机则没有限制。
支持String,Object类型
MemCached不支持数据持久化,断电或重启后数据消失,但其稳定性是有保证的。
memcache使用命令stats可以得到很多监控信息。界面化的监控工具有open-falcon,memcachephp可以使用。
memcache本身是未支持的缓存穿透与缓存同步的功能,需要使用第三方组建完成。可以使用阿里的canal。
各个memcached服务器之间互不通信,各自独立存取数据,不共享任何信息。服务器并不具有分布式功能,分布式部署取决于memcache客户端。
etcd
是一个分布式键值对存储,设计用来可靠而快速的保存关键数据并提供访问。通过分布式锁,leader选举和写屏障(write barriers)来实现可靠的分布式协作。etcd集群是为高可用,持久性数据存储和检索而准备。
您的应用程序可以读取数据并将数据写入etcd。一个简单的用例是将数据库连接细节或特性标志作为键值对存储在etcd中。这些值可以被监视,允许应用程序在更改时重新配置自身。高级使用利用etcd的一致性保证来实现数据库领导人选举或跨工作集群执行分布式锁定。
etcd提供了leader选举、分布式时钟、分布式锁、持续监控(watch)和集群内各个成员的liveness监控等功能。zookeer虽然也实现了类似的功能,但是不方便易用,还需借助Netflix提供的Apache Curator库。
etcd比较多的应用场景是用于服务发现。etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现。安装配置简单,而且提供了HTTP API进行交互,使用也很简单。根据官方提供的benchmark数据,单实例支持每秒2k+读操作。
key-value型,远程服务。
多种宿主语言客户端支持。可以参见:
https://etcd.io/docs/v3.4.0/integrations/
etcd旨在处理典型的元数据小键值对。默认情况下,任何请求的最大大小为1.5 MiB。 可以通过etcd服务器的--max-request-bytes标志配置此限制。默认的存储大小限制为2GB,可使用--quota-backend-bytes标志进行配置。 建议在正常环境下使用8GB的最大大小。可以参见:
https://github.com/etcd-io/etcd/blob/master/Documentation/dev-guide/limit.md
因为使用http api的方式进行数据管理,所以对于数据类型的直接支持就只有String类型。
Etcd 就会在默认的工作目录下生成两个子目录:snap 和 wal。两个目录的作用说明如下。
snap:用于存放快照数据。Etcd 为防止 WAL 文件过多会创建快照,snap 用于存储 Etcd 的快照数据状态。
wal:用于存放预写式日志,其最大的作用是记录整个数据变化的全部历程。在 Etcd 中,所有数据的修改在提交前,都要先写入 WAL 中。使用 WAL 进行数据的存储使得 Etcd 拥有故障快速回复和数据回滚这两个重要功能。
etcd因为它的k8s体系的原因,可以直接使用
Prometheus
进行监控。并且为其提供了完整的指标体系。可以参见:
https://etcd.io/docs/v3.4.0/metrics/
主要针对服务发现场景,所以这方面的考虑应该较少。因为我没有找到etcd关于这方面的资料。
集群方式类似与zookeeper。
H2
是一个Java编写的关系型数据库,它可以被嵌入Java应用程序中使用,或者作为一个单独的数据库服务器运行。H2数据库的前身是HypersonicSQL,它的名字的含义是 Hypersonic2,但是它的代码是从头开始编写的,没有使用HypersonicSQL或者HSQLDB的代码。
H2 Database是一个开源的嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2 Database提供了一个十分方便的web控制台用于操作和管理数据库内容。H2 Database还提供兼容模式,可以兼容一些主流的数据库,因此采用H2 Database作为开发期的数据库非常方便。
RDBMS,内嵌,本地。
因为h2使用java编写的内嵌式数据库,所以对于java的支持,或jvm上语言支持较好。
基本支持所有的sql数据类型。
支持单个文件独立存储。
提供界面化操作。
未知。
支持集群。可以参见:
http://www.h2database.com/html/advanced.html#clustering
Guava
是google的一个开源java框架。guava工程包含了若干被Google的 Java项目广泛依赖的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。 所有这些工具每天都在被Google的工程师应用在产品服务中。
Guava Cache是在内存中缓存数据,相比较于数据库或redis存储,访问内存中的数据会更加高效。Guava官网介绍,下面的这几种情况可以考虑使用Guava Cache:愿意消耗一些内存空间来提升速度。预料到某些键会被多次查询。缓存中存放的数据总量不会超出内存容量。
key-value型,内嵌,本地。
java以及JVM上语言。
未找到最大实际测试数据。但是有文章说可能会造成oom的问题。GuavaCache支持四种回收方式: (1)基于容量回收(Size-based Eviction);(2)基于时间回收(Timed Eviction);(3)基于引用类型的回收Reference-based Eviction);(4)手动回收。 4. 它可以监控加载/命中情况。
java本身所有的数据类型都可以支持。
Guava Cache不持久化数据。
不支持。CacheBuilder.recordStats()用来开启Guava Cache的统计功能。
未支持。
需要自己实现。
Caffeine
使用的是一个内存缓存,是基于Google 的 Guava与ConcurrentLinkedHashMap进行实现的。Caffeine是一个开源的Java缓存库,它能提供高命中率和出色的并发能力。
Caffeine提出了《
设计一个现代的缓存
》,这样的现代化缓存架构。在文章中Caffeine使用Caffeine设计的
Window TinyLfu
作为回收策略,TinyLfu算法提供了一个近乎最佳的命中率。
key-value型,内嵌,本地。
支持JSR-107标准。可以与Spring Cache集成使用。
无相关数据。
java本身所有的数据类型都可以支持。
无相关数据。
缓存访问统计功能。
未支持。
未支持。
Ehcache
是一个开源的、基于标准的缓存,它可以提高性能、减轻数据库负载并简化可伸缩性。它是使用最广泛的基于Java的缓存,因为它健壮、可靠、功能齐全,并且与其他流行的库和框架集成。Ehcache可以从进程内缓存扩展到进程内/进程外混合部署和太字节大小的缓存。
Ehcache是一个纯java的进程内缓存框架,具有快速、精干的特点。是hibernate默认的cacheprovider。支持REST和SOAP api等特点。
key-value型,内嵌,本地。
Java或者Jvm上语言。可通过RMI、可插入APi等方式进行分布式缓存。
通过参数配置。
java本身所有的数据类型都可以支持。
可以持久化到硬盘上。
Ehcache最初是由Greg Luck于2003年开始开发。2009年,该项目被Terracotta购买。软件仍然是开源,但一些新的主要功能只能在商业产品中使用,其中主要的产品有Big MemoryGo, Big Memory Max, Enterprise Ehcache.其官网有介绍
http://www.terracotta.org/products/
可以使用j2cache进行二级缓存设置。
使用Terracotta进行集群处理。
Hazelcast
全称是Hazelcast IMDG (In-Memory Data Grid),内存数据网格。新的支持数据的应用程序可以提供变革性的业务能力——如果它们满足当今的即时性要求的话。Hazelcast平台允许您通过跨计算机集群访问可扩展的共享RAM池来构建最快的应用程序。
Hazelcast是由Hazelcast公司开发和维护的开源产品,可以为基于jvm环境运行的各种应用提供分布式集群和分布式缓存服务。
Key-Value型,本地/远程。
java本身所有的数据类型都可以支持。
无数据。
java本身所有的数据类型都可以支持。
支持3种持久化策略,Read-Through、Write-Through和Write-Behind。
未找到相关资料。
可以使用j2cache进行二级缓存设置。
支持Coherence和Terracotta。
Apache Ignite
内存数组组织框架是一个高性能、集成和分布式的内存计算和事务平台,用于大规模的数据集处理,比传统的基于磁盘或闪存的技术具有更高的性能,同时他还为应用和不同的数据源之间提供高性能、分布式内存中数据组织管理的功能。
Ignite来源于尼基塔·伊万诺夫于2007年创建的GridGain系统公司开发的GridGain软件,尼基塔领导公司开发了领先的分布式内存片内数据处理技术-领先的Java内存片内计算平台,今天在全世界每10秒它就会启动运行一次。他有超过20年的软件应用开发经验,创建了HPC和中间件平台,并在一些创业公司和知名企业都做出过贡献,包括Adaptec, Visa和BEA Systems。尼基塔也是使用Java技术作为服务器端开发应用的先驱者,1996年他在为欧洲大型系统做集成工作时他就进行了相关实践。
2014年3月,GridGain公司将该软件90%以上的功能和代码开源,仅在商业版中保留了高端企业级功能,如安全性,数据中心复制,先进的管理和监控等。2015年1月,GridGain通过Apache 2.0许可进入Apache的孵化器进行孵化,很快就于8月25日毕业并且成为Apache的顶级项目,9月28日即发布了1.4.0版,应该说发展、迭代速度非常之快。该技术相关资料较少,但确是一个很有潜力的技术,解决了大规模、大数据量、高并发企业级或者互联网应用面临的若干痛点。
Spark是一个和Ignite类似的项目。但是Spark聚焦于OLAP,而Ignite凭借强大的事务处理能力在混合型的OLTP/ OLAP场景中表现更好。特别是针对Hadoop,Ignite将为现有的Map/Reduce,Pig或Hive作业提供即插即用式的加速,避免了推倒重来的做法,而Spark需要先做数据ETL,更适合新写的分析应用。
Key-Value型,本地/远程。
使用语言api和rest api进行操作。
PB级数据
java本身所有的数据类型都可以支持。
持久化到磁盘。
自身就支持监控。
使用j2cache进行缓存穿透。
自身支持集群。
LevelDB
是一个由Google编写的快捷键值存储库,它提供了从字符串键到字符串值的有序映射。2013年Facebook基于LevelDB开发出RocksDB,特别针对服务器负载而优化。
LevelDB 只是一个 C/C++ 编程语言的库, 不包含网络服务封装, 所以无法像一般意义的存储服务器(如 MySQL)那样, 用客户端来连接它. LevelDB 自己也声明, 使用者应该封装自己的网络服务器.
key-value型,远程。
需要自行封装。
LevelDB 是单进程的服务,性能非常之高,在一台4核Q6600的CPU机器上,每秒钟写数据超过40w,而随机读的性能每秒钟超过10w。 此处随机读是完全命中内存的速度,如果是不命中速度大大下降。
LevelDB底层存储利用了LSM tree的思想, RocksDB是Facebook基于LevelDB开发的存储引擎,针对LevelDB做了很多优化,但是大部分模块的实现机制是一样的。
未找到相关资料。
未找到相关资料。
leveldb是google开源的单机key-value存储引擎。
Tair
是快速访问内存(MDB)/持久性(LDB)存储服务。Tair采用高性能、高可用的分布式集群体系结构,能够满足企业对读写性能和可扩展容量的高要求。
一个 Tair 集群主要包括3个必选模块:ConfigServer、Dataserver和 Client.
key-value型,远程。
Java
资料不全。
java本身所有的数据类型都可以支持。
Tair 的存储引擎有一个抽象层,只要满足存储引擎需要的接口,便可以很方便地替换 Tair 底层的存储引擎。比如你可以很方便地将 bdb、tc 甚至 MySQL 作为 Tair 的存储引擎,而同时使用 Tair 的分布方式、同步等特性。
资料不全。
资料不全。
本身就是分布式的。
总结
缓存技术有很多中,但是每个缓存技术都有自己的特点。最强大的是Apache Ignite把缓存做成了Cache as a Service(CaaS) 缓存即服务。下来就是几个独立的缓存数据库:alibaba tair,redis,memcache,etcd。内嵌式的缓存有Hazelcast,Ehcache,Guava Cache,H2 Database。在这些技术中还有两种可以支持IMGD (In-Memory Data Grid内存数据网格)的两种Apache Ignite,Hazelcast。Apache Ignite还可以支持网格计算的缓存。Apache Ignite还有
苏宁 11.11:基于 Apache Ignite 日均十亿数据对账实践应用
这样的实践应用。
不要将所有的压力、吞吐都压在数据库上,因为数据库理论上是有限制的。其他还有像zookeeper,mysql memory database,sqlite3,Berkeley DB服务可以作为缓存使用。
参考
【分布式存储】CAP、BASE与ACID原则
Memcache,Redis,MongoDB(数据缓存系统)方案对比与分析
缓存那些事
Tair
Etcd官方文档中文版
阿里云Redis开发规范
Apache Ignite 初探
Apache Ignite中文网
Guava Cache使用介绍
etcd:从应用场景到实现原理的全方位解读
H2 Database简介
缓存篇 : Guava cache 之全面剖析
用 Terracotta 实现 Master-Worker
Hazelcast介绍和优势
Apache Ignite简介以及Ignite和Coherence、Gemfire、Redis等的比较
基于常见组件的微服务场景实战,注册发现
下面开始微服务相关内容的讲解。在这一部分中,仍然从最基础的场景入手,然后再逐步展开说明,帮助大家快速掌握一些微服务组件的实现原理,最终理解微服务架构的本质。