私人网站服务器免费广州清洁公司

当前位置: 首页 > news >正文

私人网站服务器免费,广州清洁公司,郑州市做网站的公,北京建设电工证查询网站一#xff1a; 计算机中的二进制 计算机以二进制表示数据#xff0c;以表示电路中的正反。在二进制下#xff0c;一个位只有 0 和 1 。逢二进一 位。类似十进制下#xff0c;一个位只有 0~9 。逢十进一位。 二#xff1a; 进制常用运算 #xff08;位运算#xff09;…         一 计算机中的二进制         计算机以二进制表示数据以表示电路中的正反。在二进制下一个位只有 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) ) ENGINEInnoDB DEFAULT CHARSETutf8mb3 COLLATEutf8mb3_bin COMMENT用户标签记录; 4.2service层接口
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 {Resourceprivate IUserTagMapper userTagMapper;Resourceprivate RedisTemplateString, String redisTemplate;private RedisTemplateString, UserTagDTO userTagDTORedisTemplate;Resourceprivate UserProviderCacheKeyBuilder cacheKeyBuilder;Overridepublic 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 RedisCallbackString() {Overridepublic 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;}Overridepublic 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;}Overridepublic 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)) {returnTagInfoUtils.isContain(userTagDTO.getTagInfo01(),userTagsEnum.getTag());} else if(UserTagFieldNameConstants.TAG_INFO_02.equals(queryFieldName)) {returnTagInfoUtils.isContain(userTagDTO.getTagInfo02(),userTagsEnum.getTag());} else if(UserTagFieldNameConstants.TAG_INFO_03.equals(queryFieldName)) {returnTagInfoUtils.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命令并设置了一些选项参数。下面对代码进行解释 首先通过redisTemplate.getKeySerializer()获取key的序列化器通过redisTemplate.getValueSerializer()获取value的序列化器。在RedisCallback的doInRedis方法中通过RedisConnection的execute方法执行set命令。参数中keySerializer.serialize(key)将key序列化为字节数组valueSerializer.serialize(-1)将value序列化为字节数组。NX.getBytes(StandardCharsets.UTF_8)表示设置NX选项即只有在key不存在时才进行set操作。EX.getBytes(StandardCharsets.UTF_8)表示设置EX选项即设置key的过期时间为3秒。3.getBytes(StandardCharsets.UTF_8)表示设置key的过期时间为3秒。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 BaseMapperUserTagPO {/** 使用或的思路来设置标签只能允许第一次设置成功* 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,ClassT targetClass){if (source null){return null;}T t newInstance(targetClass);BeanUtils.copyProperties(source,t);return t;}/** 将List对象转换成目标对象/public static K,T ListT convertList(ListK sourceList, ClassT 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(ClassT 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;}