Redis development specification (From Ali) learning summary

1. Key value design
1. Key name design
(1) [Suggestion]: Readability and manageability
are prefixed with the business name (or database name) (to prevent key conflicts), separated by colons, such as business name: table name :id

ugc:video:1



(2) [Suggestion]: On the premise of ensuring the semantics of simplicity , control the length of the key. When there are many keys, the memory usage cannot be ignored , for example:
user:{uid}:friends:messages:{mid} 简化成u:{uid}:fr:m:{mid}


(3) [Mandatory]: Do not include special characters
Counter example: Include spaces, newlines, single and double quotation marks and other escape characters

2. Value design
(1) [Mandatory]: Reject bigkey (to prevent network card traffic, slow query)
string type control Within 10KB, the number of hash, list, set, and zset elements should not exceed 5000.

Counter example: a list with 2 million elements.

For non-string bigkeys, do not use del to delete them. Use hscan, sscan, and zscan to delete them gradually. At the same time, pay attention to prevent the problem of automatic deletion of bigkey expiration time (for example, a 2 million zset set to expire in 1 hour will trigger the del operation, causing Blocking, and the operation will not appear in the slow query (latency can be checked)), search method and delete method

(2) [recommended]: select the appropriate data type.
For example: entity type (to reasonably control and use data structure memory encoding to optimize configuration, such as ziplist, but also pay attention to the balance between saving memory and performance)

Counter example:
set user:1:name tom
set user:1:age 19
set user:1:favor football

Normal example:
hmset user:1 name tom age 19 favor football


3. [Recommendation]: Control the life cycle of the key, redis is not a trash can.
It is recommended to use expire to set the expiration time (if the conditions allow, the expiration time can be broken up to prevent centralized expiration), and the data that does not expire should focus on idletime.

2. Command usage
1. [Recommended] The O(N) command pays attention to the number of N,
such as hgetall, lrange, smembers, zrange, sinter, etc. It is not impossible to use, but the value of N needs to be specified. If there is a need for traversal, hscan, sscan, and zscan can be used instead.

2. [Recommended]: Disable the command to
prohibit the online use of keys, flush, flushdb, etc., disable the command through the rename mechanism of redis, or use the scan method for progressive processing.

3. [Recommendation] Reasonable use of select
redis multi-database is weak, using numbers to distinguish, many clients have poor support, and multi-service multi-database is actually single-threaded processing, there will be interference.

4. [Recommended] Use batch operations to improve efficiency
Native commands: such as mget, mset.
Non-native commands: You can use pipelines to improve efficiency.


But pay attention to controlling the number of elements in a batch operation (for example, within 500, which is actually related to the number of element bytes).

Note that the two are different:

1. Native is an atomic operation, and pipeline is a non-atomic operation.
2. The pipeline can package different commands, which cannot be done natively
3. The pipeline needs to be supported by both the client and the server.


5. [Recommendation] Redis transaction function is weak, it is not recommended to use too much
Redis transaction function is weak (does not support rollback), and the cluster version (self-developed and official) requires that the key of a transaction operation must be in a slot ( It can be solved by using the hashtag function)

6. [Suggestion] The Redis cluster version has special requirements for using Lua:
1. All keys should be passed by the KEYS array. The redis command and key position called in redis.call/pcall must be is the KEYS array, otherwise return error directly, "-ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array"
2. All keys must be in one slot, otherwise return error directly , "-ERR eval/evalsha command keys must in same slot"
7. [Suggestion] When using the monitor command if necessary, be careful not to use it for a long time.

3. Client use
1. [Recommendation]
Avoid using one Redis instance for multiple applications

Positive example: split unrelated business, and make public data service.

2. [Recommended]
Using a database with a connection pool can effectively control connections and improve efficiency. Standard usage:

execute the command as follows:
Jedis jedis = null;
try {
    jedis = jedisPool.getResource();
    // specific command
    jedis.executeCommand()
} catch (Exception e) {
    logger.error("op key {} error: " + e.getMessage(), key, e);
} finally {
    //Note that this is not to close the connection. In JedisPool mode, Jedis will be returned to the resource pool.
    if (jedis != null)
        jedis.close();
}


3. [Recommendation] It
is recommended that the client add a circuit breaker function (such as netflix hystrix) under high concurrency.

4. [Recommendation]
Set a reasonable password, and use SSL encryption to access if necessary (supported by Alibaba Cloud Redis)

4. Delete operation

1. Hash delete: hscan + hdel
public void delBigHash(String host, int port, String password, String bigHashKey) {
    Jedis jedis = new Jedis(host, port);
    if (password != null && !"".equals(password)) {
        jedis.auth(password);
    }
    ScanParams scanParams = new ScanParams().count(100);
    String cursor = "0";
    do {
        ScanResult<Entry<String, String>> scanResult = jedis.hscan(bigHashKey, cursor, scanParams);
        List<Entry<String, String>> entryList = scanResult.getResult();
        if (entryList != null && !entryList.isEmpty()) {
            for (Entry<String, String> entry : entryList) {
                jedis.hdel(bigHashKey, entry.getKey());
            }
        }
        cursor = scanResult.getStringCursor();
    } while (!"0".equals(cursor));
    
    // delete bigkey
    jedis.del(bigHashKey);
}

2. List delete: ltrim
public void delBigList(String host, int port, String password, String bigListKey) {
    Jedis jedis = new Jedis(host, port);
    if (password != null && !"".equals(password)) {
        jedis.auth(password);
    }
    long llen = jedis.llen (bigListKey);
    int counter = 0;
    int left = 100;
    while (counter < llen) {
        //Truncate 100 pieces from the left each time
        jedis.ltrim(bigListKey, left, llen);
        counter += left;
    }
    //finally delete the key
    jedis.del(bigListKey);
}

3. Set delete: sscan + srem
public void delBigSet(String host, int port, String password, String bigSetKey) {
    Jedis jedis = new Jedis(host, port);
    if (password != null && !"".equals(password)) {
        jedis.auth(password);
    }
    ScanParams scanParams = new ScanParams().count(100);
    String cursor = "0";
    do {
        ScanResult<String> scanResult = jedis.sscan(bigSetKey, cursor, scanParams);
        List<String> memberList = scanResult.getResult();
        if (memberList != null && !memberList.isEmpty()) {
            for (String member : memberList) {
                jedis.srem(bigSetKey, member);
            }
        }
        cursor = scanResult.getStringCursor();
    } while (!"0".equals(cursor));
    
    // delete bigkey
    jedis.del (bigSetKey);
}

4. SortedSet delete: zscan + zrem
public void delBigZset(String host, int port, String password, String bigZsetKey) {
    Jedis jedis = new Jedis(host, port);
    if (password != null && !"".equals(password)) {
        jedis.auth(password);
    }
    ScanParams scanParams = new ScanParams().count(100);
    String cursor = "0";
    do {
        ScanResult<Tuple> scanResult = jedis.zscan(bigZsetKey, cursor, scanParams);
        List<Tuple> tupleList = scanResult.getResult();
        if (tupleList != null && !tupleList.isEmpty()) {
            for (Tuple tuple : tupleList) {
                jedis.zrem(bigZsetKey, tuple.getElement());
            }
        }
        cursor = scanResult.getStringCursor();
    } while (!"0".equals(cursor));
    
    // delete bigkey
    jedis.del(bigZsetKey);
}


Reprinted from: https://yq.aliyun.com/articles/531067

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326118727&siteId=291194637