原始需求:有一个功能是一个活动通过区域,楼栋,单元过滤房源,此时用到的缓存key采用活动ID,区域ID,楼栋ID,单元ID连接组成,类似$key = $activityId . '-' . $areaId . '-' . $blockId . '-' . $unitId ;缓存的加载和删除在活动的发布和取消发布进行。
新需求:在以上功能的基础上,增加户型的过滤。
当做新需求时,采用的是key中增加一个户型ID进行过滤。此时key为:$key = $activityId . '-' . $areaId . '-' . $blockId . '-' . $unitId . '-' . $houseTypeId;在活动发布和取消发布时,修改加载和清除缓存的功能。此时便出现了一个问题,由于户型在活动发布后还能修改,则会造成修改了户型,通过户型筛选时,发现筛选功能没有作用。
原因是这样的:
情景一:例如A1房间原来的户型是A户型,对应的key为$key = $activityId . '-' . $areaId . '-' . $blockId . '-' . $unitId . '-' . 'AID';(原来这个key对应房间列表中有A1,A2房间),后来修改成了B户型,key为$key = $activityId . '-' . $areaId . '-' . $blockId . '-' . $unitId . '-' . 'BID';(原来这个key对应房间列表中有B1,B2房间)。此时通过户型进行过滤,筛选A户型和B户型,由于缓存并没有修改,发现筛选出的房间列表并没有变化。
情景二:例如A1房间原来的户型是A户型,对应的key为$key = $activityId . '-' . $areaId . '-' . $blockId . '-' . $unitId . '-' . 'AID';(原来这个key对应房间列表中有A1,A2房间),后来修改成了B户型,key为$key = $activityId . '-' . $areaId . '-' . $blockId . '-' . $unitId . '-' . 'BID';(原来缓存中没有这个户型对应的key)。此时通过户型进行过滤,筛选A户型没有作用,由于原来B户型key在缓存中不存在,则会从DB中进行加载,此时筛选B户型是正确的。
还有些情景也是有问题的。
解决方案一:在修改户型时,将此房间修改前的户型对应的key对应的缓存删除掉。将修改后的户型重新生成缓存。
解决方案二:由于区域,楼栋,单元下的数据不会有很多数据,所以不将户型ID加入到缓存中,进行户型筛选时,直接通过程序进行筛选。这样也不会有性能问题,而且能减少缓存的复杂度,尽可能避免出错。
在使用缓存的时候,一定要注意缓存的复杂度与性能的取舍。
另外Yii2中AR使用where()时建议使用andWhere()进行筛选,因为where()会过滤掉原来的过滤条件.
public function where($condition, $params = []) { $this->where = $condition; $this->addParams($params); return $this; } public function andWhere($condition, $params = []) { if ($this->where === null) { $this->where = $condition; } else { $this->where = ['and', $this->where, $condition]; } $this->addParams($params); return $this; }
转载请注明:MitNick » 关于使用缓存出现问题的总结