gevent at TellApart

September 19, 2012

At TellApart, we’re big fans of gevent. It powers a number of our core components, from the TellApart Front End servers, to our open-source Taba aggragation service. For those not familiar with it, gevent is a library for standard Python (CPython) based on greenlet and libevent, which enables high concurrency workloads and co-operative scheduling.

Since we use it so extensively, we were recently invited to give a talk at Pinterest about gevent, its advantages, some pitfalls to avoid, and how we use it throughout the TellApart stack. We wanted to share the slides from that presentation for anyone who’s interested.

Kevin Ballard is a Software Engineer at TellApart.

TellApart and the Facebook Exchange

September 13, 2012

Early Results from Facebook Exchange Show 10-20x ROI for TellApart Clients

As one of the earliest companies on the Facebook Exchange (FBX), we’ve been serving ads through FBX for three months and have learned an immense amount about how to maximize performance from this new platform. We can say without reservation that it delivers strong ROI for our clients.

Facebook ads work. Hugely so, as every one of our clients on the exchange has seen a 10-20x return on investment. eBags, one of our earliest marketers to go live on FBX, sees an unwavering 15x return on ad spend. And when we say the Facebook Exchange works, understand that this is based on solid direct response data.

TellApart has the unique business model of only making money when our clients do. We get paid (a share of the sale) only when a shopper first clicks on one of our ads and then converts on our retail client’s site. There may be differences in opinion as to the worthiness of the click as the end-all metric, but there is no debating the direct response value of a shopper who clicks and purchases. Indeed, Google has built $40B of annual revenue around this core behavior.

What makes FBX a game changer for the display ads industry?

1) Huge, Consistent Audience & Environment
First, it’s important that Facebook has a lot of users who come back often and spend a lot of time there. According to ComScore, Facebook serves over 25% of all US display ad impressions, and we’ve seen that proven to be accurate. But unlike other exchanges, FBX offers a stable audience and consistent context. To know that the ads we purchase are going to appear in a clean, well-lit environment with high visibility (i.e. rarely below the fold or not in view) — is invaluable when doing the type of modeling that we do to determine predicted click through and conversion rates.

2) BYOD & Import Intent — Per User
With FBX, Facebook has enabled marketers to import their own customer & intent data, while still protecting user privacy. Facebook doesn’t share any new data with us as a result of these ads, but we’re able to remarket to people the products they’ve seen elsewhere. As with other ad exchanges, Facebook allows each marketer to “Bring Your Own Data.”. If a shopper has shown strong interest in a particular pair of Jimmy Choos on Nordstrom, we can show precisely that user exactly that pair of shoes. Both ad creative and bid pricing decisions are made at the level of the individual user, in real time.

3) Highly Engaged Users
Users shown ads on Facebook via FBX click through at similar — or better — rates as all other ad exchanges. TellApart FBX ads for OnlineShoes.com yield a consistent user click through rate of over 15%. That 15 out of 100 users to whom we served ads on Facebook would choose to click through is an amazing fact. Our all customer average user CTR is 6.6% on both the Facebook Exchange and Doubleclick Ad Exchange.

4) High Return on Investment
As great as clicks are, TellApart’s efforts are worthless until the shopper actually makes a purchase. And those from FBX do. The shoppers who come from the Facebook Exchange clicks are of high quality, with order values that are equally as high as our merchants’ average.

5) Fully Complementary
As a buyer across all of the major real time biddable ad exchanges, even we have seen that FBX increases our unique reach by 30%. The significance of this number should not be understated. With FBX, Facebook has introduced a new form of advertising media that is complementary to both the other Facebook programs and non-Facebook focused programs that retailers may be running. Because FBX uses marketers’ audience data, not Facebook data & targeting, any overlap is likely to be small.

FBX is a new opportunity that all marketers should seriously consider. It’s not accurately described by either ‘earned media’ or ‘paid media,’ and so we’ve taken to calling it, ‘invested media.’ You’ve worked hard to build your ecommerce site and brand. You’ve spent huge sums on keywords and queries. You’ve invested in creating the audience on your site who is interested in what you have to offer. Now you can take that data asset and leverage it into the world’s newest, game-changing ad marketplace: the Facebook Exchange.

TellApart FBX ad

Keep on Pushing

August 2, 2012

One of the things that’s important to us at TellApart is engineering agility: we are constantly deploying new features, launching A/B experiments, and making system improvements. Yet, this goal is often at odds with maintaining a robust system with zero downtime, whilst handling tens of thousands of queries per second. To meet both of these needs, we’ve taken advantage of many of the Amazon Web Services (AWS) technologies to build a deployment process that takes about 10 minutes, rotates out a few hundred machines, and never drops a single request on the floor.

First, a little history. What were we doing before?

Our original deploy system was a rolling push in which a few instances were deregistered at a time, overlayed with new code, and then re-registered with the ELB. Because our frontend fleet was hundreds of machines in size, this would take quite a while, frequently more than 2 hours.

As mentioned above, our new deployment process – with the help of the robust AWS services – cut deploy time by 93%. AND we did all this while maintaining overall system stability.

So, how do we do it?

At a high level, the code deployer script brings up a parallel cluster of machines registered behind the ELB. The old machines are then removed from the ELB, and terminated. The end result is the new cluster of machines handling the traffic in a seamless manner with no downtime.

More specifically, here are the steps we follow. These steps are performed by a simple script that uses Boto extensively.

  • Create a release bundle with an archiver (git/tar)
  • Canary using a test instance
    • Bring up a single frontend with the new bundle, registered with the ELB
    • Manually vet the deployment to ensure correctness — here we rely heavily on Taba statistics
    • Push the deployment archive to S3 and tag it as a production archive
  • Bring up new instances through respective AutoScaling groups in each active region
    • Temporarily disable all scaling activities for the duration of the deployment (doc)
    • Create a list of old instances behind the AutoScaler running the old code (doc)
    • Bring up a parallel set of new instances: a system boot init script will pull the S3 code bundle, and start up the TellApart frontend
    • Rely on the ELB to send traffic to the new instances once they have been setup and healthy (The ELB is configured with an application level /ping path, which will return ‘HTTP 200′ when healthy)
  • Bring down the old instances in each AutoScaling group
    • Check for new instances behind the ELB to be in the ‘InService’ state.
    • Remove old instances from the AutoScaler (doc)
    • Reset the min and max size for the AutoScalers and resume AutoScaling

This manner of deployment works well at TellApart given other continuous build and testing systems that are deployed. Unit tests and system level tests are run using Hudson, and a few high level system tests are also conducted in parallel in a continuous manner. TellApart also uses Taba extensively to capture, aggregate and monitor statistics over the entire system to ensure that any possible regressions are rapidly caught and addressed.

Sanjay Jeyakumar is a Software Engineer at TellApart.

Taba: Low Latency Event Aggregation

March 20, 2012

Introduction

At TellApart we love metrics, and certainly have lots to measure. We track data for nearly 10,000 different event types across all parts of our stack (and that’s just the real-time data!). This information is used for all sorts of things, like monitoring, performance metrics, segmentation information, and feedback loops. In order to manage all this data, we created the Taba service (the name is derived from the Japanese for bundle or flux (束)).

In designing Taba, we had a number of goals:

  • Low latency: An event should be visible within seconds of occurring. This enables responsive monitoring, tight feedback loops, and other near-line applications.
  • Low impact: CPU and memory usage within the client applications should be minimized.
  • Durability: Events should be reasonably durable, so that a Taba “Tab” can be used as a basis of important services like monitoring.
  • Scalability: All components of the Taba service should be horizontally scalable to keep up with the applications it tracks.

Different Types

Each event type, or “Tab”, being tracked is identified by a Name, and a Type that maps to a Handler class. The core Taba service doesn’t implement data manipulation operations – all schemas and transformations are left to the Handlers. By separating the schemas from the rest of the service, Tabs that behave differently can easily co-exist, and implementing new types of aggregation is simple.

Data Model 

Data life-cycle of a Taba Tab

The fundamental element of data in the Taba service is the Event. Events are composed of three pieces of data: the Tab, the time, and a value. Events are gathered to a central server (more on this later), and combined into State objects which are persisted in a database. The motivation behind persisting States instead of the individual Events is two-fold: (1) storing all events would consume far too much space (timestamps alone would consume gigabytes per hour), and (2) pre-calculated State objects mean faster query response times.

When the Taba service is queried, States are converted into Projections and/or Aggregates. A Projection is a reduction of the State into a dictionary, and an Aggregate is a combination of Projections. Depending on the query, a Projection or an Aggregate will be returned, optionally rendered by the Handler into a human-readable format.

Architecture

Taba System Architecture 

Applications generate Events by embedding a Taba Client. The Client briefly buffers Events and posts them to a Taba Agent over an HTTP based protocol. An Agent receives Events from multiple Clients (usually on the same machine) briefly buffers them, and posts them to the Taba Server using the same protocol. The Client + Agent scheme allows for a very simple and resource-light Client, putting more complex buffering and durability functions in a separate process. The Agent also helps performance by batching requests to the Server.

The Server is where the real magic happens. Like TellApart’s TAFE server, it’s a distributed Python service sitting behind an Nginx reverse proxy, and uses gevent for simple and fast co-operative concurrency. The Server itself is stateless, meaning you can launch as many as needed; the Agents will distribute requests across Servers. The Server receives Events and invokes the appropriate Handler to fold them into States, or generate Projections and Aggregates. A State object is maintained for each Client and Tab combination, so that the status of any Client can be queried.

We use Redis for the database, but with our own transparent sharding layer on top to overcome single process limitations. Sharding is based on virtual buckets, and supports a subset of Redis data-types, and transactions/locking. Like the Server, as many Redis processes as needed can be run, and re-sharding without downtime is possible.

In Production

Currently, we have the Taba service deployed in each region as a cluster of 2 Servers instances and 1 Database instance, each running 8 processes. Each cluster handles over 10,000,000 events per minute, from 300 individual Clients across 10,000 different Tabs, with an average latency of 30 seconds. The Taba architecture and data model have allowed us to use it for fine-grained monitoring, real-time feedback systems, and internal Dashboards. We’ve only started to integrate its full functionality, and already it has provided a deeper insight into TellApart’s system.

Kevin Ballard is a Software Engineer at TellApart.

Mr. Jerb: How We Launch mrjob at TellApart

June 1, 2011

At TellApart, we’ve become fans of Mrjob, an open source Python package that provides much needed hooks into Hadoop’s streaming framework. It allows for development of a job without needing to worry about infrastructure, the format of the input, or code-base bloating shell scripts. Writing a streaming job is as easy as writing a generator in python.

Prior to Mrjob, the thought of writing a streaming MapReduce job made me shudder. Simply adding a mapper required adding the python module, a test, and a shell script (with the path to the mapper hardcoded) to invoke the module with different command line parameters than the test used. It was almost enough to make me avoid writing jobs that had a reduce phase as it meant doubling the time I’d have to put in.

Mrjob mostly does the trick — but we prefer to invoke it with a launcher that we callMrJerb. MrJerb makes launching mrjob jobs as simple as writing a generator or two. Note that we use command line parameters to launch the streaming job because that’s more consistent with our own code base, but your mileage may vary. (I recommend using version >=0.2.2 of Mrjob, or expect to pull your hair out while trying to work with hadoop_extra_args.)

Here are a few other things it simplifies:

  • Adding jar files and partitioners.
  • Setting the equivalent of –python_archive (set to be released in mrjob 0.2.7).
  • Setting output protocol and other job attributes (name, number of reduce tasks).
  • Setting cleanup options for the job.
  • Optionally deleting the output path.

Check out MrJerb on GitHub.

Ned Rockson is a software engineer at TellApart.

 

TellApart Engineers Sanjay & Dmitry Discuss Why Engineering at TellApart is a Unique Opportunity

May 23, 2011

TellApart Engineers Sanjay & Dmitry recently headed over to the UC Berkeley Startup Fair to share with prospective hires what it’s like to work at TellApart. It was a great opportunity for us to meet and spend time with undergraduate & graduate students in computer science, electrical engineering and mathematics. 

In this 90 second clip, they are able to convey both the breadth of technical challenges that we tackle on a daily basis and also share a little info about our company culture and exciting growth. We may request that they pitch in soon on some marketing collateral as well…

Recruiting stars from top universities is a big focus for us now, as we are meaningfully expanding our engineering team over the next few quarters. If you’re in an academic environment and are looking to make a move into a fast-paced startup, take a look through our open positions (recently updated) and drop us a line!

Log Event Processing with HBase

February 17, 2011

This post ran earlier today on the Cloudera Blog.

Apache Hadoop is widely used for log processing at scale. The ability to ingest, process, and analyze terabytes of log data has led to myriad applications and insights. As applications grow in sophistication, so does the amount and variety of the log data being produced. At TellApart, we track tens of millions of user events per day, and have built a flexible system atop HBase for storing and analyzing these types of logs offline.

A TellApart user planning a bird-watching trip may start her day searching for binoculars on Binoculars.com, continue to comparison-shop for new hiking pants on one of our other partner merchants, and be shown relevant ads to these interests throughout her experience. Her browsing activity produces a flurry of different log data: page views, transactions, ad impressions, ad clicks, real-time ad auction bid request, and many more. Dissecting this data is a common scenario – and a real challenge – faced by many log analysis applications.

Many of these scenarios share a common set of requirements:

  • Data must be ingested into the system incrementally – one day or so worth of data at a time.
  • Data is processed at a variety of time scales. Daily reporting often cares only about one day’s worth of data, while machine learning applications may require digesting several months worth of data to build models.
  • Some events are naturally associated with others. An ad click is logged separately from an ad impression, but the two need to be processed together. Some data extraction applications need to process these associated events together, but others only care about the individual events.
  • Random-access lookups to track all the actions of a user across time are often helpful. This is a powerful debugging tool to understand how the user interacts with the web at large and with the TellApart system in particular.

We’ve found that HBase is uniquely well suited to many of these tasks. By organizing user events across rows and columns, and using the various built-in HBase server-side filters, we can slice the data across the different required dimensions. The first decision to make when setting up an HBase system is the schema to use. We broke down the data as follows:

This organization of data, coupled with HBase’s abilities, allows for powerful methods of accessing the data ‒ both for reading and writing data. Consider importing data, one day at a time, into HBase. This can be done with a simple Map-Reduce that writes data into the appropriate rows, which is about the same as a typical Hadoop implementation. However, if the data to be imported is associated with some other type of data through an event id (in our example, these are ad clicks, each of which is associated with an impression), we simply need to write the clicks into the row the associated impression is in. This can be done with a map-only Map-Reduce, so we can avoid an unnecessary reduce step to join clicks to impressions. The same basic idea of associating related events in the same row can be extended to encompass the outputs of analysis jobs. For example, if an offline analysis determines that a given impression leads to an action on an advertiser’s site, we can output data about that action into the same row. Subsequent applications don’t need to repeat this analysis to obtain that data.

Judicious use of filters and column selection lets us control which parts of the data we need to read for any specific type of operation. Consider a task where we only need to read data from the past month. Since the timestamp is embedded in the row key, we can use a Map-Reduce with an HBase RowFilter with a custom Comparator. The filter will only accept rows within our date range. An alternative here is to use the built-in timestamp associated with each HBase cell to do this kind of filtering. Doing this reduces the amount of data the mappers have to process, and significantly speeds up the jobs. Another way to slice data by rows is based simply on the prefix of the rows. In our use case, the user ID is the prefix of each row. With randomly-generated user IDs, if we want to run a Map-Reduce that analyses a sample of all users, we can do so by using a PrefixFilter, which will only accept rows with a given prefix.

We can also use columns to select the set of data we’d like to read. For some tasks, we need to read both the impressions and the bid requests associated with each impression. For others, we only need to read impressions. By selecting the columns to read, we can limit the input set of data. Going further, we can even limit the data based on the values of some columns. TellApart serves impressions that show ads for various advertisers. By storing the advertiser id in a separate “advertiser_id” column, and using a SingleValueColumnFilter, we can retrieve only rows for a particular advertiser if that’s all we care about.

Aside from Map-Reduce applications, HBase is also great for random lookups of data. We often need to see all of a particular user’s log actions over time, for debugging our system. This is where HBase really shines – we issue a Scan for the range of keys starting with a given user ID. This gives us instant visibility into the data, and we can use the same column-based filters to limit the data further if necessary. We issue these lookups in the HBase Shell, and to make this easy, we’ve modified the HBase Shell to deserialize and format the data we store in HBase to make it readable for us.

We’ve also made it easier for HBase to play nice with Cascading and Thrift. To use HBase with Cascading, we built on top of the existing Cascading.HBase support, adding support for any Hadoop Serialization to the module. This lets us read and write Thrift objects (or any other Hadoop Writable) from HBase in our Cascading jobs, much in the same way we would for any Hadoop job. The code is available at TellApart-Hadoop-Utils.

HBase’s flexibility has been a boon to our offline analysis. Separating the data by rows and columns affords us tremendous flexibility in our data access patterns, and gives us a strong platform to grow on in the future.

Dmitry Chechik is a software engineer at TellApart.

Welcome to the TellApart Engineering Blog!

February 16, 2011

At TellApart, there are a few things we’re pretty serious about: moving fast, tapping into the power of data, and keeping our in-office surround sound system in working order (let’s just say our holiday party was a bit too festive). But we’re especially serious about great engineering.

In the ten months since our public launch, TellApart engineers have had to solve some pretty daunting technical challenges, like how to handle tens of thousands of requests per second under strict latency guarantees on behalf of hundreds of millions of users. And that’s just be beginning of our story.

This blog is our way of saying hello to fellow engineers and data-heads. We’ll talk about technology, platforms, team-building, and all-things Eng. We’re also excited to share some of the code and tools we’ve developed in-house with the wider community. Stay tuned!

 

Copyright ©2013 TellApart, Inc. All rights reserved.   Privacy Policy