YII 框架 中 基于SAE的KV-DB的缓存实现.

支持超时, 写入时加锁.
锁冲突时旋转等待.

<?php

/**
* Cache implementation for saekvdb.
* Pay attention to the limit of the sae kv db,
* max key length : 200,
* max value length : 4M.
*
* @author tq02ksu
*/
class SAEKVCache extends CCache {

/**
* $kv holds the kv db connection
* @var type
*/
public $kv;

/**
* Key suffix of lock entry.
* @var string
*/
public $suffix_lock = 'l';

/**
* Key suffix of content entry.
* @var string
*/
public $suffix_content = 'c';

/**
* Key of expiration.
* @var string
*/
public $field_expiration = 'e';

/**
* Key of content.
* @var string
*/
public $field_content = 'c';
public $max_spin_wait = 3000;

public function gen_content_key($key) {
$suffix = $this->suffix_content;
return $key . $suffix;
}

public function gen_lock_key($key) {
$suffix = $this->suffix_lock;
return $key . $suffix;
}

/**
* Initializes the application component.
* This method overrides the parent implementation by setting default cache key prefix.
*/
public function init() {
parent::init();
if ($this->kv === null) {
$this->kv = new SaeKV();
$this->kv->init();
}
}

/**
* Retrieves a value from cache with a specified key.
* This method should be implemented by child classes to retrieve the data
* from specific cache storage. The uniqueness and dependency are handled
* in {@link get()} already. So only the implementation of data retrieval
* is needed.
* @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired.
* @throws CException if this method is not overridden by child classes
*/
protected function getValue($key) {
$key_content = $this->gen_content_key($key);

$field_expiration = $this->field_expiration;
$field_content = $this->field_content;

$val = $this->kv->get($key_content);

// deal as a failure:
if ($val === false) {
return false;
}

$val = unserialize($val);

if (array_key_exists($field_expiration, $val) && $val[$field_expiration] < time()) {
// expired
$this->deleteValue($key);
return false;
} else {
// cache hint:
return $val[$field_content];
}
}

/**
* Stores a value identified by a key in cache.
* This method should be implemented by child classes to store the data
* in specific cache storage. The uniqueness and dependency are handled
* in {@link set()} already. So only the implementation of data storage
* is needed.
*
* @param string $key the key identifying the value to be cached
* @param string $value the value to be cached
* @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
* @return boolean true if the value is successfully stored into cache, false otherwise
* @throws CException if this method is not overridden by child classes
*/
protected function setValue($key, $value, $expire) {
return $this->addOrSetValueByParam($key, $value, $expire, 'set');
}

/**
* Stores a value identified by a key into cache if the cache does not contain this key.
* This method should be implemented by child classes to store the data
* in specific cache storage. The uniqueness and dependency are handled
* in {@link add()} already. So only the implementation of data storage
* is needed.
*
* @param string $key the key identifying the value to be cached
* @param string $value the value to be cached
* @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
* @return boolean true if the value is successfully stored into cache, false otherwise
* @throws CException if this method is not overridden by child classes
*/
protected function addValue($key, $value, $expire) {
return $this->addOrSetValueByParam($key, $value, $expire, 'add');
}

protected function addOrSetValueByParam($key, $value, $expire, $method) {
$field_content = $this->field_content;
$field_expiration = $this->field_expiration;

$val = array(
$field_content => $value,
);

if ($expire > 0) {
$val[$field_expiration] = time() + $expire;
}
$val = serialize($val);

$key_content = $this->gen_content_key($key);
$key_lock = $this->gen_lock_key($key);

for ($i = 0; $i < $this->max_spin_wait; $i++) {
if ($this->kv->add($key_lock, '')) {
$success = $this->kv->$method($key_content, $val);
$this->kv->delete($key_lock);
return $success;
}
}
return false;
}

/**
* Deletes a value with the specified key from cache
* This method should be implemented by child classes to delete the data from actual cache storage.
* @param string $key the key of the value to be deleted
* @return boolean if no error happens during deletion
* @throws CException if this method is not overridden by child classes
*/
protected function deleteValue($key) {
$key_content = $this->gen_content_key($key);
$key_lock = $this->gen_lock_key($key);

for ($i = 0; $i < $this->max_spin_wait; $i++) {
if ($this->kv->add($key_lock, '')) {
$this->kv->delete($key_content);
$this->kv->delete($key_lock);
return true;
}
}
return false;
}

/**
* Deletes all values from cache.
* Child classes may implement this method to realize the flush operation.
* @return boolean whether the flush operation was successful.
* @throws CException if this method is not overridden by child classes
* @since 1.1.5
*/
protected function flushValues() {
$success = true;
$step = 100;
for ($ret = $this->kv->pkrget('', $step); $ret !== false; $ret = $this->kv->pkrget('', $step)) {
array_walk($ret, function( $value, $key ) use ($kv) {
$success = $success && $kv->delete($key) ? true : false;
});
}

return true;
}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值