Recently, I have been learning Redis intensively and writing while learning

Like it before you read it, make it a habit

SortSet type usage instructions

Zset is probably the most distinctive data structure provided by Redis, and it is also the most popular data structure that interviewers ask about in interviews.

  • On the one hand, it’s a set, which ensures that value is unique,
  • On the one hand, it can give each value a score, which represents the sorting weight.

Its internal implementation uses a data structure called a “skip list”.

SortSet common command

After the last value in the zset is removed, the data structure is automatically deleted and the memory is reclaimed.

>Zadd books 9.0"think in java"
>Zadd books 8.9"java concurrency"
>Zadd books 8.6"java cookbook"

> zrange books 0 -1     # List in order of score, parameter range is the ranking range
1) "java cookbook"
2) "java concurrency"
3) "think in java"

> zrevrange books 0 -1  # List in reverse order according to score, parameter range is the ranking range
1) "think in java"
2) "java concurrency"
3) "java cookbook"

> zcard books           # equals count()
(integer) 3

> zscore books "java concurrency"   Get the score of the specified value"8.9000000000000004" # Internal score is stored as double, so there is a problem with decimal accuracy
> zrank books "java concurrency"    Rank #
(integer) 1

>Zrangebyscore books 0, 8.91Walk through zset according to the score interval
1) "java cookbook"
2) "java concurrency"

>Zrangebyscore books -inf 8.91 withscoresIterate over zset according to the score interval (-∞, 8.91) and return the score. Inf stands for infinite.1) "Java Cookbook" 2) "Java concurrency"
> zrem books "java concurrency"             # to delete the value
(integer) 1
> zrange books 0 -1
1) "java cookbook"
2) "think in java"
Copy the code

Three, use scenarios

list

  • Fan list, value is the fan’s user ID, score is the attention time
  • Video websites need to make leaderboards for videos uploaded by users. The maintenance of the leaderboards may be in many aspects: by time, by play quantity, by the number of likes obtained, etc.

A good example of this happens to be the Redis Practice Top Articles list I wrote earlier

Weight queue/delay queue

For example: the order is overdue, cancel the order, restore inventory.

The recommendation for strict (no-lose) message queues is to use Kafka, professional MQ. These professional message-oriented middleware provide many features, of course, its deployment, use and maintenance are more troublesome. If you are less demanding about message queues and want something lightweight, use Redis.

PHP – Delay queue instance

The following code increases robustness:

  • function run()Lua is required to implement itatomicoperation
  • It can be considered to establish task queues & executed queues in persistent databases such as MySQL and MongoDB to further tolerate faults

      

trait RedisConnectTrait
{
    private $servers = array(a);private $instances = array(a);/** * Set the Redis configuration *@param array $serversConfig
     * @return $this
     * @throws Exception
     */
    private function setServers( array $serversConfig = [ [ '127.0.0.1'.6379.0.01]])
    {
        if ( !$serversConfig )
            throw new \Exception( 'Redis link configuration cannot be null '.false );

        $this->servers = $serversConfig;
        return $this;
    }

    private function initInstances(a)
    {
        if (empty($this->instances)) {
            foreach ($this->servers as $server) {
                list($host, $port, $timeout) = $server;

                $redis = new \Redis();
                $redis->connect($host, $port, $timeout);
                // $redis->select( ['index'] );

                $this->instances[] = $redis; }}}}class RedisDelayQueueUtil
{
    use RedisConnectTrait;

    const QUEUE_PREFIX = 'delay_queue:';
    protected $redis = null;
    protected $key = ' ';

    public function __construct( string $queueName, array $config = [] )
    {
        $instances = $this->setServers( $config )->initInstances();

        $this->key = self::QUEUE_PREFIX . $queueName;
        $this->redis = $instances[ 0 ];
        // $this->redis->auth($config['auth']);
    }

    public function delTask($value)
    {
        return $this->redis->zRem($this->key, $value);
    }

    public function getTask(a)
    {
        // Get the task, 0 and the current time as the interval, return a record
        return $this->redis->zRangeByScore( $this->key, 0, time(), [ 'limit'= > [0.1]]); }public function addTask($name, $time, $data)
    {
        // Add tasks, and sort the task queue from smallest to largest by time, using time as score
        return $this->redis->zAdd(
            $this->key,
            $time,
            json_encode([
                'task_name' => $name,
                'task_time' => $time,
                'task_params' => $data,
            ], JSON_UNESCAPED_UNICODE )
        );
    }

    public function run(a)
    {
        // Take one task at a time
        $task = $this->getTask();
        if (empty($task)) {
            return false;
        }

        $task = $task[0];
        if ($this->delTask($task)) {
            $task = json_decode($task, true);
            // Process tasks
            echo 'Task:' . $task['task_name'].'Runtime:' . date('Y-m-d H:i:s') . PHP_EOL;

            return true;
        }

        return false;
    }
}

$dq = new RedisDelayQueueUtil('close_order'['host'= >'127.0.0.1'.'port'= >6379.'auth'= >' '.'timeout'= >60,]); $dq->addTask('close_order_111', time() + 30['order_id'= >'111']);
$dq->addTask('close_order_222', time() + 60['order_id'= >'222']);
$dq->addTask('close_order_333', time() + 90['order_id'= >'333']);

set_time_limit(0);

$i2Count = 0;
while ( 10 < $i2Count ) {
    $dq->run();
    usleep(100000);
    $i2Count++;
}

Copy the code