




















在电商系统中,商品打标是高频需求,无论是秒杀、拼团、限量等活动标签,都需要高效的打标、去标和标签判断能力。本文将分享一套基于64位整数位运算的通用商品打标实现方案,该方案兼顾性能与扩展性,同时提供Laravel、ThinkPHP6的PHP专属实现,以及Java、Python的跨语言实现,可直接集成到各类电商项目中。
采用long类型(64位无符号整数) 存储商品标签,通过位运算(或、与、取反) 实现打标、去标、标签判断操作,核心优势如下:
核心位运算逻辑(以秒杀标签为例):
| 操作 | 位运算逻辑 | 说明 |
|---|---|---|
| 打标 | `skuTags = skuTags | 标签常量` |
| 去标 | skuTags = skuTags & (~标签常量) |
与取反运算,将对应标签位设为0 |
| 判标 | (skuTags & 标签常量) != 0 |
与运算,结果非0则表示存在该标签 |
无论哪种框架/语言,都需要在商品表中添加一个64位无符号整数字段sku_tags,默认值为0(表示无任何标签)。
-- 通用写法,适配MySQL等主流数据库
ALTER TABLE `product` ADD COLUMN `sku_tags` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '商品标签位字段';
-- Laravel迁移文件专属写法
Schema::table('products', function (Blueprint $table) {
$table->unsignedBigInteger('sku_tags')->default(0)->comment('商品标签位字段');
});
PHP主流电商框架均采用枚举类定义标签+Trait封装位运算+模型引入的架构,实现代码解耦和复用,以下分别给出Laravel和ThinkPHP6的完整实现。
以秒杀(第11位)、拼团(第12位)、限量(第13位) 为例定义标签,标签常量通过1 << n实现(n为位序,从0开始计数),保证每个标签对应唯一的二进制位。
创建文件:app/Enums/SkuTag.php
<?php
namespace App\Enums;
class SkuTag
{
const SECKILL = 1 << 10; // 秒杀标记(第11位)
const GROUP_BUY = 1 << 11; // 拼团标记
const LIMITED = 1 << 12; // 限量标记
// 可按需继续拓展其他标签
}
创建文件:app/Traits/SkuTaggable.php
<?php
namespace App\Traits;
trait SkuTaggable
{
// 打标
public function addTag($tag)
{
$this->sku_tags |= $tag;
return $this;
}
// 去标
public function removeTag($tag)
{
$this->sku_tags &= ~$tag;
return $this;
}
// 判断是否存在标签
public function hasTag($tag)
{
return ($this->sku_tags & $tag) !== 0;
}
}
修改文件:app/Models/Product.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Traits\SkuTaggable;
class Product extends Model
{
use SkuTaggable;
// 需将sku_tags加入可填充字段
protected $fillable = ['name', 'sku_tags', 'price', 'stock']; // 补充其他字段
}
use App\Models\Product;
use App\Enums\SkuTag;
// 获取商品实例
$product = Product::find(123);
// 打标:添加秒杀标签(链式调用直接保存)
$product->addTag(SkuTag::SECKILL)->save();
// 判标:判断是否为秒杀商品
if ($product->hasTag(SkuTag::SECKILL)) {
// 执行业务逻辑,如路由到秒杀服务、显示秒杀标签等
}
// 去标:移除秒杀标签
$product->removeTag(SkuTag::SECKILL)->save();
创建文件:app/common/enums/SkuTagEnum.php
<?php
declare(strict_types=1);
namespace app\common\enums;
class SkuTagEnum
{
public const SECKILL = 1 << 10; // 秒杀标签(第11位)
public const GROUP_BUY = 1 << 11; // 拼团标签
public const LIMITED = 1 << 12; // 限量标签
// 拓展:获取所有标签键值对,方便后台渲染
public static function all(): array
{
return [
'秒杀' => self::SECKILL,
'拼团' => self::GROUP_BUY,
'限量' => self::LIMITED,
];
}
}
创建文件:app/common/traits/SkuTaggable.php
<?php
declare(strict_types=1);
namespace app\common\traits;
trait SkuTaggable
{
// 打标,返回自身支持链式调用
public function addTag(int $tag): self
{
$this->sku_tags |= $tag;
return $this;
}
// 去标
public function removeTag(int $tag): self
{
$this->sku_tags &= ~$tag;
return $this;
}
// 判标
public function hasTag(int $tag): bool
{
return ($this->sku_tags & $tag) !== 0;
}
}
创建文件:app/model/Product.php
<?php
declare(strict_types=1);
namespace app\model;
use think\Model;
use app\common\traits\SkuTaggable;
class Product extends Model
{
use SkuTaggable;
protected $table = 'product'; // 指定商品表名
protected $autoWriteTimestamp = true; // 自动维护时间戳(按需开启)
}
use app\model\Product;
use app\common\enums\SkuTagEnum;
// 获取商品
$product = Product::find(123);
// 打标并保存
$product->addTag(SkuTagEnum::SECKILL)->save();
// 判标
if ($product->hasTag(SkuTagEnum::SECKILL)) {
// 秒杀商品专属逻辑
}
// 去标并保存
$product->removeTag(SkuTagEnum::SECKILL)->save();
若项目非PHP框架开发,或需要多语言服务联动(如Java网关、Python数据分析),可直接使用以下原生实现代码,核心位运算逻辑完全一致。
<?php
// 定义秒杀标签常量
define('SECKILL_FLAG', 1 << 10); // 1024,第11位
// 打标方法
function addSkuTag($skuTags, $flag) {
return $skuTags | $flag;
}
// 去标方法
function removeSkuTag($skuTags, $flag) {
return $skuTags & (~$flag);
}
// 判标方法
function hasSkuTag($skuTags, $flag) {
return ($skuTags & $flag) !== 0;
}
// 使用示例
$skuTags = 0; // 初始无标签
$skuTags = addSkuTag($skuTags, SECKILL_FLAG); // 打标
var_dump(hasSkuTag($skuTags, SECKILL_FLAG)); // bool(true)
$skuTags = removeSkuTag($skuTags, SECKILL_FLAG); // 去标
var_dump(hasSkuTag($skuTags, SECKILL_FLAG)); // bool(false)
public class SkuTagUtil {
// 定义标签常量,使用1L保证64位长整型
public static final long SECKILL_FLAG = 1L << 10; // 秒杀标签
public static final long GROUP_BUY_FLAG = 1L << 11; // 拼团标签
// 打标
public static long addSkuTag(long skuTags, long flag) {
return skuTags | flag;
}
// 去标
public static long removeSkuTag(long skuTags, long flag) {
return skuTags & ~flag;
}
// 判标
public static boolean hasSkuTag(long skuTags, long flag) {
return (skuTags & flag) != 0;
}
// 测试示例
public static void main(String[] args) {
long skuTags = 0;
skuTags = addSkuTag(skuTags, SECKILL_FLAG);
System.out.println(hasSkuTag(skuTags, SECKILL_FLAG)); // true
skuTags = removeSkuTag(skuTags, SECKILL_FLAG);
System.out.println(hasSkuTag(skuTags, SECKILL_FLAG)); // false
}
}
# 定义标签常量
SECKILL_FLAG = 1 << 10 # 秒杀标签,1024
GROUP_BUY_FLAG = 1 << 11 # 拼团标签
# 打标
def add_sku_tag(sku_tags: int, flag: int) -> int:
return sku_tags | flag
# 去标
def remove_sku_tag(sku_tags: int, flag: int) -> int:
return sku_tags & ~flag
# 判标
def has_sku_tag(sku_tags: int, flag: int) -> bool:
return (sku_tags & flag) != 0
# 使用示例
sku_tags = 0
sku_tags = add_sku_tag(sku_tags, SECKILL_FLAG)
print(has_sku_tag(sku_tags, SECKILL_FLAG)) # True
sku_tags = remove_sku_tag(sku_tags, SECKILL_FLAG)
print(has_sku_tag(sku_tags, SECKILL_FLAG)) # False
商品打标后,可基于sku_tags实现电商系统的流量染色和业务隔离,核心落地场景如下:
sku_tags判断是否为秒杀/拼团商品,转发到专属服务集群,避免影响主站性能;seckill:sku:{id}),方便单独管理缓存过期和刷新策略;基于本方案的高扩展性,可快速实现以下进阶功能,满足企业级电商需求:
where (sku_tags & 1024) != 0;本文分享的商品打标方案基于64位整数位运算,是电商系统中高性能、高扩展性的经典实现方式,相比传统的标签关联表方案,大幅减少了数据库交互和代码复杂度。方案同时提供了PHP主流框架(Laravel、ThinkPHP6)的工程化实现,以及PHP、Java、Python的跨语言原生实现,可直接复制到项目中使用,也可根据实际业务需求灵活拓展标签类型和功能。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。