0

0

PHP下通过系统信号量加锁方式获取递增序列ID_PHP教程

php中文网

php中文网

发布时间:2016-07-21 15:43:45

|

1257人浏览过

|

来源于php中文网

原创

在网上搜了搜,有两个办法但都不太好:一个是简单的以进程ID+时间戳,或进程ID+随机数来产生近似的唯一ID,虽简单但对于追求“完美”的我不愿这样凑合,再说Apache2以后进程会维持相当长得时间,生成的ID发生碰撞的几率还是比较大的;第二个思路是通过Mysql的自增字段,这个就更不能考虑了,效率低不说,我的设计里压根就没数据库。
递增ID的获取是个过程:
1. 从全局某个存储中读取ID
2. 给ID加1
3. 将ID重新存入全局存储
在多进程或线程的程序中需要将上述3步作为单步的原子操作,才能保证ID的唯一。
Java中很好解决,这是因为Java程序大多以多线程方式运行,每个线程都能共享Java进程中的变量,并能方便的加线程锁控制线程的运转同步。在PHP中ID全局存储没问题,可以放在session中,大不了放在文件中,但进程间同步就是问题了。
实际上进程调度、管理是操作系统内核必须实现的功能,今天介绍的信号量(也称为信号灯)就是在Unix/Linux上解决进程同步的一项技术。
信号灯原是用在铁路上的管理机制,我们今天看到的铁路大多是双线并行,但有的路段受山势、地形影响只有单条铁轨,必须保证同一时间只能有一列火车运行通过这些路段。早先铁路上就是用信号灯来管理的:没有火车经过时,信号等处于闲置状态,一旦有火车进入此路段,信号灯即变为在用状态,其他的火车经过时就需要等待,等待先前的火车驶出路段信号等变为闲置后,才能进入此路段,一旦又有火车进入,信号灯又变为繁忙......,以此来保障铁路运行的安全畅通。
Unix系统就像铁路管理局控制信号灯一样管理控制信号量的状态,因此也可以这样说信号量是由内核管理的,信号量不仅能控制进程间的同步,同样可以控制线程间的同步。
信号量属于系统进程间通讯技术(IPC),今天我们只从PHP角度介绍信号量的使用,有关IPC的技术细节可参考Stevens的权威著作《UNIX网络编程第二卷 进程间通信》。
先看最终的代码:

复制代码 代码如下:

php
// ---------------------------------------------------
// 递增序列号ID(1~1000000000)
//
// ID存储在共享内存中(shared memory),通过信号灯(semaphore)同步
// ---------------------------------------------------
$IPC_KEY = 0x1234; //System V IPC KEY
$SEQ_KEY = "SEQ"; //共享内存中存储序列号ID的KEY
//创建或获得一个现有的,以"1234"为KEY的信号量
$sem_id = sem_get($IPC_KEY);
//创建或关联一个现有的,以"1234"为KEY的共享内存
$shm_id = shm_attach($IPC_KEY, 64);
//占有信号量,相当于上锁,同一时间内只有一个流程运行此段代码
sem_acquire($sem_id);
//从共享内存中获得序列号ID
$id = @shm_get_var($shm_id, $SEQ_KEY);
if ($id == NULL || $id >= 1000000000)
{
$id = 1;
}
else
{
$id++;
}
//将"++"后的ID写入共享内存
shm_put_var($shm_id, $SEQ_KEY, $id);
//释放信号量,相当于解锁
sem_release($sem_id);
//关闭共享内存关联
shm_detach($shm_id);
echo "序列号ID:{$id}";
?>

009行,定义了一个16进制的整形KEY,在PHP中只支持System V的IPC机制,需要通过一个KEY关联到指定的资源(消息队列、信号量、共享内存)。
010 行,定义了一个在共享内存中存储递增ID的KEY,这是PHP对System V共享内存的闲置:需要通过类似hashtable的KEY-VALUE方式存储变量。在上面的代码中使用共享内存做ID的存储容器,也可以换为 Session、文件等其他机制,本文重点是信号量,有关共享内存的知识以后在讲(别忘了前面推荐的那本书)。
013行,获得系统中的以1234为KEY的信号量,如果系统中没有就创建一个。
015行,同13行相似,获得系统中的以1234为KEY的共享内存,如果系统中没有就创建一个,第二个参数64表示创建64bytes大小的共享内存。
018~034 行,同步代码区,当一个进程或线程执行sem_acquire函数占有了信号量,到它调用sem_release函数释放信号量的过程内,其他进程或线程执行到sem_acquire会阻塞。021行从共享内存中获得ID,函数shm_get_var前缀"@"是为了屏蔽出错信息(第一次执行时,共享内存中并没有以"SEQ"为KEY的数据,会在页面上打印警告信息)。
其他语句非常简单,不需多讲。
程序编好后,访问这个PHP页面,会递增的输出数字。
我们可以通过系统命令ipcs查看在程序创建的信号量和共享内存:
$ ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00001234 1212412443 www-data 666 64 0
------ Semaphore Arrays --------
key semid owner perms nsems
0x00001234 163841 www-data 666 3
------ Message Queues --------
key msqid owner perms used-bytes messages
前两段分别是共享内存和信号量,0x00001234既是我们创建的KEY。
也可以通过命令ipcrm删除:
$ ipcrm -M 0x00001234 #删除共享内存
$ ipcrm -S 0x00001234 #删除信号量
---------------------------------------------
PHP手册中关于IPC的资料非常少,这点也不难想象,Stevens已经在十几年前讲得透透的东东,在PHP中只是包装了一下,还有多少必要去深入说明呢?
文本只是借着ID说了说信号量的使用,如果您有更简单的生成自增ID的办法,还望赐教。
可能有朋友还想了解信号量的执行效率,我这里用一句过时的流行语总结: 相当的快。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/320685.htmlTechArticle在网上搜了搜,有两个办法但都不太好:一个是简单的以进程ID+时间戳,或进程ID+随机数来产生近似的唯一ID,虽简单但对于追求“完美”的...

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

46

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

178

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

51

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

92

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

102

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

227

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

532

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

171

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.5万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号