Submind YouTube summaries
Thumbnail for Vaultaire: a data vault for system metrics, backed onto Ceph

Vaultaire: a data vault for system metrics, backed onto Ceph

Watch on YouTube

Video summary

Vaultaire emerged as a specialized data vault designed to store raw system metrics backed by the scalable storage capabilities of Ceph, addressing significant limitations found in traditional time-series databases like Graphite. The project was driven by a need for full-resolution raw data points rather than averaged or smoothed derivatives, which are often insufficient for modern analytics. To overcome local disk constraints and leverage horizontal scaling without managing filesystem growth complexities, the system adopted an object storage approach where initial designs relied on immutable data points and idempotent writes to gracefully handle network failures through sorting and deduplication during reads rather than complex write-side coordination. The development journey involved overcoming severe performance bottlenecks caused by variable-length Protobuf serialization overhead and excessive garbage collection in Haskell when processing large volumes of key-value pairs, alongside Ceph's challenges with high-concurrency writes that could grind the system to a halt under heavy replication loads. To resolve these issues, the architecture was refined through deterministic addressing based on source hashes, bucket sharding strategies to distribute write load dynamically, and an optimized custom binary format inspired by high-frequency trading practices that reduced payload sizes significantly. These enhancements allowed Vaultaire to successfully process terabytes of metric data from Anchor Systems while supporting extended payloads for complex logs alongside simple metrics. In production environments utilizing OpenStack with RBD, Vaultaire demonstrated robustness in handling node failures and network conflicts without losing a single accepted data point over ten months of operation. The system intelligently manages Ceph OSD outages by marking nodes as missing before cascading data to peers if unresponsiveness persists beyond a configurable threshold, prioritizing consistency even when network issues like InfiniBand memory allocation fights cause packet loss that might falsely declare machines dead. To further enhance performance for analytics and real-time modeling, the implementation employs a three-tier caching strategy keeping recent live data in RAM, caching billing-related usage, and accelerating bulk reads while preserving other traffic patterns to handle corner cases effectively. Although not yet fully open-source, Vaultaire has attracted external contributors who have built visualization consumers and integrated decision tree models to correlate HTTP server failure modes with Ceph metrics. The system represents a mature solution that balances the need for high throughput and data integrity against the complexities of distributed storage systems, proving that careful architectural adjustments can solve early prototype limitations while maintaining safety during infrastructure incidents. Ultimately, Vaultaire stands as a testament to leveraging robust engineering in underlying technologies like Ceph to create reliable platforms capable of handling massive datasets without compromising on consistency or availability under adverse conditions.
Read the full video transcript
so most of us have been living the dream staring and graphs looking like this for the better part of the last 15 years and one of the problems with systems metrics is presented by our Rd is that they're kind of it's taking up an awful lot of screen real estate to not tell you very much this is you know a scale or number eight servers in this cluster but the you know there's there's all this you know logic to work out averages and transitions over time one of the things that goes into the core of the way the argue was designed was that once upon a time disk space was expensive or released a very limited resource and so we couldn't just record all this system data ever and keep around forever because we would exhaust our disks so what was built into the system was something that would compact over time that you would set a policy it would retain data at a high resolution for an hour and then it would average it down and compact it so that it we then maintained a five-minute type average for a week and then compacted again at a month and year and so on with the result that you had a constant size database you could at the moment you initialize the database know exactly how big that file on disk would ever be and thus managers were saying this was a good thing for system is once upon time the trouble is that it's a little malossi side we had an event where apparently we had 7.8 servers in the cluster and and that's obviously a result of averaging it's moving right and it's a side effect of of this dis kind of storage mechanism the so the question is can we do something about that I would like to build a system that doesn't that keeps the data because the challenge that we have is if we want to do analytics of any form on data in the present using proper mathematical mathematical models you need to give those models all the points you can't pre smooth them you can't average them you need to give the raw data to the people doing the math because it's an analytics decision whether or not to throw away data and it shouldn't be won in the storage system so we need to store all the data at raw at its source resolution we want to give that data in its original form not derivatives this is something that it's kind of clued into this ISM in community a few years back Jimmy Wilkinson speaks very eloquently about this but we don't want to calculate rates it's very tempting to store first derivatives in your systems database but you end up doing it wrong basically whose idea of time are you using what you know how many points went into a system if you're talking about events and you're sampling that to once per second or something like that you're throwing a huge amounts of data potentially especially when we're looking for anomalies and it's the little transitions there actually end up being really significant so we want to store a raw data points not first derivatives and the biggest thing of all is that I don't want to worry about this space on the one hand no it's not our deal and anymore and all hail to Tobey but you know we can expand accept it at you we now deal with problems like customers with hundred gigabyte MySQL databases in a single table and wondering why things don't work or 27 terabyte manifest systems we won't talk with that the the thing is is that I want a system where I don't have to worry about whether the file system is getting too big or how am I going to grow this MySQL database or Postgres database I'd like something that would just scale horizontally without me needing to worry about it and you know it would be nice if it was fault tolerant you know I mean maybe I'm asking for too much here but so I turned to Seth at anchor we had an SF cluster we've been hearing about stuff for some year from monitors from sage here at the conference and just even before I joined the firm they had already set up as an experimental stuff cluster I'm like hey this is terrific I'm pretty enthusiastic what's up it's good to see that you guys are - let's use it the those of you know many of you be familiar with stuff but some some aren't if you have worked with or you can just learn to its f chances are you've worked with one of these three things ratos GW which is s3 or swift compatible front-end because you HTTP access to objects the we're the place where cefalu attraction was RBD a block device that's backed on to on to SEF and this power is virtual machines in quite a number of organizations and it's it's fantastic because it means that the virtual that the water the walk image is behind a VM don't have to be co-located as local storage with machine so it means that the whole problem of local storage and worrying about how to get that local storage to another machine when trying to do migration is just evaporates because it's all effectively networked back storage which gives pretty good management efficiencies that's actually all secondary to the real point that stuff was created which was that the original goal was to create a better clustered file system and it's called sefa fess and really all the work that has been done in the last decade since they first started was trying to put in place a really solid reliable object store to be the backing store behind this file system and that'll come up again a bit later what most people don't tend to see is that all of this is built on top of a library called liberate O's and this is a client code that talks across the network to the storage cluster to get things to happen and for a while now we've been wondering you know can you actually program against liberate O's directly it was sort of suggested by people talking on behalf of the Ceph project that yes you can use the API directly but what does that actually involve was that practical or was that just sort of a nice idea that wouldn't really ever come ever come to say anything ray dos is this it's a reliable autonomic distributed object store which is one of those names that at first glance looks really ugly turned it to mean something but in the end you don't care because an object is its own best description so here's the picture that has been seen ad nauseam and in Ceph talks but again is for anybody doesn't know what store is you've got lots of machines a few machines that are designated as monitors to enforce quorum and otherwise just a large number of machines each of which have spinning disks one of the things it's a little different about an object store in this model is that every single disk spinning disk has a process in front of it called an object storage daemon and that they work independently so the fact that to overseas might be in the same chassis is kind of irrelevant they don't have anything to do with each other their individual processes so you managed you don't build raid arrays on machines you just manage individual disks which was a bit unusual after all those years we spent building raid arrays the this isn't meant to be a talked about but self but I just want to describe one more thing about it which is that it has a very elegant placement algorithm which works out that you specify as a policy where things go the point is to articulate the failure domains so if you have data that needs to be stored you want it to be let's say you have a data center where you've got rows and the rows are quite expensive to do in your connectome a very limited bandwidth between the rows but between inside the rows inter inter rack you've got good connectivity and you want to have a setup where let's say the power domains are that you expected maybe you'd lose power to one rack but not another I mean that's you know not necessarily what your data center would be but it's a possible failure to set up and so you would articulate a question which says that I want to pick from any one row to pick a row and then find me three racks with one server per rack and one disk each of those servers and that way you've got if you want three copies of the data and that way you've got that data spread across different failure domains and this is the kind of thing that crush is really good at now that kind of tree layout isn't terribly exciting but the really novel part I think the part that made Ceph something that we all set up and take took note of was that this calculation is done by clients the bottleneck that was emerging circa 2005 wasn't the ability to have object demons and wasn't the ability to put lots and lots of things on them it was to locate where an object lives what machine do I talk to what disk do I talk to to get to a piece of piece of data and the original solution that was what you have index servers that would know where all the objects are became a huge bald neck it's somewhere between five hundred terabytes and petabytes and everybody was just crumbling as they tried to scale past that point SEF solution to this is to it's a pseudo-random number generator and you feed this the policy map into it and it comes out with 742 and 129 and the thing is is that you the client can make that calculation as can all the servers so when 42 dies they just crank the calculation and discover that 791 is the fourth one in that set and they now know where the third copy should be and the thing is it's not just the clients that know that all the individual demons know this too so the moment that this cluster state changes every participate in the cluster can think about oh wait a minute I've got objects I miss the tertiary for this for this particular object I now need to make sure that that one over there knows that it's now responsible for the being a tertiary copy because I've now effectively the secondary and the former second and the secondary was gone in the foreign primary yeah so that they work as if in a peer-to-peer fashion to work out to restore the level of redundancy and balanced over a large cluster this has you know some pretty nice properties so that's that's all ratos cluster so the purpose is pretty basic we gather metrics we put him in self and then later on people pull him out they do analytics to do work and then we get pretty graphs right good theory the real question is actually that I would turn to it was the final point that I'd mentioned which was how do you build a fault-tolerant system well well fault-tolerant distributed they're pretty much synonyms at this point how do you build a distributed system that's fault tolerant that they can handle something like this and it turns out that there are two properties of our data that make it a little different than traditional database because I know there's some there are some database discovers in the room and some of them are rolling their eyes already what are you talking about building another database like ours and there's not even a shortage of time-series databases I think we have a couple insights to offer one is that if you choose you can treat your data points as immutable now we're talking about system primarily the data we're gathering here systems metrics you gather the data point and that's it it's never going to change it has identity you're like but where it came from it has a time stamp associated you and a value and that's it and there will never ever be an update on that data point which was a pretty big insight because almost every database structure out there is concerned with updates and dealing with updating indexes and all the side effects that happen when you have to make changes like that we found ourselves the data set that is immutable that has the correlates very nicely with another property which is that if you want to build a system that is tolerant against failure it really helps if your operations can be idempotent because that gives you the ability to not have your credit card be charged three times right I mean this is the the core problem of the web is do not click this button twice and you know it's just it's kind of like the only thing you need to worry about because we get that right pretty much everything else falls out of it in in our case the the question was well I would like a system where I can have multiple you know you want a system where you at least one copy is written can you articulate a design where it doesn't matter if more than one copy is written the way that we did that was and oh if the final thing is do not carry any state in the system because after all there is no state except that which we make and that leads me to Voltaire which is the system we've been building the properties that they the the weights design is that we have data points being collected that the I'm not trying to enforce the universal idea of time the time is whatever time we get sent in it's just a timestamp the identity is also assigned by wherever the day is coming from Voltaire yourself doesn't care it just namespaces it and hashes it and sends it on its way on today show you a bit more about that in a moment the idempotency property this was actually I thought you know very clever and as all courts always you know I've learned enough of mountain to be you know weary whenever I have a clever is probably gonna have consequences but nevertheless it was a good idea the time and remains to be seen whether it still is in the long haul but the clever idea was rather than trying to work out that I have a point written a duplicate on write work it out on read when you're reading a whole bunch of points are gonna pull them into some kind of an or a hashmap or in order you know ordered ordered list if you've got an ordering property and timestamps are a pretty good one then it doesn't matter if I read the same point five times as I'm scanning down a block of data I can just sort that in to deduplicate by putting it into a into a set not for this case and the and while you're at it if it's a sorted set backing a sort of you know backing a map well then you get your ordering property because sooner or later this is if you need to order the data anyway but on the way and I don't need to have it ordered so suddenly I've got two things here one is it doesn't matter what order points show up in and it doesn't matter what I write them twice so that was the original design you know and I apologize this blurry but you know I sort of like fun to look back I'll be simple we'll just have points and if you think saying there'll be some kind of a bus and we'll have multiple ingestion demons absorbing stuff and then writing down to stuff which will end up in buckets and then things will come out at the other side you know that took an afternoon right and again very pleased with ourselves and that's what it looks like in production it's a lot of pieces every single one of those boxes is a different server and what sort of bring me to the point that this isn't a small system that you can go install your laptop tomorrow and I actually feel kind of bad about that but it's a large system it has the properties we're after the point that I'm talking about in terms of item potency and immutability immutability this is a characteristic of the clients generating the data data and potency property comes in because the writer demons and label the ingestion here they just take stuff that comes in whenever it comes in if there's a connection loss if a writer deem it fails if there's a network dropout if the brokers collapse the clients retransmit I mean this is your vendetta bleed everything industry systems comes down to retransmit time and you can be a long time about 10 minutes later you can get returns and it doesn't matter and patterns like well what happens if a point was written down but the acknowledgment was lost right the two journals problem well in our system we can get around that because we don't care if it's written twice and or eight times or mmm any more than that one I had real bugs so because I mean you can imagine that things go really wrong here like LAN I'll just sort of put a little teaser out there let's say that your timeout somewhere in the middle of the system is maybe 60 seconds well surely points to get written down a couple seconds if you acknowledge back right and in testing that's exactly what it looked like think about that for a minute the other thing we did is early on and I thought this was clever too and it was utterly wrong about was that we use proto bust both to encode on the transport and is the serialization format down to the wire Pro buffs are a nice way to articulate data they give you a slight scheme on top of which although in a binary encoding they if you've read if you work at a place like Google where everything is encoded in protobufs that's lovely it's I anecdotally it's used as the interface format for virtually everything there it is sometimes uses a storage format I was hoping that this would be a good way to make have different clients and different consumers agnostic about you know I was working in language that she'll be not named yet but I didn't want any of other people have to worry about that and so protobuf seemed like a good way to create that abstraction the trouble comes that a whole bunch of these fields are variable lengths and it's surprising how expensive that becomes and all the and there's two things going on here in the original design if anybody has used collecti for example you'd know that every single data point gets sent along with host slash CPU slash CPU zero and then a value you get labels like that and this can be generalized to field value pairs it could be the data center came out of and maybe something about a customer ID anything like that but you end up with these key value pairs which identify a source and although this was all very tightly what are you worrying about you know how many bytes and should be using four numerix verses or two more general types and and the the general encoding and proto bus for integers is variable length and it uses like this many bits to say whether or not it's longer and then this many bytes bits of storage and it rolls long so a small integer can be encoded three bytes whereas a larger 64-bit integer one I'm taking seven right and so the sweet spot is that you know the point is that if it's new each since you can you ship around small numbers there's no reason to pay for bytes every single bloody time you want to or eight bytes for word size to every time you want to encode to the number 12 right and so on average that work that pays off pretty well in terms of over the wire efficiency the trouble is is that frankly at this day at this point the size over the wire isn't the problem so I spend all sorts of time worrying about getting the variable encoding right and implementing all this to optimize for something that really isn't it certainly currently I maybe this will change again in a while but in a datacenter on a LAN between machines you know over the wire bandwidth is not the bottleneck that's the other thing you see here is that these field in order to articulate what is just a map of key value pairs you know it's pretty easily constructed you can see that but you're of course going to have to serialize this in and out so what we were doing was and this is the part that I thought was get would allow me to get away with creating a database without having to pay the ten a decade or two of building a full database management system was that the whole idea was to punt everything to SEF I said that that there was no state that all the pieces in the system other than let's go back to this slide everything in that system other than Insaf carries no state at all there's no statement brokers there's the only state in the clients is whether or not the pipe point has been acknowledged not so they maintain points that are in flight but everything else it gets down to SEF and that's it and so we encoded the location of points at terminus tically there's a generation tag and then the FM to xr-7 part when the name state in origin is just a digit hash of what turn emails I don't like data center an IP address the collector or something it's just a just a namespace and then a hash of the source and so what I did there was serialize out that that map so all the key value pairs which uniquely identify this host knit you know hostname 71 CPU /c p u0 and you just put that down looked into a hash function and come out with that and is the deterministic address and again and that's sort of the final driver of this was determinism the whole thing can be calculated you don't I don't need to maintain a whole index of what the address addresses were because every participant system can figure it out so and then finally a timestamp to the nearest metric day I made that up ten thousand hundred thousand seconds you know why not and and that just seems a reasonable system I mean trying to do you like work out what day it is was silly just rounding it to the nares hundred thousand was easy and that gave me names to then pass to seth and the crush hash function and and the placement group algorithms would then work out where it goes and into the system it is it goes and it's reliable it's duplicated and mirrored and that's it so that gave us a system whereby we could write arbitrary amounts of data to to SEF and pull it up again the writers didn't need to coordinate with the readers and I mentioned before the business about all that business about deduplication and not having to worry about it that with the magic that made that work is append yet idempotency if you if you're a pen safe and there's an append operation and liberate us and so once we work out the name of the bucket where it goes we just take the data point serialize it two bytes and append and if you append the same thing six times Edward doesn't matter because we sort out ordering and deduplication on read that's a good design it had some problems the burned a few things here on the first thing we burned to the ground was this after the second thing we burned to the ground were the server's writing to it South mates a few promises or not promises it just you asks you know sage would would get up in front of us and tell us that you can have an unlimited number of objects and that is more or less the case I mean unlimited is a big number but you can have the number of the knit and the namespace of objects isn't the limit so the scheme we had where we would have you know all these different objects labeled by name by namespace and hashed address and then over time partly that up wasn't a problem the size of objects they also tell us that that's unlimited and well yeah that's true they really probably should roll that back because there's this the trouble is is that are both registry WN RBD stripe their data over four megabyte chunks so when you write an object array dos GW it actually breaks it off or whatever hash scheme and then and then writes them down in order same thing with a block device it's there for mag blocks and that makes perfect sense I might well be some size and pick one the trouble is is that down in the guts of Ceph object demons they eventually end up being single threaded the concurrent system comes from its sheer mass it's it's it's lazy parallelism there are a lot of places within the system that is nothing of the sort and which is fair enough the trouble is is that one lesson is G is responding to a request it's kind of busy doing that and only that and so there are there are cases and it's it's not so much server Wes as is doing replication that there's certain operations and to be honest every time we thought we'd pin this one down we kind of figured that we were half right and found in it so getting an authoritative answer on any of this is actually a little bit tough but our impression is is there are operations that happen one at a time and so if you go and dump a 200 gigabyte object into a sect to Hungary by filing to any staffing a single object it'll take it because you know it's it's you know that it doesn't it will absorb that rights as long as there's this space out there but when it comes time to replicate that object or read it back things will kind of grind to a halt while serving that request and only that request and so it turns out to be a really good I like that we the experiments we did and this was up to the point where we became Network beyond but we found that the sweet spot was between about 400 K and 20 mix the the bottom of the curve was indeed at four Meg's so it's not a hard-coded limitation but it certainly is in the DNA of the Ceph code that form eggs is a good size for objects so if you're writing something use that size and then of course the final thing is and nobody actually promised this but I sort of have made an assumption which is pretty stupid and that was that I could just sort of blast out asynchronous there's asynchronous operations and you fire it out and they're in flight and eventually you get an acknowledgment back via a completion mechanism it's a primitive little your futures thing and that seemed all very coherent and we read through the code and all seem pretty sound and it's not that complicated it's just a straight it's actually the synchronous mechanism uses the async mechanism under the hood it's it's fine and well no and it turns out this makes sense because when you've got a block device let's say on top of SEF and you you write - I object over here I'll block over here you dirty a block and it gets flushed and so this one lights up and it's two friends get you don't have to synchronize what and then you know I'm standard operations the patterns you're over here and then you write do another block and it gets it that OSD takes the right it talks to its two peers if your application level three and they get back and they get back to you that's fine this is happening in random sarcastically over the cluster no problem the trouble in if you got a large read suddenly across a logical the continuous array then you know you might light up 12 of them at once but again it crossed a large cluster with hundreds of OS Jesus isn't a problem the trouble was is that we were finally the number objects about quarter million when we started out that represents a quarter million data points we were taking in per / / check cycle and there are sizes were fine as like I said sometimes we overdid it but in general all most of our points weren't even triggering me I'm getting past a couple hundred K in data we had allowed for some some larger higher rate ones and that would have had it's around 4 Meg's and so the trouble was is that we found that it was taking you know upwards of you know well this is large error bars on this for three and a half to five minutes per right cycle to get those quarter million points out that translates to about 2,500 operations per second it's it's ops per second that is the limitation in a theft Koster not object size not a number of objects but the rate at which you can manipulate them and it would appear the scales linearly with the number of voice T's we don't have hard numbers on that we were kind of busy you know desperately trying to sort this out it would be interesting experiment to do but you did one of those things it doesn't show up in development it's all working great but when we were launching this many points at it it would take three and a half minutes to complete now there were two problems I mentioned before about time outs well guess what happens when you've got 60 second time edits on the clients that are you know waiting for that indulging packet to come back they're like oh you must have lost my right I'll send it to you again so we got up into the tens and even maybe close to hundreds of millions right spending and it drained once we figured that out and stopped you know stop pre sending everything we were able to drain it and in a better course of a day Seth absorbed it we end up with some pretty large buckets but we were able to do it the thing was this was absolutely maxing out the cluster because I was sort of you know waving my hand resting a couple year couple year we were writing 200 s DS simultaneously now the reality is is that no matter how a distributed system is once we want to achieve concurrent consistency sooner or later you have to linearize it's a basic systems basic property of distributed systems and so underneath the hood sooner or later one ôs DS can need to talk to another OSD to establish it it's got its copy of the object it's trying to do a write on and get acknowledgment off and that other irty is busy and so you wait and so the whole thing just kind of ground halt and averaged out at the pace of around about 2,500 second right and it was not a small cluster by the way it was on the order of seven machines with on the order of 60 or 80 discs in it at the time so you know not huge but not small but the point was not to maximize the cluster I mean this was this is an internal system this is overhead I can't have this system Domino wrecking an entire production object store I need that storage for other things we had a couple of VMs back onto it as well with our BDA needs to say I was doing very bad things to the performance of those those VMs so that had to stop the other thing was happening oh dear I'm so that's v1 right copy and paste here so yes I was saying we had 2500 operations a second the other problem was the Machine writing we had to get a really big one and we were we had a 16 core machine with 32 gigs of ram in it and we were flattening it I mean I've never seen that many bars in H top over to the side cranked up I've never seen 1600 per CPU usage either and it was regularly running out of memory like a this thing was ooming and like then filling swap and moving it and gone and which of course was another reason I was losing all these rights in flight there's a right cycle I would lose a whole cycle because it was just yeah and what was going on it was it turned out that so we were working in high school we are working in high school and we were using the the standard libraries map anybody who's worked in a you know one if the languages that was where our roots are immutable language like like see we're used to tree structures being mutable and and trees tree base map structures are fantastically easy you know easy to implement or clean the implement when you can manipulate and change pointers Haskell is a language which uses immutable data when you create when you make a change to an object it creates a new one it's copy-on-write thing and that has certain properties and and you can create this by the way in Java you know I've built persistent it's called a persistent structure when you have a previous version and the next version of a strut of a data structure yeah created maybe the change you've got both now that you'd think that would be wasteful of a memory it's not because you can amortize space over time is you're only changing the nodes up to the route that are the structure that's changed which means it's actually quite cheap to store both trees and the reason that's worth doing is that when you've got a concurrent system and lots lots of threads it means that any given thread can always have a consistent correct not in progress version of that tree to work with or data structure in general which is fantastic which means that the all the problems you have about having to lock data structures in as traditional mutable program just go away I have a copy of tree you have a copy of the tree and like I can we can both iterate over them and no problem which is amazing and gives you you know if you build a system that you only point you have synchronizes the handover of the tree group between between threads so it's a phenomenal thread safety advantage and it's just sort of given in a functional programming world the problem is is that remember those field value pairs that were a map that identified a source well I each value was on the order of a hundred 50 bytes with 100 100 of which 120 of which was the this map and so I was bringing in those key value pairs building a map of that in order to which was by weight sterilized on disk in the protobuf bring it up into memory into a map in order to order it serializing and that would again in alpha or just cuz I had to make sure that through then hash encode it to then trim it down to become that address it was label all very deterministic sure but I was building up these maps and then throwing them away in fact I was you know taking something serialize building an app and then serializing EV again which was just you know I kind of silly in hindsight but it wasn't the effort of doing a building building on structure such as the problems the garbage collection we were generating tons and tons of garbage and it was took it we had to do quite a bit of performance tuning in hooray for perf top but I I was worried because it was it was seemingly correlated with the right cyclone what's going on and I was really worried the crush map calculation was was what was burning me to the ground crush wasn't even taking 1% of the CPU as advertised it has all the GC so it there were a couple ways we could have worked around that it turns out there are mutable data structures in haskell ask allows you to easily drop in a mutable state you just need to isolate it so that you can maintain the properties of the language elsewhere and we couldn't fix it that way we could've tuned the garbage collector but that really wasn't the way ahead so yes so it's but the two things so one was it like this the the portable structure itself is fine but you're gonna have to bring it into your language to do something with it and virtually any language and the modern age is going to require you to do you know to convert it out of its native format that the guys who have made something called captain proto which is floating around it's actually very clever they've created a serialization format which doesn't have the variable like thing going on and is laid out any memory exactly like a structure now how you actually get structure alignment to line up with a machine you have I think that's a pretty big assumption but nevertheless the basic idea is good if you can if you're a C programmer and you've got a structure off the wire you can just drop into memory and then access as a structure that's pretty clever there's no manipulation required and a higher-level language Python and Perl on up you're going to need to turned into that languages terms which means taking the original source serialize structure and then reformatting it in internal terms and that will work that will create all this this this this fluff so there's really no avoiding that and that's what makes what was a cool idea not such a good idea ok so what we're going to do about it the changes we made were first of all deterministic addresses are like predetermined addresses excuse me you can do a deterministic calculation to get an address but I was just like you know we're 64 is pretty big we will give you an address and either you can ask the system for the next one we had an auto increment in there so if you want to guarantee next clean address or which is a an unused address we had a mechanism to go get to do a random number generator check and see if it was there which across to 64 is you know pretty good or you can calculate yourself maintaining yourself do that calculation yourself it at least was outside of the system that was happening so for example our legacy checks didn't have the way to reach back to the core system and so you know they they did that calculation and we exposed unab ility to make that you know that deterministic calculation in the library the change we made was to hash those resultant sources over 128 buckets pretty simple really it's like okay well it turns out that just writing to SEF was fine it was not a bottleneck in fact one of our sort of workarounds temporarily was just to take everything off the wire imma write it to disk right to SEF and that was glorious none of the CPUs twitched SEF didn't even notice we were dumping everything off the wire just into a cash bucket basically into a temporary bucket and it was great the machine that was picking that up and then you're falling it off according to region algorithm was burning but it sort of really Illustrated that we could taste off that wire speed and and get into SEF and and stuff we wouldn't even notice so the data volume wasn't the issue so we sort of took that idea and mutated a bit and say well any for any object source coming in figure out which bucket it goes into and and fire it in the number of buckets is a if a factor in the equation and the other is this size the time that book so it was no longer fixed to a hundred thousand seconds because one of the problems there is what happens if you got a high rate source it'll end up with you know a huge bucket whereas you know low rate sources would be the very sparse so the system adapts so that's why the timestamps here now I think as seconds are really long in hindsight or like this was done by by my colleague Christian we came up with a design on a Friday and I came on Monday you'd already done it on the weekend so I certainly wasn't gonna complain one thing I would change in hindsight is that when you do a radio snot that you want to be doing radio LS very much but if you were to if you're doing Diagnostics and you do a radio cell s on the pool that has these buckets at these objects in it this doesn't order very well it sent orders by bucket by hash slot not by timestamp and you really want to see how many you know where you know see them all together so that would be one thing I'll change in the v3 generation is just put it back so that it does list out in order nicely the other thing we changed was that there are two types of points there are simple points which are simply just words you see for values and extended ones which are arrays of bytes so we saw the ability to take in arbitrary length data because one thing we'd like to store is is web server logs having the ability to correlate systems data with what's going on a web server will be very nice and so we did one the ability of taking arbitrary strings and so that's that's what the objects look like and stuff so still a deterministic lookup like it once you conform this object you go get it and Steph gets it back to you and that's no problem the again not maintaining state the the evolution of the number of buckets in and given epoch and the side so the length of that book is Riyaz maintained in two to seven objects one for simple one for extended and that looks kind of like this and again just very simple serialization format and and the data points themselves the file change was is that we kind of work this out exactly the same time that Yaron Minsky who's the head of engineering at Jane Street capital in New York came down and gave some lectures in Sydney and he was talking about it's not directly relevant here but it's a fascinating insight it's like if you want fast code market high frequency trading fast code you can't allocate you have to use fixed size buffers you fill a buffer you process it you empty it and you refill it no allocation and that's the way to make fast code that's not for me but that's for my one of people that makes the markets work so that was a nice reinforcement of the idea we had which was it seemed to us that the way to get around it seems for a long time we avoided creating file format so we've kind of drummed into us I walked for a while there that we shouldn't create our own file formats wait a minute if you can articulate what the rules for format are and what the offsets are you just use it and so we can't with something very simple it's three words and and we have one for the address one for the timestamp fits in very nicely and the payload that's it so for every 24 bytes that's a data point that's it that's you know could we make that smaller sure but it does mean that we have the ability to we're not even doing much like a pre allocation tricks but it does mean that it's fairly compact and that comes off a wire and we just take it off the wire and write it just once we figure out where it's going and that did reading is then finding the bucket that holds that that source that it's been hashed to and then we just read the whole bucket in and scan down it it's a very fast filter operation and find out the three bytes that have the three words that have there or if you can want to real just running your friend your finger down it pull up the ones to have your source and there you go and then do the deduplication all the times so that's what goes on for the simple data points the extended data points we it comes in mush together but then when it goes out to disk we right out of sync a simple point thing includes the offset in what is just a long a pending file for where the that it is so we say okay it offset 65 300 there's then there's a length prefix and I'm in the data you know your web server long pulling or whatever and you know one of the guys they work for stresses hey can I put kind of what sound do it in there like no and hey it's happening and in fact you know I finally designed something that works I just pulled these numbers up an hour ago this is the current size of our of our production vault there are not even a million objects yet and we're running about one and a half terabytes this represents about ten months of every data metric that anchor systems has collected and for system metrics and it also now includes the last three months all the data we've collected on metering and measuring whatever the second subtree so salaah meters data is feeding in here as well and it's rolling at under 100 operations per second oscillates there are some some factors there that it's galo in but we're running about 77 operations a second and the machines aren't twitching that's 50-minute leverage on the writer and I'm pretty pleased about that it means it's it's a viable system one quick digression but back to Steph because I did say this talk was about writing staff in production there's two classes of low we're putting all that load is going into the object store but of course we're running are the nether nodes the system on on OpenStack on RBD and that in turn is running on a different staff cluster the one we just brought up for our production cloud and if you've never worked with Steph this will be a bit gibberish if you're in old stuff hand you'll recognize this but this is what Seth looks like when it's healthy there's some monitors there are it tells you something about how much disk space there is available and it says that the placement groups the modules except hashes over before sending it up to its individual machines is all happy and clean when a when single OSD is down you get something that looked might look like this it says that well I'm missing one there's only 167 168 are up and most of them are happy but the other ones are happy but they are currently being served by their peers and then it goes in other phases like it evolves from there to suddenly decides after a period of time that no it looks like that machine's not coming back so I'm going to need to worry about cascading the data on that's very clever and that if it's a reboot happening there's no reason to rebalance the whole cluster for that gif for every given object if the disk is coming back and just machine is unavailable for a little while so that's different machine being down and I machine me out and that's just by default is ten minutes but you know you really kind of you can configure that and you can also flag it to not do that if you're doing heavy clothes for maintenance but you see things like this in a fairly ordinary case it comes up with health worn as the indication but really that's probably something that we should change a bit because this is entirely nominal behavior but unfortunately is the same thing when it looks like this and I had this on the wall at work and this is this is like you know so does it Timmy's like I take a picture this yeah this is real this happened we were having some network troubles and what was happening was InfiniBand and XFS were fighting each other for the highest order of allocations and memory manager looks like we were one of the first people to hit this one but since we've heard other people squealing in pain so at least it's not just us and we've worked out some workarounds and and but the problem was ultimately that a InfiniBand would start dropping packets because XS past was trying to store to make extended attributes because anyway and so packets were getting lost and the other machine would assume that since it wasn't getting reports of health checks or a package loss it was like oh that machine must be down and so we start telling all of its friends that that machine was down even though it wasn't copes with that but this was happening on mass but then it started happening to the monitors too and so the monitors would go away which was triggering and monitored elections so you shouldn't really get an unmonitored election more than like once a month and that's just cuz it's bored we were getting a monitor election every couple minutes and needless to say the whole thing came to a screaming halt I've you know never want to see recovery Rio looking like that ever again but you know what I'll tell you something every single VM was wedged like you're sitting there pressing enter on your shells and why is nothing happening you know everything was stopped which permit available the stand point represents loss yeah we mean the other thing was down we were down in terms of any external consumer but all of the m's were safe they were just blocked SEF is a consistency store non availability one right cap theorem see AP most systems nowadays are built as a peace tourists you have lots of copies you write to it you write an update and eventually one will overwrite the other if it's last writer wins or maybe if you're really smart you build to see rdt it's the topic for another day I mean if you're not really smart you'll have a shopping cart like Amazon's that just things magically appear and disappear the but dynamo or react Sandra these are all availability stores and indeed s3s as a whole is present Esther he's great if you write to it once and look knowledge that right done just don't update anything in it well and expect to have the you know what consist an answer anytime this week which is why you don't want use s3 for backups the orders to Billa file system on anyway the I told you the beginning that SEF ray toasts the object store the entire system of all these peers talking to each other was built to be the mechanism underneath the file system a distributed file system and the semantics of every file system we've ever built has been the assumption that the the foss system code owns the blocks this is why you don't hook one drive up to two different machines and in order to build this is the hard part about building attributes file system is that you've got multiple machines all trying to hit the same blocks right so the Ceph abstract that the rate of abstraction presents a consistency model using paxos to guard the master map of what's available and then the nodes in themselves or create consistency Seth will block if it can't complete a right Steph will block if it you know it would just sit there and stop the whole thing grinds will halt terrible hundreds of terabytes as you saw there just suddenly unavailable and that's the point and you kind of really have to sort of clench your hands hard go yes this is what I wanted because we're kind of used to languages that yes it compiles and runs it doesn't work and you know it monkey patched it engine sensibility but but it runs dammit you know and you know why are we working in a statically compiled strongly typed language well the you know things things don't compile when when something downstream is broken and then we have a build a swell that's the point I don't want to be able build the software if it's broken and I prefer the compiler telling me that then then find that our users finding out the runtime CP versus AP is the same thing so when we were able to figure out the problems that I was alluding to the previous slide and we hit it you know execute one of our workarounds suddenly what whole by Jenner you know shell prompts go by because nope it's it's happy now it's it's got its read back you know and carries on so the client games that we're running the system never fell over and and likewise similar behavior in the object store we haven't lost we have you know our systems absorbing data have occasionally forgotten to write or fallen over but once Volterra's accepted a point we haven't lost a single one in ten months of running so that's really not down to me so much as it is to stuff be an amazing piece of engineering and if you can tolerate the consistency property um it's somebody's really consider looking at we've been in production for a while as I said the second version improved the write performance problem there is a corner case that we've hit which of course is that you've got you know a bucket with it's very fast for a single read you know you just scan down it and pull that data point out and gather them together and give them back the reason I built this monster was to do analytics on and so the first thing that our data scientist page DS do would want request all the data which way no one squared on me needless to say so a pretty obvious optimization is gathering a bulk request figure out what reads are going into a single bucket and do all those at the same time that's gonna happen now and then we got some further look to you oh the final thing is my buddy could come off with an easier really quick alright the final thing is caching I talked about immutability data being a big insight the other insight into the system that I want to offer is that for us to improve performance is obvious that we can put caching in front of the thing the biggest insight we've had is that there are different types of data so that we don't just want to arbitrary cache there's three signs of data we care about first and foremost I want those bulk reads to not mess up the system but there are there's a live set of data there's basically everything has happened in the last couple hours eight hours or so I need that all in memory because I can build models are evolving over time and looking for patterns and doing alerting and calculations and turns out is only gonna be like a hundred 80 gigabytes I can keep that in RAM no problem the last last eight hours a day does 180 gigs even if it's really slow to that I was with a 10x multiplier for memory layout and so we can keep that a memory no problem so we're gonna create a fast path across the top that doesn't go down a step just any point that comes in and get broadcast across the live set cache and so it makes those points available the second set of data that we care about is a very very limited set of but the the few data points that we do care about for billing right if a customer wants to look at their bill they want to look at their current complete bill which is last month they probably wanna compare it to the month before that fine and we need to be accumulating the current set so that we can tell people what their usage is in real time and that's all I need to carry care about I just need to make sure that those are up I can't have a slow query being blocking on the data Bowl so that's the second specific type of data set will have cache and end and then third one is to take those the remainder of the traffic is bulk reads cache it because sometimes people ask for the same query multiple times so there's no reason we can't accelerate that but just basically pass that through and keep it other way no you know I'm not gonna give follow leanest rule on this one but it's a lot of pieces if I actually in hindsight I probably should have ruthlessly suppressed the number of rot repositories that this is proliferated out to it basically matches mostly haskell modules but also other languages in there the stuff talking about today is the three at the top they were both faced a lot of people have gone into making this what it is it's I can't say it's an open-source project to the sense that it's a large community yet but down the bottom there Aaron Zimmerman is the first person outside of anchor who's called instead of trying to install it can you help me out so we've got you've got users outside the company which is terrific and a big shout out to Katie whose talk on Machiavelli you might have seen yesterday who's built a visualization system which is a big consumer of this and the entik people outside the company as well who have offered us help on design and the indexes will build on the next generation so the last thing I mentioned that I wanted to build analytics on this and this is just a very quick example of the one of the early outputs of the system in terms of being able to use the knowledge that we've gathered and this is correlating what kind of failure modes happen in HTTP servers with meta system metrics and a decision tree models so that's what I had to say thank you for time the half of LCA please take this skipped Andrew and please thank Andrew good