Redis internally uses a RedisObject to represent all keys and values. The type in a RedisObject represents the specific data type of a value object. It contains strings, lists, hashes, sets, and Sorted sets.

In daily work, there are two ways to store object information, one is to store it with Hash and the other is to store it with String. But there seems to be no such thing as a best practice, so what data structure is actually better for storage?

First, a quick review of Redis’s Hash and String structures.

String

A String data structure is a simple key-value type. A value is not just a String, it can also be a number. A String in Redis can represent a number of semantics:

  • String (bits)

  • The integer

  • Floating point Numbers

For these three types, Redis will automatically convert them according to specific scenarios and select the underlying bearing mode as required. String is stored internally in Redis as a String by default, and is referenced by RedisObject. When incR, DECr, etc., is converted to a numeric value for calculation. In this case, the Encoding field of RedisObject is int.

In the stored procedure, you can serialize the user information into a string using Json, and then store the serialized string in Redis for caching.

Because the string of Redis is dynamic and can be modified, its internal structure is similar to That of Java’s ArrayList, and it reduces the frequent allocation of memory by pre-allocating redundant space. As shown in the figure above, the actual space allocated internally for the current string, Capacity, is generally higher than the actual string length len.

Suppose the structure we want to store is:

{
  "name": "xiaowang",
  "age": "35"
}
Copy the code

If you change the name of the user information to Xiaoli and save it to Redis, the Redis does not need to reallocate space. And when we read and store data, we only need to do Json serialization and deserialization, which is convenient.

Hash

Hash is widely used in many programming languages, and Redis is no exception. In Redis, Hash is often used to cache some object information, such as user information, product information, configuration information, etc., so it is also called dictionary. The dictionary of Redis uses Hash table as the underlying implementation. A Hash table can have multiple Hash table nodes, and each Hash table node holds a key-value pair from the dictionary. In fact, the underlying Redis database also uses Hash tables to store key-value pairs.

Redis Hash is equivalent to Java HashMap, and its internal structure is the same as HashMap, that is, array + linked list structure. They just reHash it differently.

String is suitable for storing user information, and the Hash structure can store user information separately for each field. Therefore, you can obtain partial field information during query to save network traffic. The Hash value of Redis can only be a string. The Hash value of Redis can only be a string.

{
  "name": "xiaowang",
  "age": 25,
  "clothes": {
    "shirt": "gray",
    "pants": "read"
  }
}
Copy the code

How to store the “clothes” property then becomes a question of whether to use String or Hash.

Comparison of memory usage between String and Hash

Since both data structures can store structure information. Which is more appropriate?

First, we used code to insert 10000 pieces of data, and then we used visual tools to see the memory footprint.

const Redis = require("ioRedis"); const Redis0 = new Redis({port: 6370}); const Redis1 = new Redis({port: 6371}); const user = { name: 'name12345', age: 16, avatar: 'https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=256767015, & FM = 26 & gp = 0. 24101428 JPG', phone: '13111111111', email: '[email protected]', lastLogon: '2021-04-28 10:00:00', } async function main() { for (let i = 0; i < 10000; i++) { await Redis0.set(`String:user:${i}`, Json.Stringify(user)); await Redis1.hmset(`Hash:user:${i}`, user); } } main().then(process.exit);Copy the code

Look at the Redis0:

Take a look at Redis1:

You can see there’s a gap, but it’s not obvious.

The net friend to discuss

Users on the web have the same question, wondering whether String or Hash is more efficient because the length of the value is indeterminate.

Here I mainly give you a translation of the question under the quality of the answer:

Suitable for String storage:

  • You need to access a large number of fields at a time

  • When the storage structure has multiple layers of nesting

Where Hash storage is appropriate:

  • In most cases, only a few fields need to be accessed

  • You always know which fields are available in case you don’t get the data you want when you use MGET

conclusion

This article mainly introduces whether Redis stores object information using Hash or String. It is recommended to use String in most cases. After all, it is more convenient to store objects with multiple layers of nesting and takes less space than Hash. Consider using Hash when you need to store a particularly large object and, in most cases, only a small number of the object’s fields need to be accessed.