Three special data types

In addition to the so-called five basic data types of Redis, there are also some special data types that we need to have a deep or shallow understanding of;


But according to my personal habit, unless I really don’t understand, I should always write in great detail, which is why MY writing tends to be ten thousand words

Personally, I think it’s not a shame to write a technology that’s shallow, but it’s a shame that it’s so obscure that few people can really understand it

So I write things as low as possible; Of course, this is just my opinion and you can disagree with it


I also wrote about the five basic data types two days ago, and it was very long and you can read it yourself if you need to click on the jump

These special data types include Bitmap, Hyperloglogs and Geospatial. Let’s look at them one by one. First of all, Geospatial is relatively simple and close to everyone’s life

Geo

Geospatial is also referred to as Geo. This data type is mainly used to store geographical location information and was added after Redis3.2

How do you store it? Simply add the specified geographic location information (longitude, latitude, name) to the specified Zset;

The purpose of this is to facilitate the use of GEORADIUS or GEORADIUSBYMEMBER command to query the radius of the data.

To here need to mention a mouth, Geo related commands rarely almost one hand can count over, so few commands to achieve add, delete, change, check are enough

So Zset can use the command, Geo is also most likely applicable

Geo is used to store location information and perform operations on the stored information

The ability to implement location-dependent features such as nearby location and shake is a boon for developers who need to implement these features.

Geoadd key longitude latitude member geoadd key longitude latitude member geoadd key longitude latitude member

Like Zset, it allows us to store multiple members, but with two required parameters of latitude and longitude before storing; The longitude is in front and the latitude is behind

The latitude and longitude order is emphasized here because Redis does not allow you to store location information as error information, and it has a valid latitude and longitude concept

  • Effective longitude ranges from -180 degrees to 180 degrees.
  • Valid latitudes range from -85.05112878 degrees to 85.05112878 degrees.

This command returns an error when the coordinates are outside the range specified above.

It’s easy to throw such an error if you’re in front of it, even if you don’t throw the error, the information stored in the error will be wrong; It’s gonna be a headache.

We can try to save several Cities in China. The following are examples:

Geoadd China: City 115.858200 28.682892 nanjing 118.796875 32.060253 Nanjing 120.311913 Wuxi 111.678101 29.031940 Changde 117.943436 28.454863 Shangrao 120.382670 36.067108 Qingdao 122.069847 46.07083 wulanhaote 127.511840 46.871850 qingan 104.066803 30.572815 Chengdu 105.870010 32.430000 guangyuan 121.537498 29.874910 Ningbo 121.540199 25.016500 zhoushan# Added Nanchang, Nanjing, Nanning, Wuxi, Changde, Shangrao, Qingdao, Ulanhot, Qing 'an, Chengdu, Guangyuan, Ningbo, Zhoushan
Copy the code

To see what location information we have stored, use the zrange key start end command mentioned earlier in Zset

127.0.0.1:6379> zrange china:city 0 -1
 1) "nanning"
 2) "chengdu"
 3) "changde"
 4) "guangyuan"
 5) "zhoushan"
 6) "nanchang"
 7) "shangrao"
 8) "wuxi"
 9) "ningbo"
10) "nanjing"
11) "qingdao"
12) "wulanhaote"
13) "qingan"
Copy the code

But don’t take the withscores parameter

To see the latitude and longitude of the cities we have stored, we can use geopos key member[members] to demonstrate

127.0.0.1:6379 > geopos China: the city of shangrao# Check the latitude and longitude of individual cities
1) 1) "117.94343858957290649"
   2) "28.45486211317673764"Geopos China :city shangrao Guangyuan Wulanhaote# Check the latitude and longitude of multiple cities
1) 1) "117.94343858957290649"
   2) "28.45486211317673764"
2) 1) "115.85819810628890991"
   2) "28.68289323283435266"
3) 1) "105.87001115083694458"
   2) "32.429999404617881"
4) 1) "122.06984549760818481"
   2) "46.07082944850478157"
Copy the code

In addition to that if you want to see the straight line distance between two cities you can use the geodist key member1 member2

The length unit can be m, km, mi (miles), or ft (feet). The default length unit is meter

127.0.0.1:6379> Geodist China: City Shangrao Wulanhaote"1992385.3469" The distance as the crow flies from Shangrao to Ulanhot is 1,992,385 meters127.0.0.1:6379> Geodist China: City Shangrao Wulanhaote kmChange the unit to kilometers
"1992.3853" 
Copy the code

It is a useful command to calculate the straight-line distance between two places by latitude and longitude

The next command, which will be of interest to you, allows you to view a collection of location information within a given latitude and longitude radius

It’s like people nearby, but we’re not storing location information for individuals, we’re storing location information for cities;

This command can be used to view the location of a city within the specified radius. You can simply understand the nearby city

This is done with Georadius, but you can also use the Georadiusbymember command to do almost the same thing

The difference is that the former requires you to give a latitude and longitude and the latter requires you to give a member

Let’s try both. First georadius Key Longitude Latitude RADIUS.

127.0.0.1:6379> Georadius China: City 117.94 28.45 500 kmCheck cities within a 500km radius of the latitude and longitude (the location is near Shangrao)
1) "nanchang"
2) "shangrao"
3) "wuxi"
4) "ningbo"
5) "nanjing"
These cities are within a radius of 500km
Copy the code

Georadiusbymember key member RADIUS [length unit]

127.0.0.1:6379> Georadiusbymember China: City Shangrao 500 km 1)"nanchang"
2) "shangrao"
3) "wuxi"
4) "ningbo"
5) "nanjing"
Copy the code

Both commands can carry multiple parameters. The parameters that can be carried are as follows:

  • Withcoord: Carrying this parameter allows the returned position to carry latitude and longitude.
  • Withdist: The position returned with this parameter gives the distance from the specified member or latitude and longitude.
    • The units of distance are the same as those given by the user.
  • COUNT COUNT: Specifies the number of return positions.
  • Asc | desc: returns the distance from the specified member or latitude and longitude for ascending or descending order.

If you're interested, you can test it by yourself, but I'm not going to test it


The last and least used command geohash key member[members]

This command returns an 11-character Geohash string

127.0.0.1:6379> GeoHash China: City shangrao nanchang"wt5cgu5c960"
2) "wt47hmt3gw0"
Copy the code

Make sure you haven’t used Redis GEO

GeoHash is essentially a way of spatially indexing, based on understanding the earth as a two-dimensional plane and recursively breaking the plane into smaller sub-blocks, each with the same encoding over a certain latitude and longitude range. Using GeoHash to establish spatial index can improve the efficiency of latitude and longitude retrieval for spatial POI data. The Geohash principle uses the Geohash to convert a two-dimensional latitude and longitude into a one-dimensional string. Geohash has the following features:

  1. GEOIs of the data typezsetRedis will have all geo-location informationgeohashStored in azsetIn the.
  2. The longer the string, the more precise the position, for examplegeohashWhen the length is 9, the accuracy is about 2 meters. The following figure
  3. The more similar two strings are, the closer they are to each other, and Redis implements the related commands using the string prefix matching algorithm.
  4. geohashCoding and latitude and longitude are interchangeable.

Here geo related commands are finished, the rest of the operation you can use Zset command to operate on geo; I won’t go into any more details here

Hyperloglog

Redis added the HyperLogLog structure in version 2.8.9.

Redis HyperLogLog is used to do cardinality statistics algorithm. The advantage of HyperLogLog is that when the number or volume of input elements is very, very large, the space required to calculate the cardinality is always fixed and small.

In Redis, each HyperLogLog key costs only 12KB of memory to calculate the cardinality of nearly 264 different elements.

This is in stark contrast to sets where the more elements you have, the more memory you consume when calculating cardinality.

However, because HyperLogLog only calculates the cardinality from the input elements and does not store the input elements themselves, HyperLogLog cannot return the individual elements of the input, as collections do.

So this data structure type is often used for UV on your site, if your project is still using Set for UV, consider using Hyperloglog

Hyperloglog has a slight problem, with an error of 0.81%, but if used for UV, such a small error is not too fatal

Hyperloglog commands are relatively few and simple, but if you want to understand Hyperloglog, you need a certain algorithm basis;

Unfortunately, the algorithm has been my short board, I will not show the ugly only about hyperloglog command with, you forgive me (after the algorithm brought up to fill this pit, I promise! .

Hyperloglog commands all start with PF, pfadd, pfcount, and pfmerge

As the names suggest, add, count, and merge are all very simple commands; Here is an example

# Suppose I write an article and the following users click on the article in the first time it is posted
127.0.0.1:6379> pfadd views1 uid1 uid2 uid3 uid4 uid5 uid6 uid7 uid8
(integer1)# In the second period, the following users clicked on this article
127.0.0.1:6379> pfadd views2 uid3 uid5 uid2 uid9 uid11 uid7 uid20 uid22 uid40 uid31 uid12 uid3 uid5
(integer1)Copy the code

At this point, we want to calculate how many users clicked on this article in these two periods, but a single user clicked on this article several times.

This is just a click and we need to de-weigh, which is to calculate the cardinality of views1 and views2

To merge the two Hyperloglog sets we can use the pfmerge command

# merge the two collections. Name the merged collection "all".
127.0.0.1:6379> pfmerge all views1 views2
OK
Copy the code

Then a counting operation can be performed on the combined collection to complete the statistics of the number of clicks

127.0.0.1:6379 > pfcount all (integer15)Copy the code

Finally, the cardinality is 15, which is the simplest use of Hyperloglog, should also be the most application scenarios; The above

Bitmap

In daily development, occasionally the data we need to store will have only two states;

In this case, if we want to store data, the best way is to use bit for storage

In case you’re wondering what a bit is, a bit is a binary unit or binary digit

It is the smallest unit of computer memory. In binary computer systems, each bit can represent either a zero or a one (binary) digital signal (either black or white, or zero or one).

If there are three women and four men out of seven, the easiest way to store this message is to store three zeros, four ones or vice versa;


The original meaning of a BitMap is to map the state of an element in a single bit.

Since a bit can only represent 0 and 1 states, bitmaps can map only a limited number of states, but the advantage of using bits is that they can save a lot of memory space.

In Redis, Bitmaps can be thought of as an array of bits, each cell of which can store only zeros and ones, and the subscripts of the array are called offsets in Bitmaps.

I can’t go any further than that, but let’s finish up by talking about commands and demonstrations

Setbit key offset value

This command is used to set or overwrite the bit of the key’s value(string) at offset.

The offset parameter must be greater than or equal to 0 and less than 232 (the bitmap size is limited to 512MB).

Using the example given above, we need to store seven pieces of data into the Map, as shown below:

127.0.0.1:6379> setbit people 1 0
127.0.0.1:6379> setbit people 2 0
127.0.0.1:6379> setbit people 4 0
127.0.0.1:6379> setbit people 5 0
127.0.0.1:6379> setbit people 0 1
127.0.0.1:6379> setbit people 3 1
127.0.0.1:6379> setbit people 6 1
Add 7 data, 0 for male and 1 for female
Copy the code

Like sets, bitsets can be overridden; We can modify the data by bitset again (overwrite)

127.0.0.1:6379> setbit people 1 1
(integer) 0
127.0.0.1:6379> getbit people 1 Check whether the string is 0 or 1 for the data store with offset 1
(integer1)# return 1 to indicate overwriting; Because the data has changed and now 1 is male and 0 is female
Copy the code

Now that we know about simple access, let’s look at how to count bitmaps. How many strings of 1 are stored in a given Map

The statistics command is bitcount key [start end], where start and end are optional. By default, returns the number of strings 1 stored in the entire Map

127.0.0.1:6379 > bitcount people (integer4)# The number of 1s in this Map is 4
Copy the code

At this point, our bitMap with key “people” is still one byte in size, since offset is not larger than 8

127.0.0.1:6379 > strlen people (integer1)Copy the code

Once offset exceeds 8, the Map becomes two bytes in size

127.0.0.1:6379> setbit people 8 1
(integer) 0
127.0.0.1:6379> strlen people
(integer2)Copy the code

Why bring that up? What does this have to do with the bitcount command?

It matters because the start end argument in the bitcount command is used to specify bytes, specifically a range of bytes

If we take these two arguments, the command instead looks at the number of bytes stored in the string 1 in the specified byte range, which in turn is tied to offset (the maximum offset determines the number of bytes the Map occupies).

Such as:

127.0.0.1:6379> bitcount people 0 0 # check the number of stored strings 1 between bytes 0 and 0
(integer4)# These are the four ones we saved to indicate gender in the beginning
# string 1 with offset < 8 will not be counted because the range specified is 0-0.
127.0.0.1:6379> bitcount people 1 1 If we look at the number of 1's stored between bytes 1 and 1, we will find only the one we just added
(integer1)String 1 whose offset is less than 8 and greater than 15 will not be counted
127.0.0.1:6379> bitcount people 0 1 # Change the condition, and the string 1 of offset 0-15 in Map will be counted
(integer5)Copy the code

Relax your eyes

I'll always like Recy

Original picture P station address

Painters home page