AWS Database Blog

Working with geospatial data in Amazon ElastiCache for Redis

There are multiple examples of geospatial data use cases that most of us encounter on a daily basis. From maps, to weather, to tracking software on phones, geospatial data is all around us. In this post, we explore a use case of a ride sharing app and show the ease of working with geospatial data on Amazon ElastiCache for Redis.

Amazon ElastiCache traditionally has been implemented as a performance booster for persistent data stores such as relational databases. This post provides an alternate usage for ElastiCache by using its native features to perform business-related processing.

Benefits of ElastiCache for Redis

For this use case, ElastiCache for Redis is the right tool for working with geospatial data because of the following features:

  • Speed – It offers microsecond latency (data is stored in memory)
  • Transient data – Vehicles are constantly on the move
  • Managed service – ElastiCache is a fully managed service that can provision a new cluster within minutes
  • High availability – It offers automatic failover and recovery with Multi-AZ deployments and continuous monitoring
  • Scalability – ElastiCache for Redis features auto scaling, with is important for performance when multiple riders are calling for vehicles
  • Cost – There are no upfront costs or long-term commitments
  • Simplicity – The built-in geospatial functionality allows you to get to the desired result in few steps
  • Integration with AWS services – For example, you can use Amazon Location Service for visual representations
  • Write locally, read globally – With Global Datastore, you can bring data closer to your users and enable cross-Region disaster recovery

Although there are multiple services to process geospatial data, the features in ElastiCache for Redis, such as microsecond latency, Multi-AZ, and scalability with the click of a button, are the right fit for this use case. Furthermore, by deploying ElastiCache for Redis in cluster mode, you can shard the data cross multiple instances. This provides the application with multiple write-points to support a high number of updates to the geospatial data.

Solution overview

With this use case, we demonstrate how you can use ElastiCache for Redis to simplify the complex tasks of storing vehicle information and sweeping the area for available vehicles that can provide a ride to the rider. When a rider requests a ride, they can be paired with an available vehicle in a given radius based on their current location.

The following diagram illustrates the flow of data coming in and going out of ElastiCache.

The flow consists of the following steps:

  1. Vehicles send their location and availability.
  2. A rider calls for a car.
  3. Redis uses its built-in functionality to identify available vehicles in the vicinity.
  4. An API call notifies the rider and the driver.
  5. An API call updates the data notifying the vehicle’s availability to accept the next ride.

Prerequisites

This example requires the latest version of ElastiCache for Redis and the cluster should be instantiated. For this post, we use ElastiCache for Redis 7.07.

The latest version of the Redis client is required for command line access from Amazon Elastic Compute Cloud (Amazon EC2). For setup instructions, refer to Grant access to your cluster.

The latest version of the Redis Python library is required to run the Python code either via an AWS Lambda function or an integrated development environment (IDE). For instructions to enable a Lambda function to access an ElastiCache cluster, refer to Tutorial: Configuring a Lambda function to access Amazon ElastiCache in an Amazon VPC.

Initialize and list keys

Initialize and list any keys in the ElastiCache for Redis cluster and verify there is no data in the Redis client. In the Redis client, run the following command:

$ redis-cli -h <cluster endpoint> -p 6379
> keys *
(empty array)

Configure, query, and remove geospatial data

In this section, we demonstrate the API calls and commands in ElastiCache for Redis to configure, query, and remove geospatial data. We have provided the same code for both the Python API calls and interactive commands on the command line.

  1. First, we set up the geospatial data. Vehicles that are available to a rider are added to the geospatial hash NYC-CABS using GEOADD.
    The following is the Python code:

    import redis
    
    r = redis.Redis(
        host='<cluster endpoint>',
        port= 6379)
        
    CabList=[(40.73202896118164,-73.98812866210938, "id3004672"),
            (40.67999267578125,-73.96420288085938,"id3505355"),
            (40.73758316040039,-73.9974365234375,"id1217141"),
            (40.77190017700195,-73.95606994628906,"id2150126"),
            (40.761474609375,-73.97021484375,"id1598245")]
    
    for coords in CabList:
        r.geoadd("NYC-CABS",coords )     
    

    Use the following code with the Redis client:

    > GEOADD "NYC-CABS" 40.73202896118164 -73.98812866210938 "id3004672" 40.67999267578125 -73.96420288085938 "id3505355"  40.73758316040039 -73.9974365234375 "id1217141" 40.77190017700195 -73.95606994628906 "id2150126"  40.761474609375 -73.97021484375 "id1598245"
    (integer) 5
  2. List the vehicles that were added and are available using GEOHASH.
    The following is the Python code:

    import redis
    
    r = redis.Redis(
        host='<cluster endpoint>',
        port= 6379)
        
    r.geohash( "NYC-CABS","id3004672","id3505355","id1217141","id2150126","id1598245")

    We get the following output:

    ['hfugnfu5vj0', 'hfugjxnr290', 'hfugp10jwq0', 'hfugrb9nwj0', 'hfugpw1s700']

    Use the following code with the Redis client:

    > GEOHASH "NYC-CABS" "id3004672" "id3505355" "id1217141" "id2150126" "id1598245"
    1) "hfugnfu5vj0"
    2) "hfugjxnr290"
    3) "hfugp10jwq0"
    4) "hfugrb9nwj0"
    5) "hfugpw1s700"

    A rider hails a ride, which invokes a Lambda function. The rider in this case is hailing from location 130 E 12th St, New York, NY, 10003, with co-ordinates 40.732, -73.9881.

    The following is the Python code:

    pickup_latitude,pickup_longitude=40.732,-73.9881
  3. Using GEOSEARCH, you can quickly find the vehicles in a given radius. In the following code block, we look for vehicles in a 1-mile radius.
    The following is the Python code:

    ridelist=r.geosearch(name="NYC-CABS", longitude=40.732, latitude=-73.9881, 
                         radius=1, unit="mi", sort="ASC")
    print(ridelist)

    We get the following output listed in ascending order of distance:

    ['id3004672', 'id1217141']

    Use the following code with the Redis client:

    GEOSEARCH NYC-CABS FROMLONLAT 40.732 -73.9881 BYRADIUS 1 mi  ASC
    1) "id3004672"
    2) "id1217141"
  4. In the following code block, we get data relevant to the vehicle, such as how far it is from the rider and its coordinates.
    The following is the Python code:

    ridelist=r.geosearch(name="NYC-CABS", longitude=40.732, latitude=-73.9881, 
                         radius=1, unit="mi", sort="ASC")
                         
    for ride in ridelist:
        print(ride)

    We get the following output:

    ['id3004672', 0.0021, (40.732028782367706, -73.98812916556949)]
    ['id1217141', 0.654, (40.737580955028534, -73.9974366616666)]

    Use the following code with the Redis client:

    GEOSEARCH NYC-CABS FROMLONLAT 40.732 -73.9881 BYRADIUS 1 mi  ASC WITHDIST WITHCOORD
    1) 1) "id3004672"
    2) "0.0021"
    3) 1) "40.7320287823677063"
    2) "-73.98812916556948949"
    2) 1) "id1217141"
    2) "0.6540"
    3) 1) "40.73758095502853394"
    2) "-73.9974366616665975"
  5. We choose the closest vehicle, with ID id3004672, for this ride. The vehicle is currently located at 86 3rd Ave, New York, NY, 10003 with co-ordinates 40.73203, -73.988129
  6. Notify the rider and driver of the match and acknowledgement.
  7. After the vehicle has been identified and engaged, use ZREM to remove the vehicle from the available list.
    The following is the Python code:

    r.zrem("NYC-CABS","id3004672")

    We get the following output:

    1

    Use the following code with the Redis client:

    > ZREM NYC-CABS id3004672
    (integer) 1
  8. To confirm, check for the existence of the vehicle in the hash.
    The following is the Python code:

    r.geohash( "NYC-CABS","id3004672")

    We get the following output:

    [None]

    Use the following code with the Redis client:

    > GEOHASH "NYC-CABS" id3004672
    1) (nil)

In just a few simple commands, ElastiCache for Redis can quickly process geospatial data.

Clean up

To stop incurring unnecessary charges, complete the following steps to clean up your resources:

  1. Delete ElastiCache for Redis cluster.
  2. Delete any Lambda functions or other resources used to simulate the ride sharing use case.
  3. Delete any EC2 instances that you created to test the solution.

Conclusion

In this post, we showed how to quickly store and match riders to vehicles using a few simple commands in ElastiCache for Redis. Apart from the performance and cost benefits, this simplicity of use will increase innovation to develop more complex geospatial use cases.

For more information about ElastiCache for Redis and other geospatial use cases, refer to the following:


About the Author

Venkataramanan Govindarajan is a Senior Database Specialist Solutions Architect at Amazon Web Services. Venkat works with our customers to provide architecture guidance and database solutions, helping them innovate using AWS services and to improve their business value.