实战篇之基于二进制思想的用户标签系统(Mysql+SpringBoot)

        一: 计算机中的二进制

        计算机以二进制表示数据,以表示电路中的正反。在二进制下,一个位只有 0 和 1 。逢二进一 位。类似十进制下,一个位只有 0~9 。逢十进一位。

        二: 进制常用运算 (位运算)

  • 与运算(&):将两个二进制数的对应位进行与操作,只有当两个位都为1时,结果为1。
  • 或运算(|):将两个二进制数的对应位进行或操作,只要有一个位为1,结果就为1。
  • 非运算(~):对一个二进制数的每个位取反,将1变为0,将0变为1。
  • 异或运算(^):将两个二进制数的对应位进行异或操作,只有当两个位不同时,结果为1。
  • 左移运算(<<):将一个二进制数的所有位向左移动指定的位数,右边空出的位用0填充。
  • 右移运算(>>):将一个二进制数的所有位向右移动指定的位数,左边空出的位用原来的最高位填充。 这些二进制的运算在计算机的逻辑设计、编程和数据处理中经常使用。
  • 无符号右移( >>> , 无符号右移就是右移之后,无论该数为正还是为负,右移之后左边都是补上 0

        三: 标签记录的实现原理

        基于(或)|,与+取反(&~) 去实现:

        假设我们给用户添加的标签是一个数字 16 ,转换为二进制就是 10000
       1.设置标签  使用 或(|) (参加运算的两个位只要有一个为 1 ,其值为 1

        

        2.取消标签 与 + 取反(&~)(两位同时为 1,结果才为 1,否则为 0取消16这个标签

        四:一起动手实现用户标签系统 - 底层标签读写组件的实现

                4.1: 建立用户标签表SQL

CREATE TABLE `t_user_tag` (
 `user_id` bigint NOT NULL DEFAULT -1 COMMENT '用户 id',
 `tag_info_01` bigint NOT NULL DEFAULT '0' COMMENT '标签记录字段',
 `tag_info_02` bigint NOT NULL DEFAULT '0' COMMENT '标签记录字段',
 `tag_info_03` bigint NOT NULL DEFAULT '0' COMMENT '标签记录字段',
 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时
间',
 `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP COMMENT '更新时间',
 PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin 
COMMENT='用户标签记录';

                4.2:service层接口

package com.laoyang.provider.service;

import com.laoyang.constants.UserTagsEnum;

/**
 * @author:Kevin
 * @create: 2023-08-01 09:53
 * @Description:
 */

public interface IUserTagService {

    /**
     * 设置标签 只能设置成功一次
     *
     * @param userId
     * @param userTagsEnum
     * @return
     */
    boolean setTag(Long userId, UserTagsEnum userTagsEnum);
    /**
     * 取消标签
     *
     * @param userId
     * @param userTagsEnum
     * @return
     */
    boolean cancelTag(Long userId, UserTagsEnum userTagsEnum);
    /**
     * 是否包含某个标签
     *
     * @param userId
     * @param userTagsEnum
     * @return
     */
    boolean containTag(Long userId,UserTagsEnum userTagsEnum);
}
                4.3: service实现接口
package com.laoyang.provider.service.impl;

import com.laoyang.common.utils.ConvertBeanUtils;
import com.laoyang.constants.UserTagFieldNameConstants;
import com.laoyang.constants.UserTagsEnum;
import com.laoyang.dto.UserTagDTO;
import com.laoyang.framework.redis.key.UserProviderCacheKeyBuilder;
import com.laoyang.provider.dao.mapper.IUserTagMapper;
import com.laoyang.provider.dao.po.UserTagPO;
import com.laoyang.provider.service.IUserTagService;
import com.laoyang.usils.TagInfoUtils;
import jakarta.annotation.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.nio.charset.StandardCharsets;

/**
 * @author:Kevin
 * @create: 2023-08-01 09:54
 * @Description:
 */

public class UserTagServiceImpl implements IUserTagService {

    @Resource
    private IUserTagMapper userTagMapper;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    private RedisTemplate<String, UserTagDTO> userTagDTORedisTemplate;

    @Resource
    private UserProviderCacheKeyBuilder cacheKeyBuilder;

    @Override
    public boolean setTag(Long userId, UserTagsEnum userTagsEnum) {
        boolean updateStatus = userTagMapper.setTag(userId,userTagsEnum.getFieldName(),userTagsEnum.getTag()) > 0;
        if (updateStatus){
            String redisKey = cacheKeyBuilder.buildtagInfoKey(userId);
            userTagDTORedisTemplate.delete(redisKey);
            return  true;
        }
        String key = cacheKeyBuilder.buildTagLockKey(userId);
        //TODO 分布式锁 实现多个线程之间对同一个资源的互斥访问,保证同一时间只有一个线程能够获取到锁并执行相应的操作
        String setNxResult = redisTemplate.execute(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer keySerializer = redisTemplate.getKeySerializer();
                RedisSerializer valueSerializer = redisTemplate.getValueSerializer();
                String result = (String) connection.execute("set", keySerializer.serialize(key),
                        valueSerializer.serialize("-1"),
                        "NX".getBytes(StandardCharsets.UTF_8),
                        "EX".getBytes(StandardCharsets.UTF_8),
                        "3".getBytes(StandardCharsets.UTF_8));
                return result;
            }
        });

        if (!"OK".equals(setNxResult)){
            return false;
        }

        UserTagPO userTagPO = userTagMapper.selectById(userId);
        if (userTagPO!=null){
            return false;
        }
        userTagPO = new UserTagPO();
        userTagPO.setUserId(userId);
        userTagMapper.insert(userTagPO);
        updateStatus = userTagMapper.setTag(userId,userTagsEnum.getFieldName(),userTagsEnum.getTag()) > 0;
        redisTemplate.delete(key);
        return updateStatus;
    }

    @Override
    public boolean cancelTag(Long userId, UserTagsEnum userTagsEnum) {
        boolean cancleStatus = userTagMapper.cancelTag(userId,userTagsEnum.getFieldName(),userTagsEnum.getTag()) > 0;
        if (cancleStatus){
            return false;
        }
        String redisKey = cacheKeyBuilder.buildtagInfoKey(userId);
        userTagDTORedisTemplate.delete(redisKey);
        return true;
    }

    @Override
    public boolean containTag(Long userId, UserTagsEnum userTagsEnum) {
        UserTagDTO userTagDTO = this.queryByUserId(userId);
        if (userTagDTO == null) {
            return false;
        }
        String queryFieldName = userTagsEnum.getFieldName();
        if
        (UserTagFieldNameConstants.TAG_INFO_01.equals(queryFieldName)) {
            return
                    TagInfoUtils.isContain(userTagDTO.getTagInfo01(),
                            userTagsEnum.getTag());
        } else if
        (UserTagFieldNameConstants.TAG_INFO_02.equals(queryFieldName)) {
            return
                    TagInfoUtils.isContain(userTagDTO.getTagInfo02(),
                            userTagsEnum.getTag());
        } else if
        (UserTagFieldNameConstants.TAG_INFO_03.equals(queryFieldName)) {
            return
                    TagInfoUtils.isContain(userTagDTO.getTagInfo03(),
                            userTagsEnum.getTag());
        }
        return false;
    }

    /**
     * 从redis查询用户标签
     * @param userId
     * @return
     */
    private UserTagDTO queryByUserId(Long userId){
        String redisKey = cacheKeyBuilder.buildtagInfoKey(userId);
        UserTagDTO userTagDTO = userTagDTORedisTemplate.opsForValue().get(redisKey);
        if (userTagDTO != null){
            return userTagDTO;
        }
        UserTagPO userTagPO = userTagMapper.selectById(userId);
        if (userTagPO == null){
            return null;
        }
        userTagDTO = ConvertBeanUtils.convert(userTagPO,UserTagDTO.class);
        userTagDTORedisTemplate.opsForValue().set(redisKey, userTagDTO);

        return userTagDTO;

    }


}

        说明:我们使用了redis作为缓存,mybatisplus, 并自行创建了redis业务主键生成工具类等等,会放在最后,先把核心代码呈现。这里说明下使用到了redis分布式实现

这段代码是使用RedisTemplate执行一个"set"命令,并设置了一些选项参数。下面对代码进行解释:

  1. 首先,通过redisTemplate.getKeySerializer()获取key的序列化器,通过redisTemplate.getValueSerializer()获取value的序列化器。
  2. 在RedisCallback的doInRedis方法中,通过RedisConnection的execute方法执行"set"命令。
  3. 参数中,keySerializer.serialize(key)将key序列化为字节数组,valueSerializer.serialize("-1")将value序列化为字节数组。
  4. "NX".getBytes(StandardCharsets.UTF_8)表示设置NX选项,即只有在key不存在时才进行set操作。
  5. "EX".getBytes(StandardCharsets.UTF_8)表示设置EX选项,即设置key的过期时间为3秒。
  6. "3".getBytes(StandardCharsets.UTF_8)表示设置key的过期时间为3秒。
  7. connection.execute方法返回的是一个Object类型的结果,需要将其转换为String类型并返回。 总体来说,这段代码的作用是在Redis中执行一个set命令,将key和value存储到Redis中,并设置了过期时间和NX选项,确保只有在key不存在时才进行set操作。

        

        当多个节点同时尝试执行set操作来设置同一个key时,只有一个节点能够成功设置,因为Redis中的set命令默认具有原子性。如果设置了NX选项,即只有在key不存在时才进行set操作,那么只有第一个节点能够成功设置该key,其他节点将无法设置。 通过利用这个特性,可以将某个共享资源对应的key作为锁的名称,多个节点试图通过set操作来竞争该锁。只有一个节点能够成功设置该锁的key,即获得了分布式锁。其他节点则在设置失败后,可以选择等待或者进行其他处理。 同时,为了避免因为某个节点获得锁后发生故障而导致锁一直无法释放,还可以为锁设置过期时间。当锁的持有者在一定时间后未能释放锁,锁将自动过期并被其他节点获取。 综上所述,通过使用Redis的set操作和一些选项参数,可以实现简单的分布式锁。多个节点可以通过竞争设置同一个key来获得锁,并通过设置过期时间来避免因为锁的持有者发生故障而导致锁一直无法释放。

                4.4: Mapper层
package com.laoyang.provider.dao.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.laoyang.provider.dao.po.UserTagPO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Update;

/**
 * @author:Kevin
 * @create: 2023-08-01 09:54
 * @Description:
 */
@Mapper
public interface IUserTagMapper extends BaseMapper<UserTagPO> {

    /**
     * 使用或的思路来设置标签,只能允许第一次设置成功
     * @param userId
     * @param fieldName
     * @param tag
     * @return
     */
    @Update("update t_user_tag set ${fieldName}=${fieldName} | #{tag} where user_id=#{userId} and ${fieldName} & #{tag}=0")
    int setTag(Long userId, String fieldName, long tag);


    /**
     * 使用先取反在与的思路来取消标签,只能允许第一次删除成功
     * @param userId
     * @param fieldName
     * @param tag
     * @return
     */
    @Update("update t_user_tag set ${fieldName}=${fieldName} &~ #{tag} where user_id=#{userId} and ${fieldName} & #{tag}=#{tag}")
    int cancelTag(Long userId, String fieldName, long tag);
}

        说明:这里的sql可以参考开头看到的实现原理

        4.5 工具类

        4.5.1:对象转换类

package com.laoyang.common.utils;

import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;


/**
 * @author:Kevin
 * @create: 2023-07-29 15:03
 * @Description:
 */

public class ConvertBeanUtils {

    /**
     * 将一个对象转成目标对象
     */
     public static <T> T convert(Object source,Class<T> targetClass){
         if (source == null){
             return null;
         }
         T t = newInstance(targetClass);
         BeanUtils.copyProperties(source,t);
         return t;
     }

    /**
     * 将List对象转换成目标对象
     */
    public static <K,T> List<T> convertList(List<K> sourceList, Class<T> targetClass){
        if (sourceList == null){
            return null;
        }
        List targetlist = new ArrayList((int) (sourceList.size() / 0.75) + 1);
        for (K source : sourceList) {
            targetlist.add(source);

        }
        return targetlist;
    }

    private static <T> T newInstance(Class<T> targetClass){
        try {
            return targetClass.newInstance();
        }catch (Exception e){
            throw new BeanInstantiationException(targetClass,"instantiation error",e);

        }

    }


}

        调用实例:第一个参数:要转的对象  第二个参数:最终转换成的对象类

userTagDTO = ConvertBeanUtils.convert(userTagPO,UserTagDTO.class);

        4.5.2 redis业务封装key的工具类(继承实现)

                父类

package com.laoyang.framework.redis.key;

import org.springframework.beans.factory.annotation.Value;

/**
 * @author:Kevin
 * @create: 2023-07-30 16:37
 * @Description:
 */

public class RedisKeyBuilder {

    #获取到对应业务主题的名称
    @Value("${spring.application.name}")
    private String applicationName;

    private static final String SPLIT_ITEM = ":";

    public String getSplitItem() {
        return SPLIT_ITEM;
    }

    public String getRrefix(){
        return applicationName + SPLIT_ITEM;
    }
}

               子类

package com.laoyang.framework.redis.key;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

/**
 * @author:Kevin
 * @create: 2023-07-30 16:41
 * @Description:    用户中台的redis的key的封装工具类,生成这个业务字段的key
 */
@Configuration
@Conditional(RedisKeyLoadMatch.class)
public class UserProviderCacheKeyBuilder extends RedisKeyBuilder{

    private static String USER_INFO_KEY = "userInfo";
    private static String USER_TAG_LOCK_KEY = "userTagLock";
    private static String USER_TAG_KEY = "userTag";

    private static String USER_PHONE_LIST_KEY = "userPhoneList";
    private static String USER_PHONE_OBJ_KEY = "userPhoneObj";

    private static String USER_LOGIN_TOKEN_KEY = "userLoginToken";

    public String buildUserInfoKey(Long userId) {
        return super.getRrefix() + USER_INFO_KEY + super.getSplitItem() + userId;
    }

    public String buildTagLockKey(Long userId){
        return super.getRrefix() + USER_TAG_LOCK_KEY + super.getSplitItem() + userId;
    }

    public String buildtagInfoKey(Long userId){
        return super.getRrefix() + USER_TAG_KEY + super.getSplitItem() + userId;
    }

    public String buildUserPhoneListKey(Long userId) {
        return super.getRrefix() + USER_PHONE_LIST_KEY + super.getSplitItem() + userId;
    }

    public String buildUserPhoneObjKey(String phone) {
        return super.getRrefix() + USER_PHONE_OBJ_KEY + super.getSplitItem() + phone;
    }

    public String buildUserLoginTokenKey(String tokenKey) {
        return super.getRrefix() + USER_LOGIN_TOKEN_KEY + super.getSplitItem() + tokenKey;
    }

}

                4.5.3 po类

package com.laoyang.provider.dao.po;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.util.Date;

/**
 * @author:Kevin
 * @create: 2023-08-01 09:56
 * @Description:
 */
@Data
@TableName("t_user_tag")
public class UserTagPO {

    @TableId(type = IdType.INPUT)
    private Long userId;
    @TableField(value = "tag_info_01")
    private Long tagInfo01;
    @TableField(value = "tag_info_02")
    private Long tagInfo02;
    @TableField(value = "tag_info_03")
    private Long tagInfo03;
    private Date createTime;
    private Date updateTime;


}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/79136.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django框架 靓号管理(增删改查)

Django框架 靓号管理&#xff08;增删改查&#xff09; 新建一个项目 backend 使用pycharm创建app startapp app项目目录 C:\code\backend ├── app | ├── admin.py | ├── apps.py | ├── migrations | ├── models.py | ├── tests.py | ├── views.…

【设计模式】抽象工厂模式

抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 在抽象工厂模式中&#xff0c;接口是负责创建一个相关对象…

Jenkins改造—nginx配置鉴权

先kill掉8082的端口进程 netstat -natp | grep 8082 kill 10256 1、下载nginx nginx安装 EPEL 仓库中有 Nginx 的安装包。如果你还没有安装过 EPEL&#xff0c;可以通过运行下面的命令来完成安装 sudo yum install epel-release 输入以下命令来安装 Nginx sudo yum inst…

神经网络基础-神经网络补充概念-14-逻辑回归中损失函数的解释

概念 逻辑回归损失函数是用来衡量逻辑回归模型预测与实际观测之间差异的函数。它的目标是找到一组模型参数&#xff0c;使得预测结果尽可能接近实际观测。 理解 在逻辑回归中&#xff0c;常用的损失函数是对数似然损失&#xff08;Log-Likelihood Loss&#xff09;&#xff…

1.物联网LWIP网络,TCP/IP协议簇

一。TCP/IP协议簇 1.应用层&#xff1a;FTP&#xff0c;HTTP&#xff0c;Telent&#xff0c;DNS&#xff0c;RIP 2.传输层&#xff1a;TCP&#xff0c;UDP 3.网络层&#xff1a;IPV4&#xff0c;IPV6&#xff0c;OSPF&#xff0c;EIGRP 4.数据链路层&#xff1a;Ethernet&#…

Syncfusion Essential Studio JavaScrip Crack

Syncfusion Essential Studio JavaScrip Crack 数据透视表 添加了在将数据透视表导出到PDF文档时自定义列宽的支持。 签名 添加了对在特定位置绘制文本的支持。 Syncfusion Essential Studio for JavaScript在一个包中包含80多个高性能、轻量级、模块化和响应式UI组件。包括Jav…

dockerfile的概念

目录 一、Dockerfile 概念 1.1 docker镜像的分层 二、Docker镜像的创建 2.1 基于已有的镜像创建 2.2 基于本地模板创建 2.3 基于dockerfile创建 2.3.1 dockerfile 结构(四部分) 三、Dockerfile操作指令 3.1 ENTRYPOINT指令 3.2 CMD 与entrypoint 3.3 小结 四、ADD和…

【JAVA】我们该如何规避代码中可能出现的错误?(一)

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 文章目录 前言三种类型的异常异常处理JAVA内置异常类Exception 类的层次 前言 异常是程序中的一些错误&#xff0c;但并不是所有的错误都是异常&#xff0c;并且错误有时候是可以避免的&…

什么是CSS Grid布局?什么是Flexbox布局?它们两者有什么不同?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS Grid布局⭐ Flexbox布局⭐ 不同之处⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web…

Python“牵手”lazada商品评论数据采集方法,lazadaAPI申请指南

lazada平台API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范&#xff0c;lazadaAPI接口是指通过编程的方式&#xff0c;让开发者能够通过HTTP协议直接访问lazada平台的数据&#xff0c;包括商品信息、店铺信息、物流信息等&#xff0c;从而实现la…

【第八讲---视觉里程计2】

在图像中提取特征点并计算特征描述&#xff0c;非常耗时 通过计算描述子距离在不同图像中寻找特征匹配&#xff0c;也非常耗时 利用通过匹配点信息计算相机位姿&#xff0c;没什么问题 我们可以采用以下方法进行改进&#xff1a; 光流&#xff1a;通过其他方式寻找匹配点直接法…

Python Opencv实践 - 图像均值滤波

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) print(img.shape) pixel_count img.shape[0] * img.shape[1] print(pixel_count)#为图像添加椒盐噪声 #参考资料&#xf…

Android性能优化----执行时间优化

作者&#xff1a;lu人皆知 在APP做启动优化时&#xff0c;Application会做一些初始化的工作&#xff0c;但不要在Application中做耗时操作&#xff0c;然而有些初始化工作可能是很耗时的&#xff0c;那怎么办&#xff1f;初始化操作可以开启子线程来完成。 计算执行时间 常规…

学无止境·运维高阶⑤(LVS-DR 群集 配置Nginx负载均衡)

LVS-DR 群集 && 配置Nginx负载均衡 一、LVS-DR 群集1、相关配置环境2、在RS上配置并启动脚本2.1相关脚本2.2 启动脚本&#xff0c;另一台RS同样步骤 3、LVS-DR模式配置脚本4、测试 二、Nginx负载均衡1、安装Nginx并关闭相应设置2、向主机 node2&#xff0c;node3 写入内…

Spring Clould 消息队列 - RabbitMQ

视频地址&#xff1a;微服务&#xff08;SpringCloudRabbitMQDockerRedis搜索分布式&#xff09; 初识MQ-同步通讯的优缺点&#xff08;P61&#xff0c;P62&#xff09; 同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&…

比ChatGPT更强的星火大模型V2版本发布!

初体验 测试PPT生成 结果&#xff1a; 达到了我的预期&#xff0c;只需要微调就可以直接交付&#xff0c;这点比ChatGPT要强很多. 测试文档问答 结果&#xff1a; 这点很新颖&#xff0c;现在类似这种文档问答的AI平台收费都贵的离谱&#xff0c;星火不但免费支持而且效果也…

TiDB v7.1.0 跨业务系统多租户解决方案

本文介绍了 TiDB 数据库的资源管控技术&#xff0c;并通过业务测试验证了效果。资源管控技术旨在解决多业务共用一个集群时的资源隔离和负载问题&#xff0c;通过资源组概念&#xff0c;可以限制不同业务的计算和 I/O 资源&#xff0c;实现资源隔离和优先级调度&#xff0c;提高…

优思学院|六西格玛黑带的9大任务和7大技能

六西格玛黑带是六西格玛管理中最为重要的一个角色&#xff0c;他们专职&#xff08;也可以是兼职&#xff09;从事六西格玛改进项目&#xff0c;是成功完成六西格玛项目的技术骨干成员&#xff0c;是六西格玛组织的核心力量。他们的努力程度决定着六西格玛管理的成败。 六西格玛…

新榜 | CityWalk本地生活商业价值洞察报告

如果说现在有人问&#xff0c;最新的网络热词是什么? “CityWalk”&#xff0c;这可能是大多数人的答案。 近段时间&#xff0c;“CityWalk”刷屏了各种社交媒体&#xff0c;给网友们带来了一场“城市漫步”之旅。 脱离群体狂欢&#xff0c;这个在社交媒体引发热议的词汇背后又…

HCIP VLAN实验

VLAN实验 拓扑图配置和分析分析配置LSW1LSW2R1 测试dhcp获取ipICMP测试 拓扑图 配置和分析 分析 从题目来看&#xff0c;因为 pc 1 3都是vlan2而且还是不同网段&#xff0c;pc 2 4 5 6在同一网段&#xff0c;所以可以将pc 1 2 5 4 6分在一个网段 pc4不通5 6 &#xff0c;那就…
最新文章