锁的使用,一般情况是针对并发或者我们希望程序(crontab的job)串行处理,我们加锁的办法有很多,像文件锁,数据库锁,或者memcache锁,这里关注一下memcache锁,针对memcache锁,考虑三个问题。
1、 memcache并发情况下的get,set会出现什么样的问题?
2、 如何使用memcache实现加锁
3、 memcache加锁后,解锁前程序crash,如何处理
针对第一个问题,我们考虑一下这样一个场景,我们使用memcache记录一个用户最近五次的访问时间。
我们会怎么做呢?
我们用用户的uid做key,将每次访问的时间用符号连接起来做value,存储在memcache中。我们看一下程序的流程。
先get查看用户的uid是否存在,如果不存在,set key是uid,value是当前时间,如果存在,获取vaule,做下逻辑处理,连接上当前时间。我们一厢情愿的希望我们的程序是 get --> set -->get --> set……, 可是,问题来了,并发了,用户第一次访问的时间还未set,就来了第二次访问,并且get数据了,成了 get --> get --> set --> set,会发生什么呢? “脏读”,第二次读到的数据不准确。很明显,第二次set 会把第一次set的值替换掉。 我们丢了一次记录!
怎么办? 加锁! 很简单我们改一下流程, 加锁 --> get --> set --> 解锁 -->加锁 --> get --> ……
我们程序在每次要get的时候,都加上一把锁,如果加不上,我们可以等待,直到能加上锁,我们再去get值, 这样就保证我们改的数据不会出现上面脏读的问题!
来看第二个问题,如何使用memcache加锁呢?
Memcache::add | 增加一个条目到缓存服务器 |
Memcache::addServer | 向连接池中添加一个memcache服务器 |
Memcache::close | 关闭memcache连接 |
Memcache::connect | 打开一个memcached服务端连接 |
Memcache::decrement | 减小元素的值 |
Memcache::delete | 从服务端删除一个元素 |
Memcache::flush | 清洗(删除)已经存储的所有的元素 |
Memcache::get | 从服务端检回一个元素 |
Memcache::getExtendedStats | 缓存服务器池中所有服务器统计信息 |
Memcache::getServerStatus | 用于获取一个服务器的在线/离线状态 |
Memcache::getStats | 获取服务器统计信息 |
Memcache::getVersion | 返回服务器版本信息 |
Memcache::increment | 增加一个元素的值 |
Memcache::pconnect | 打开一个到服务器的持久化连接 |
Memcache::replace | 替换已经存在的元素的值 |
Memcache::set | Store data at the server |
Memcache::setCompressThreshold | 开启大值自动压缩 |
Memcache::setServerParams | 运行时修改服务器参数和状态 |
Memcache::setServerParams | 运行时修改服务器参数和状态 |