Optimize rate_limiter performance for get_events queries
See https://chat.zulip.org/#narrow/stream/3-backend/topic/profiling.20get_events/near/816860 for profiling details, but basically, currently a get_events request spends 1.4ms/request talking to redis for our rate limiter, which is somewhere between 15% and 50% of the total request runtime (my measurement technique is susceptible to issues like the first request on a code path being extra expensive).  Since get_events is our most scalability-critical endpoint, this is a big deal.

We should do some rethinking of the redis internals for our rate limiter.  I have a few ideas:
* Writing an alternative rate-limiter implementation for `get_events `specifically that's entirely in-process and would be basically instant.  Since the Tornado system has a relatively strong constraint that a given user always connect to the same server, this might be fairly cheap to implement and would bring that 1.4ms to probably 50us or less. (And gate it on `RUNNING_INSIDE_TORNADO`).  
* Look at rewriting our redis transactions to be more efficient for the highest-traffic cases (E.g. user is not close to limit, or user is way over limit).  E.g. maybe `incr_rateimit` should automatically return the `api_calls_left` result rather than requiring 2 transactions.
* Looking at https://github.com/popravich/python-redis-benchmark, there may be some alternative async IO redis clients we could consider migrating to, and possibly some that are just faster.  Given how little code we have interacting with redis directly, this might be an easy port to do; I'm not sure whether or not it would help.  (And unlike the in-process hack approach, this would have side benefits to non-Tornado endpoints).
Optimize rate_limiter performance for get_events queries
See https://chat.zulip.org/#narrow/stream/3-backend/topic/profiling.20get_events/near/816860 for profiling details, but basically, currently a get_events request spends 1.4ms/request talking to redis for our rate limiter, which is somewhere between 15% and 50% of the total request runtime (my measurement technique is susceptible to issues like the first request on a code path being extra expensive).  Since get_events is our most scalability-critical endpoint, this is a big deal.

We should do some rethinking of the redis internals for our rate limiter.  I have a few ideas:
* Writing an alternative rate-limiter implementation for `get_events `specifically that's entirely in-process and would be basically instant.  Since the Tornado system has a relatively strong constraint that a given user always connect to the same server, this might be fairly cheap to implement and would bring that 1.4ms to probably 50us or less. (And gate it on `RUNNING_INSIDE_TORNADO`).  
* Look at rewriting our redis transactions to be more efficient for the highest-traffic cases (E.g. user is not close to limit, or user is way over limit).  E.g. maybe `incr_rateimit` should automatically return the `api_calls_left` result rather than requiring 2 transactions.
* Looking at https://github.com/popravich/python-redis-benchmark, there may be some alternative async IO redis clients we could consider migrating to, and possibly some that are just faster.  Given how little code we have interacting with redis directly, this might be an easy port to do; I'm not sure whether or not it would help.  (And unlike the in-process hack approach, this would have side benefits to non-Tornado endpoints).