使用redis在symfony2中缓存重复请求

时间:2015-08-24 07:16:24

标签: php symfony caching redis

这是我目前的设置:

private Context context;
private List<ContactListItems> items;

/**
 * @param context
 * @param groupList
 */
public TestListAdapter(Context context, List<ContactListItems> items) {
    this.context = context;
    this.items = items;
}

@Override
public int getCount() {
    return items.size();
}

@Override
public Object getItem(int position) {
    return position;
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.li_plus_minus, parent, false);
        holder = new ViewHolder();
        holder.plus = (Button) convertView.findViewById(R.id.plus);
        holder.minus = (Button) convertView.findViewById(R.id.minus);
        holder.et = (EditText) convertView.findViewById(R.id.editText);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    ContactListItems item = items.get(position);
    holder.et.setText(String.valueOf(item.value));
    holder.plus.setOnClickListener(new ClickListener(item));
    holder.minus.setOnClickListener(new ClickListener(item));
    return convertView;
}

class ClickListener implements View.OnClickListener {
    private ContactListItems item;

    public ClickListener(ContactListItems item) {
        this.item = item;
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.minus) {
            item.value--;
        } else if (v.getId() == R.id.plus) {
            item.value++;
        }
        notifyDataSetChanged();
    }
}

class ViewHolder {
    Button plus, minus;
    EditText et;
}

我有一个获取多个重复请求的API(通常是快速连续),我可以使用此设置在重复请求时发回缓存响应吗?还可以设置缓存到期吗?

2 个答案:

答案 0 :(得分:3)

在您提供的配置示例中,我猜测您要缓存Doctrine结果而不是完整的HTTP响应(尽管后者是可能的,请参阅下文)。

如果是这样,最简单的方法是每当您创建一个Doctrine查询时,将其设置为使用您在上面设置的result cache来使用redis。

$qb = $em->createQueryBuilder();
// do query things
$query = $qb->getQuery();
$query->useResultCache(true, 3600, 'my_cache_id');

这将使用您的缓存ID将该查询的结果缓存一小时。清理缓存有点过分了:

$cache = $em->getConfiguration()->getResultCacheImpl();
$cache->delete('my_cache_id');

如果你想缓存完整的响应 - 即你在应用程序中进行一些需要很长时间的处理 - 那么有很多方法可以做到这一点。可以将其序列化并弹出到redis中:

$myResults = $service->getLongRunningResults();
$serialized = serialize($myResults);
$redisClient = $container->get('snc_redis.default');
$redisClient->setex('my_id', $serialized, 3600);

或者查看varnish等专用HTTP缓存解决方案或查看Symfony documentation on HTTP caching

编辑 SncRedisBundle提供了自己版本的Doctrine的CacheProvider。因此,在你的答案中你创建自己的课程,你也可以这样做:

my_cache_service:
    class: Snc\RedixBundle\Doctrine\Cache\RedisCache
    calls:
        - [ setRedis, [ @snc_redis.default ] ]

这几乎与你班级的作用完全相同。因此,$app_cache->get('id')代替$app_cache->fetch('id') import sentiwordnet from sentiwordnet import * swn_filename = 'C:\\Python27\\Lib\\SentiWordNet_3.0.0_20130122.txt' swn = SentiWordNetCorpusReader(swn_filename) 。这样,您可以在不更改应用类的情况下切换缓存的后端,只需更改服务说明。

答案 1 :(得分:0)

最后,我创建了一个缓存管理器,并将其注册为名为@app_cache的服务。

use Predis;

class CacheManager
{
    protected $cache;

    function __construct()
    {
        $this->client = new Predis\Client();
    }

    /**
     * @return Predis\Client
     */
    public function getInstance()
    {
        return $this->client;
    }
}

在控制器中我可以md5 request_uri

$id = md5($request->getRequestUri()); 

检查是否存在,是否确实返回$result

if($result = $app_cache->get($id)) {
   return $result;
}

如果它没有......无论如何......并保存下次的响应

$app_cache->set($id,$response);

要设置到期时间,请使用第3和第4个参数ex =秒和px =毫秒。

$app_cache->set($id,$response,'ex',3600);