Analysis of Redis ActiveRecord in Yii 2.0 that the primary key ID is duplicated and resolved
1. The request interface, the total number of resources in the response parameters is 30. Resources containing ids equal to 37918 are duplicates. A total of 2. as shown in Figure 1
{
"code": 10000,
"message": "获取 CMC 用户列表成功",
"data": {
"items": [
{
"user_birthday": "1990-01-01",
"login_name": "xianwanzhou",
"add_time": "2020-03-31 09:41:07",
"user_email": "",
"group_id": "643d80843ae23bcfa95b75bae30a7656",
"id": "37918",
"user_pic": "http://uploads.cmc.lzgbdst.com/uploads/cmc_user_avatar/default_header.png",
"update_time": "2020-03-31 09:43:16",
"is_open": "1",
"user_nick": "鲜万州",
"user_mobile": "15208396209",
"user_token": "6a1de11e594d61790963eaaf1d9bee8d",
"user_chat_id": "f98e3b834f577cc3d83d74323cd3094d",
"user_type": "2",
"user_sex": "2"
},
{
"user_birthday": "1990-01-01",
"login_name": "xianwanzhou",
"add_time": "2020-03-31 09:41:07",
"user_email": "",
"group_id": "643d80843ae23bcfa95b75bae30a7656",
"id": "37918",
"user_pic": "http://uploads.cmc.lzgbdst.com/uploads/cmc_user_avatar/default_header.png",
"update_time": "2020-03-31 09:43:16",
"is_open": "1",
"user_nick": "鲜万州",
"user_mobile": "15208396209",
"user_token": "6a1de11e594d61790963eaaf1d9bee8d",
"user_chat_id": "f98e3b834f577cc3d83d74323cd3094d",
"user_type": "2",
"user_sex": "2"
}
],
"_links": {
"self": {
"href": "http://pcsapi.cmc.lzgbdst.com/v1/cmc-users?login_id=7309cba1c93fc0a80663007612b784b8&login_tid=25f49c543b8ec31c6d905def0ad99913&per-page=30&page=1"
}
},
"_meta": {
"totalCount": 30,
"pageCount": 1,
"currentPage": 1,
"perPage": 30
}
}
}
2. Check the model class, /common/models/redis/cmc_console/user.php
<?php
namespace common\models\redis\cmc_console;
use Yii;
use common\components\redis\ActiveRecord;
/**
* This is the model class for table "{{%user}}".
*
* @property string $id
* @property string $group_id
* @property string $login_name
* @property string $user_token
* @property string $user_nick
* @property string $user_pic
* @property string $user_mobile
* @property string $user_email
* @property string $user_sex
* @property string $user_birthday
* @property string $user_type
* @property string $user_chat_id
* @property string $is_open
* @property string $add_time
* @property string $update_time
*/
class User extends ActiveRecord
{
/**
* @return array the list of attributes for this record
*/
public function attributes()
{
return ['id', 'group_id', 'login_name', 'user_token', 'user_nick', 'user_pic', 'user_mobile', 'user_email', 'user_sex', 'user_birthday', 'user_type', 'user_chat_id', 'is_open', 'add_time', 'update_time'];
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['id', 'group_id', 'login_name', 'user_token', 'user_nick', 'user_pic', 'user_mobile', 'user_email', 'user_sex', 'user_birthday', 'user_type', 'user_chat_id', 'is_open', 'add_time', 'update_time'], 'safe'],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('model/redis/cmc-console/user', 'ID'),
'group_id' => Yii::t('model/redis/cmc-console/user', 'Group ID'),
'login_name' => Yii::t('model/redis/cmc-console/user', 'Login Name'),
'user_token' => Yii::t('model/redis/cmc-console/user', 'User Token'),
'user_nick' => Yii::t('model/redis/cmc-console/user', 'User Nick'),
'user_pic' => Yii::t('model/redis/cmc-console/user', 'User Pic'),
'user_mobile' => Yii::t('model/redis/cmc-console/user', 'User Mobile'),
'user_email' => Yii::t('model/redis/cmc-console/user', 'User Email'),
'user_sex' => Yii::t('model/redis/cmc-console/user', 'User Sex'),
'user_type' => Yii::t('model/redis/cmc-console/user', 'User Type'),
'user_birthday' => Yii::t('model/redis/cmc-console/user', 'User Birthday'),
'user_chat_id' => Yii::t('model/redis/cmc-console/user', 'User Chat Id'),
'is_open' => Yii::t('model/redis/cmc-console/user', 'Is Open'),
'add_time' => Yii::t('model/redis/cmc-console/user', 'Add Time'),
'update_time' => Yii::t('model/redis/cmc-console/user', 'Update Time'),
];
}
}
3. Check /common/components/redis/activerecord.php , which defines the prefix and applies to all AR keys.
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/02/05
* Time: 9:47
*/
namespace common\components\redis;
use Yii;
class ActiveRecord extends \yii\redis\ActiveRecord
{
/**
* Declares prefix of the key that represents the keys that store this records in redis.
* By default this method returns the class name as the table name by calling [[Inflector::camel2id()]].
* For example, 'Customer' becomes 'customer', and 'OrderItem' becomes
* 'order_item'. You may override this method if you want different key naming.
* @return string the prefix to apply to all AR keys
*/
public static function keyPrefix()
{
return Yii::$app->params['redisActiveRecord']['keyPrefix'] . parent::keyPrefix();
}
}
4. Open RedisDesktopManager, check the total number of users, and determine it to 29, as shown in Figure 2
5. Open RedisDesktopManager, and determine that the primary key value is 37918 to be 1, which is not repeated. as shown in Figure 3
6. Check the values of PA:AR:USER, and find that the values of rows 29 and 30 are all 37918. From this, it is determined that the value of this key results in the number of resources with the ID equal to 37918 equal to 2. as shown in Figure 4
7. Delete the 30th line of PA:AR:USER, as shown in Figure 5
8. Request the interface again, the total number of resources in the response parameters is 29. Resources containing id equals 37918 are not duplicated. Only one left.
{
"code": 10000,
"message": "获取 CMC 用户列表成功",
"data": {
"items": [
{
"user_birthday": "1990-01-01",
"login_name": "xianwanzhou",
"add_time": "2020-03-31 09:41:07",
"user_email": "",
"group_id": "643d80843ae23bcfa95b75bae30a7656",
"id": "37918",
"user_pic": "http://uploads.cmc.lzgbdst.com/uploads/cmc_user_avatar/default_header.png",
"update_time": "2020-03-31 09:43:16",
"is_open": "1",
"user_nick": "鲜万州",
"user_mobile": "15208396209",
"user_token": "6a1de11e594d61790963eaaf1d9bee8d",
"user_chat_id": "f98e3b834f577cc3d83d74323cd3094d",
"user_type": "2",
"user_sex": "2"
}
],
"_links": {
"self": {
"href": "http://pcsapi.cmc.lzgbdst.com/v1/cmc-users?login_id=7309cba1c93fc0a80663007612b784b8&login_tid=25f49c543b8ec31c6d905def0ad99913&per-page=29&page=1"
}
},
"_meta": {
"totalCount": 29,
"pageCount": 1,
"currentPage": 1,
"perPage": 29
}
}
}
9. Prepare to reproduce the case of the ID primary key duplication in the local environment. The request interface, the total number of resources in the response parameters is 13. The ID primary key is not repeated. as shown in Figure 6
{
"code": 10000,
"message": "获取 CMC 用户列表成功",
"data": {
"items": [
{
"login_name": "13281105967",
"update_time": "2019-12-11 14:28:26",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "13281105967",
"user_sex": "2",
"user_mobile": "13281105967",
"user_type": "1",
"is_open": "1",
"user_chat_id": "ede7616c5e4232896453202cd0c3f7ec",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/20190219/1550570817-4LLQJJ.png",
"id": "3",
"add_time": "2018-04-26 10:05:28",
"user_birthday": "1990-01-01",
"user_email": "13281105967@chinamcloud.com",
"user_token": "fb46626f0e71e423ca8ab4c750620a85"
},
{
"login_name": "test10",
"update_time": "2019-12-11 15:00:38",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test10",
"user_sex": "2",
"user_mobile": "13980074657",
"user_type": "2",
"is_open": "1",
"user_chat_id": "ce524778954bd10d5a0ff65dadc0354b",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "4",
"add_time": "2019-12-11 14:55:07",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "bc8daab7ba8620c132cdf4e5de1d4758"
},
{
"login_name": "jmj12130003",
"update_time": "2019-12-13 14:41:55",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "jmj1213",
"user_sex": "2",
"user_mobile": "18412130003",
"user_type": "2",
"is_open": "1",
"user_chat_id": "84e1bb32ffa895e56d950bbfa24fefc7",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "49",
"add_time": "2019-12-13 14:41:55",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "ba0ca65da7c3048fd9d449bb0d21a39b"
},
{
"login_name": "test11",
"update_time": "2019-12-17 11:14:53",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test11",
"user_sex": "2",
"user_mobile": "13980074650",
"user_type": "2",
"is_open": "1",
"user_chat_id": "bc1650a6834fc490de65a4527dfc8ae5",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "64",
"add_time": "2019-12-17 11:14:53",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "04532bb62deb99bf229698c9e1a81da1"
},
{
"login_name": "test12",
"update_time": "2019-12-17 11:15:14",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test12",
"user_sex": "2",
"user_mobile": "13980074651",
"user_type": "2",
"is_open": "1",
"user_chat_id": "fa154673421e5a3731991498397d712d",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "65",
"add_time": "2019-12-17 11:15:14",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "bcdc9e3781180b7bc18bc0e38777a467"
},
{
"login_name": "test13",
"update_time": "2019-12-17 11:15:35",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test13",
"user_sex": "2",
"user_mobile": "13980074652",
"user_type": "2",
"is_open": "1",
"user_chat_id": "35ce7075c1c57bb6c66d0f67a7840383",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "66",
"add_time": "2019-12-17 11:15:35",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "633cae769e274cabd4441acb7be1c5a1"
},
{
"login_name": "test14",
"update_time": "2019-12-17 11:15:55",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test14",
"user_sex": "2",
"user_mobile": "13980074654",
"user_type": "2",
"is_open": "1",
"user_chat_id": "3190c55b297b51b38463da4eae6bbd95",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "67",
"add_time": "2019-12-17 11:15:55",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "84c5871da19f7a489234af73c491f74f"
},
{
"login_name": "test15",
"update_time": "2019-12-17 11:16:16",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test15",
"user_sex": "2",
"user_mobile": "13980074655",
"user_type": "2",
"is_open": "1",
"user_chat_id": "fd072f598ec1a978f5fb968dfa386f0d",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "68",
"add_time": "2019-12-17 11:16:16",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "5bb37b4045e9ad6eb1cc398d3170d33e"
},
{
"login_name": "test16",
"update_time": "2019-12-17 11:16:36",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test16",
"user_sex": "2",
"user_mobile": "13980074656",
"user_type": "2",
"is_open": "1",
"user_chat_id": "88178648656ae259bae213ee00ccb4c7",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "69",
"add_time": "2019-12-17 11:16:36",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "2926796eb8e990aa8bd726e121cb91e8"
},
{
"login_name": "test17",
"update_time": "2019-12-17 11:17:07",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test17",
"user_sex": "2",
"user_mobile": "13980074653",
"user_type": "2",
"is_open": "1",
"user_chat_id": "b03d6e7b4db061d52b3d420844a5dde8",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "70",
"add_time": "2019-12-17 11:17:07",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "bf028bc0353bf8ff070bfd62490ae284"
},
{
"login_name": "test18",
"update_time": "2019-12-17 11:17:25",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test18",
"user_sex": "2",
"user_mobile": "13980074658",
"user_type": "2",
"is_open": "1",
"user_chat_id": "c1eddd55f8efcec8da1e0cc6fc1a5624",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "71",
"add_time": "2019-12-17 11:17:25",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "4adbe2313b7e4967ac518e4e0a73f5c9"
},
{
"login_name": "test19",
"update_time": "2019-12-17 11:17:41",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "test19",
"user_sex": "2",
"user_mobile": "13980074659",
"user_type": "2",
"is_open": "1",
"user_chat_id": "5bf1e9f7e4bf9aa2d8a633eddf628710",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "72",
"add_time": "2019-12-17 11:17:41",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "dd7ab3f1fb3e8651b35ba070d10594c7"
},
{
"login_name": "15708495493",
"update_time": "2020-03-02 14:31:36",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "clover",
"user_sex": "2",
"user_mobile": "15708495493",
"user_type": "2",
"is_open": "1",
"user_chat_id": "251f91338781d5354e08c1351ca3342d",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/default_header.png",
"id": "166",
"add_time": "2020-03-02 14:31:36",
"user_birthday": "1990-01-01",
"user_email": "",
"user_token": "ff94d3f7b1dafada193ae7d6a82fa628"
}
],
"_links": {
"self": {
"href": "http://api.pcs-api.localhost/v1/cmc-users?login_id=2e368664c41b8bf511bcc9c65d86dbc3&login_tid=efda7e64b7747f8c4360b29aa9c18f77&per-page=13&page=1"
}
},
"_meta": {
"totalCount": 13,
"pageCount": 1,
"currentPage": 1,
"perPage": 13
}
}
}
10. During the program execution, when the data is inserted into the Redis, it will be judged whether the ID exists. If it exists, it will be updated, and if it does not exist, it will be inserted. It is initially suspected that in the case of concurrent requests. Insertion is performed.
$redisCmcConsoleUser = new RedisCmcConsoleUser();
$redisCmcConsoleUserResult = $redisCmcConsoleUser->initSync(['group_id' => $groupInfo['group_id']], $loginId, $loginTid);
if ($redisCmcConsoleUserResult === false) {
throw new NotFoundHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '201041'), ['id' => $loginId])), 201041);
}
$redisCmcConsoleUserItem = $redisCmcConsoleUser::find()->where(['id' => $userInfo['id'], 'group_id' => Yii::$app->params['groupId']])->one();
/* 如果资源不存在,则插入;否则更新 */
$redisCmcConsoleUserAttributes = [
'id' => $userInfo['id'],
'group_id' => $groupInfo['group_id'],
'login_name' => $userInfo['login_name'],
'user_token' => $userInfo['user_token'],
'user_nick' => $userInfo['user_nick'],
'user_pic' => $userInfo['user_pic'],
'user_mobile' => $userInfo['user_mobile'] ? $userInfo['user_mobile'] : '',
'user_email' => $userInfo['user_email'] ? $userInfo['user_email'] : '',
'user_sex' => $userInfo['user_sex'],
'user_type' => $userInfo['user_type'],
'user_birthday' => $userInfo['user_birthday'],
'user_chat_id' => $userInfo['user_chat_id'] ? $userInfo['user_chat_id'] : '',
'is_open' => $userInfo['is_open'],
'add_time' => $userInfo['add_time'],
'update_time' => $userInfo['update_time'],
];
if (!isset($redisCmcConsoleUserItem)) {
$redisCmcConsoleUser->attributes = $redisCmcConsoleUserAttributes;
$redisCmcConsoleUser->insert();
// 设置用户身份为已认证
Yii::$app->user->setIdentity($redisCmcConsoleUser);
} else {
$redisCmcConsoleUserItem->attributes = $redisCmcConsoleUserAttributes;
$redisCmcConsoleUserItem->save();
// 设置用户身份为已认证
Yii::$app->user->setIdentity($redisCmcConsoleUserItem);
}
11. During program execution, when inserting data into Redis, regardless of whether the ID exists, it is inserted. The request interface, the total number of resources in the response parameters is 14. Resources with IDs equal to 3 are duplicates. A total of 2. as shown in Figure 7
if (!isset($redisCmcConsoleUserItem)) {
$redisCmcConsoleUser->attributes = $redisCmcConsoleUserAttributes;
$redisCmcConsoleUser->insert();
// 设置用户身份为已认证
Yii::$app->user->setIdentity($redisCmcConsoleUser);
} else {
$redisCmcConsoleUserItem->attributes = $redisCmcConsoleUserAttributes;
$redisCmcConsoleUserItem->insert();
// 设置用户身份为已认证
Yii::$app->user->setIdentity($redisCmcConsoleUserItem);
}
{
"code": 10000,
"message": "获取 CMC 用户列表成功",
"data": {
"items": [
{
"login_name": "13281105967",
"update_time": "2019-12-11 14:28:26",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "13281105967",
"user_sex": "2",
"user_mobile": "13281105967",
"user_type": "1",
"is_open": "1",
"user_chat_id": "ede7616c5e4232896453202cd0c3f7ec",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/20190219/1550570817-4LLQJJ.png",
"id": "3",
"add_time": "2018-04-26 10:05:28",
"user_birthday": "1990-01-01",
"user_email": "13281105967@chinamcloud.com",
"user_token": "fb46626f0e71e423ca8ab4c750620a85"
},
{
"login_name": "13281105967",
"update_time": "2019-12-11 14:28:26",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "13281105967",
"user_sex": "2",
"user_mobile": "13281105967",
"user_type": "1",
"is_open": "1",
"user_chat_id": "ede7616c5e4232896453202cd0c3f7ec",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/20190219/1550570817-4LLQJJ.png",
"id": "3",
"add_time": "2018-04-26 10:05:28",
"user_birthday": "1990-01-01",
"user_email": "13281105967@chinamcloud.com",
"user_token": "fb46626f0e71e423ca8ab4c750620a85"
}
],
"_links": {
"self": {
"href": "http://api.pcs-api.localhost/v1/cmc-users?login_id=2e368664c41b8bf511bcc9c65d86dbc3&login_tid=efda7e64b7747f8c4360b29aa9c18f77&per-page=14&page=1"
}
},
"_meta": {
"totalCount": 14,
"pageCount": 1,
"currentPage": 1,
"perPage": 14
}
}
}
12. It can be confirmed that Redis ActiveRecord cannot ensure the uniqueness of the primary key ID. At this stage, there are 2 solutions, and the first option is to implement unique locking based on Redis when inserting records. The second option is to deduplicate when queries. Decided to adopt the second option. Since Redis does not support SQL queries, the query API is limited to the following methods: WHERE(), LIMIT(), OFFSET() , ORDERBY() , and indexBy() . (OrderBy() has not yet been implemented: #1305). Based on indexBy(). The request interface, the total number of resources in the response parameters is 13. The ID primary key is not repeated. However, the value of totalCount is 14. Statistical error. as shown in Figure 8
// 查询当前用户所属租户 ID 下的 CMC 的用户模型(Redis)
$query = $modelClass::find()
->where([
'group_id' => $identity->group_id,
'is_open' => $modelClass::STATUS_ENABLED
])
->indexBy('id');
{
"code": 10000,
"message": "获取 CMC 用户列表成功",
"data": {
"items": [
{
"login_name": "13281105967",
"update_time": "2019-12-11 14:28:26",
"group_id": "015ce30b116ce86058fa6ab4fea4ac63",
"user_nick": "13281105967",
"user_sex": "2",
"user_mobile": "13281105967",
"user_type": "1",
"is_open": "1",
"user_chat_id": "ede7616c5e4232896453202cd0c3f7ec",
"user_pic": "https://pgcupload.flydev.chinamcloud.cn/uploads/cmc_user_avatar/20190219/1550570817-4LLQJJ.png",
"id": "3",
"add_time": "2018-04-26 10:05:28",
"user_birthday": "1990-01-01",
"user_email": "13281105967@chinamcloud.com",
"user_token": "fb46626f0e71e423ca8ab4c750620a85"
}
],
"_links": {
"self": {
"href": "http://api.pcs-api.localhost/v1/cmc-users?login_id=2e368664c41b8bf511bcc9c65d86dbc3&login_tid=efda7e64b7747f8c4360b29aa9c18f77&per-page=14&page=1"
}
},
"_meta": {
"totalCount": 14,
"pageCount": 1,
"currentPage": 1,
"perPage": 14
}
}
}
13. Therefore, try to adopt the first option. However, since the implementation of the program here is a process that all requests will execute, I am worried that the lock will reduce the performance of the program, and finally decide to give up the insertion and only do the update. Insert if the user does not exist in Redis; otherwise update. Adjusted to: if the user does not exist in Redis, then the response 404; otherwise, update.
/* 如果资源不存在,则响应 404 */
if (!isset($redisCmcConsoleUserItem)) {
throw new NotFoundHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '201011'), ['user_nick' => $userInfo['user_nick']])), 201011);
}
/* 更新 */
$redisCmcConsoleUserItem->attributes = $redisCmcConsoleUserAttributes;
$redisCmcConsoleUserItem->save();
// 设置用户身份为已认证
Yii::$app->user->setIdentity($redisCmcConsoleUserItem);
14. If the user does not exist in Redis, then the response 404. as shown in Figure 9
15. However, this repair only prevents the problem of user duplication in the future, and users who have been repeated before are still duplicated. If you want to remove the weight, you need to manually operate Redis. And this fix will lead to a new problem affecting the experience, that is, after adding a new user B to the framework, if user B does not exist in Redis, user B cannot use the planning command. You need to wait until user B is synchronized to Redis before it can be used.








