An overview of the

This article is mainly based on the previous Redis core data structure and application of a supplement mainly describes several data types and applications.

  1. pipline
  2. The lua script
  3. Geo
  4. bitmap

The main is a simple description of the use of scenarios and demo code. Jedis version 2.9.0

Pipline pipeline

Redis is a TCP service based on the client-server model and request/response protocol. This means that typically a request will follow these steps:

  • The client sends a query request to the server and listens for the Socket return, usually in blocking mode, waiting for the server to respond.
  • The server processes the command and returns the result to the client.

Redis pipeline technology allows the client to continue sending requests to the server when the server does not respond, and eventually read all of the server’s responses at once.

public class RedisPipelineTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1".6379);

        // Use pipes
        long start = System.currentTimeMillis();
        Pipeline pipeline = jedis.pipelined();
        for (int i = 1; i <= 10000; i++) {
            pipeline.set("abc" + i, "i=" + i);
        }
        pipeline.multi();
        pipeline.exec();
        long end = System.currentTimeMillis();
        // 50ms
        System.out.println("pipeline cost time :" + (end - start) + "ms");


        jedis.resetState();
        start = System.currentTimeMillis();
        for (int i = 1; i <= 10000; i++) {
            jedis.set("abcd" + i, "i=" + i);
        }
        end = System.currentTimeMillis();
        //261ms
        System.out.println("pipeline cost time :" + (end - start) + "ms"); }}Copy the code

Therefore, we can come to the conclusion that pipeline is suitable for batch operation scenarios, and has obvious advantages for the cost of time.

The lua script

Redis scripts use the Lua interpreter to execute scripts. Redis 2.6 supports the Lua environment through embedding. The common command for executing scripts is EVAL.

Because LUA scripts are atomic in Redis execution process, and ensure that all operations in LUA script will either succeed at the same time, if the failure will be rolled back, if we can use LUA script for transaction implementation, the following is a mutex example code:

public class RedisLuaTest {

    public static void main(String[] args) {
        // Implement exclusive lock demo
        Jedis jedis = new Jedis("127.0.0.1".6379);
        String key = "test:redis:lock";
        // Each thread has a different value, so uuid can be used here
        String val = "1000";
        String result = jedis.set(key, val, "nx"."px".100000);
        if ("OK".equals(result)) {
            System.out.println("Lock success: key =" + key + "; value=" + val);
        }
        // The use of lua scripts
        Long count = (Long) jedis.eval("if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
                " return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                " return 0\n" +
                "end", Arrays.asList(key), Arrays.asList(val));
        if (count == 1) {
            System.out.println("Unlocked successfully: key =" + key + "; value="+ val); }}}Copy the code

Geo Address location information

Redis GEO is used to store location information and perform operations on the stored information. This feature is added in Redis 3.2.

Redis GEO operation methods include:

  • Geoadd: Adds the coordinates of a geographic location.
  • Geopos: To obtain the coordinates of geographical locations.
  • Geodist: Calculates the distance between two locations.
  • Georadius: Obtain the set of geographical locations within the specified range according to the latitude and longitude coordinates given by the user.
  • Georadiusbymember: Retrieves a set of geographic locations within a specified range based on a location stored in the location set.
  • Geohash: Returns the geohash value of one or more positional objects.

Usage Scenarios:

  1. Nearby get people, nearby get location search

The following is a demo by city location query surrounding cities, query conditions by latitude and longitude query surrounding information:

public class RediGeoTest {

    static class Coordinate {
        / / longitude
        public double lng;
        / / latitude
        public double lat;
        / / position
        public String name;

        public Coordinate(double lng, double lat, String name) {
            this.lng = lng;
            this.lat = lat;
            this.name = name; }}public static void main(String[] args) {
        / / GEO calls
        Jedis jedis = new Jedis("127.0.0.1".6379);
        / / gold map coordinate pick up: https://lbs.amap.com/console/show/picker
        / / 104.066143, 30.573095 in chengdu
        / / 104.741722, 31.46402 in mianyang
        / / 103.001033, 29.987722
        / / 103.761263, 29.582024 in leshan
        / / 106.550464, 29.563761 in chongqing
        List<Coordinate> list = new ArrayList<>();
        list.add(new Coordinate(30.573095.104.066143."chengdu"));
        list.add(new Coordinate(31.46402.104.741722."mianyang"));
        list.add(new Coordinate(29.987722.103.001033."yaan"));
        list.add(new Coordinate(29.582024.103.761263."lesan"));
        list.add(new Coordinate(29.563761.106.550464."chongqing"));

        // Storage location
        String key = "geo:city:001";
        for (Coordinate item : list) {
            // Geoadd 106.550464 29.563761 CHONGQING
            jedis.geoadd(key, item.lat, item.lng, item.name);
        }

        // query cities within 50km from chengdu
        // Georadius geo: City :001 104.066143 30.573095 200 km ASC withcoord withdist
        List<GeoRadiusResponse> citys = jedis.georadius(key, 104.066143.30.573095.2000, GeoUnit.KM,
                GeoRadiusParam.geoRadiusParam()
                        // From near to far
                        .sortAscending()
                        // return latitude and longitude
                        .withCoord()
                        // Return the distance
                        .withDist());
        citys.stream().forEach(item -> {
            String val = "member:" + new String(item.getMember()) + "; distance:" + item.getDistance() + ";";
            GeoCoordinate coordinate = item.getCoordinate();
            if(coordinate ! =null) {
                val += " lat:" + coordinate.getLatitude() + "; lng:" + coordinate.getLongitude();
            }
            System.out.println(val);
        });
        
        // Return the result
        //member:chengdu; Short: 2.0 e-4; Lat: 30.573095634661236; LNG: 104.06614512205124
        //member:lesan; Short: 114.0718; Lat: 29.582024730802026; LNG: 103.76126378774643
        //member:mianyang; Short: 118.1798; Lat: 31.464019705514964; LNG: 104.74172383546829
        //member:yaan; Short: 121.2653; Lat: 29.987722060681172; LNG: 103.00103455781937
        //member:chongqing; Short: 264.1675; Lat: 29.56376206484898; LNG: 106.55046612024307}}Copy the code

Bitmap bitmap

It’s a Bitmap. To manipulate binary bits to record, there are only 0 and 1 states. It can be used to record clocking, check whether the day is clocking, count the number of days, or the number of likes. The following is a simple demo code advantage: use a bit to represent the value or state of an element, where the key is the element itself. We know that 8 bits can form a Byte, so bitmap itself can save a lot of storage space.

public class RedisBitMapTest {

    public static void main(String[] args) throws IOException {
        / / redis bitmap
        Jedis jedis = new Jedis("127.0.0.1".6379);

        // Record news subscribers
        String key = "article:like:1001";
        Pipeline pp = jedis.pipelined();
        for (int offset = 1; offset <= 500000; offset++) {
            pp.setbit(key, offset, offset % 3= =0);
        }
        pp.multi();
        pp.exec();
        pp.close();

        Long count = jedis.bitcount(key);
        System.out.println("key=" + key + "; count=" + count);

        // User check-in (regardless of persistent storage)
        int start = 20200101;
        int now = Integer.parseInt(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        key = "user:sign:1001";
        int offset = now - start;
        for (int i = 0; i <= 365; i++) {
            jedis.setbit(key, i, String.valueOf((i % 3= =0 ? 1 : 0)));
        }
        // Total check-in
        count = jedis.bitcount(key);
        System.out.println("User: 1001 Accumulative check-in:" + count);

        // Whether to check in
        Boolean isSign = jedis.getbit(key, offset);
        System.out.println("User: 1001" + now + "Check in or not:" + isSign);

        // Number of check-in days in January
        count = jedis.bitcount(key, 0.30);
        System.out.println("User: 1001 Cumulative check-in in January:" + count);

        // Output the result
        // key=article:like:1001; count=333332
        // User: 1001 Accumulative sign-in: 122
        // User: 1001 20210127 Check in or not: false
        // Users: 1001 Cumulative check-in in January: 83}}Copy the code