纵向货架的优化
-
针对纵向货架指标进行优化,主要集中在Android侧,目前新策略秒开Android已提升3.4分。主要优化:新策略下钟点房模块延迟加载,避免抢占首屏全日房加载资源。
-
剩余可优化点
- 钟点房首屏延迟加载全日房模块。
- 详情页接口添加returnFormat,避免Android侧序列化耗时长的问题。
- 钟点房场景与全日房接口拆分,提升首屏接口速度。
- 纵向快筛栏layout后置逻辑优化。
-
中间页接口缓存:需要注意,价格在接口返回之后展示,否则价格跳变体验不好
缓存优化
- 缓存: 缓存就是一个临时储存数据的地方。当用户查询数据时,首先会在缓存中查找,如果找到了就直接使用;如果找不到,就再到数据的原始位置去寻找。所以,缓存本质上是一种用空间换时间的技术,通过数据在空间上的重复,来提升数据的访问速度。 并不是所有的缓存都只是为了提升速度,因为在分布式系统中,缓存机制实际上是系统级性能设计的一个重要权衡手段。 比如当某个数据库的负载比较高,接近系统瓶颈时,我们就可以使用缓存技术,把负荷分担到其他数据库中,那么这里使用缓存的目的,主要就是负载均衡,而不是提升访问速度。
- 几种数据类型
- 不变性数据:这类数据就是可以优先考虑使用缓存技术的一种数据类型,在实际的业务场景中也非常多。比如,Web服务中的静态网页、静态资源,或者数据库表中列数据与key的映射关系、业务的启动配置,等等,这些都可以认为是不变性数据;
- 弱一致性数据,它代表数据会经常发生变化,但是业务对数据的一致性要求不高,也就是说,不同用户在同一时间点上看到不完全一致的数据,都是可以接受的。由于这类数据对一致性的要求比较低,所以在设计缓存机制时,你只需要实现最终一致性就可以了。这类数据在实际业务中也比较多,比如业务的历史分析数据、一些搜索查找返回数据等,即使最近的一些数据没有记录进去,关系也不大。这类数据缓存失效机制是基于时间失效
- 强一致性数据:第三种缓存数据类型是强一致性数据,它是指代码数据会经常发生变化,而且业务对数据库的一致性要求非常高,也就是说当数据发生变更后,其他用户在系统中的任何地方,都应该看到的是更新后的数据。那么,针对这种类型的数据,我一般是不推荐你去使用缓存机制,因为这类数据在使用缓存时会比较复杂,而且很容易会引入新的问题。比如说,用户可以直接提交和修改的各种数据内容,如果没有同步修改缓存中的数据,就会引发数据不一致性的问题,导致比较严重的业务故障。不过在一些特殊的业务场景中,比如,在针对个别的数据访问频率非常高的情况下,我们还是需要通过设计缓存机制,来进一步提升性能。因此针对这类强一致性数据,在设计缓存机制时,你需要特别注意两点:
- 这种数据的缓存一定要采用修改同步的实现方式。也就是说,所有的数据修改都必须确保可以同步修改缓存与数据库中的数据。
- 准确识别特定业务流程中,可以使用缓存获取数据的时间有多长。因为有些缓存数据(比如一次REST请求中,多个流程都需要使用的数据)只可以在单次业务流程中使用,不能跨业务流程使用。
缓存
//过滤字段,即key
const filter = `${checkInDate}_${checkOutDate}_${roomCount}_${numberOfAdults}_${childAges}`;
//加载缓存
dayRoomCacheData = getDayRoomListCache(poiId, filter);
//方法
export const getDayRoomListCache = (poiId, filter) => {
return getDayRoomListCacheWitchKey(
poiId,
filter,
OLD_FIRST_KEY,
OLD_SECOND_KEY_PREFIX
);
};
//具体缓存
/**
* 读缓存获取全日房数据
* @param poiId
* @param filter 筛选条件
* @returns
*/
const getDayRoomListCacheWitchKey = (
poiId,
filter,
firstKey,
secondKeyPrefix
) => {
const value = syncGetStorage(firstKey);
if (value && value.data) {
try {
const dayRoomList = JSON.parse(value.data);
if (isValid(dayRoomList)) {
const invalidList = []; //过期缓存
let hasCache = false;
const currentTimestamp = getCurrentTimeSync();
for (const item of dayRoomList) {
if (item.uniqueKey === poiId) {
if (item.filter === filter) {
if (currentTimestamp < item.expirationTime) {
hasCache = true;
} else {
//缓存过期
toastCacheStatus(
'缓存过期' +
(currentTimestamp -
item.expirationTime) +
'ms'
);
}
} else {
//缓存不匹配
toastCacheStatus(
'缓存筛选条件不匹配\nfilter:' +
filter +
'\ncacheFilter:' +
item.filter
);
}
}
if (currentTimestamp >= item.expirationTime) {
invalidList.push(item);
}
}
if (isValid(invalidList)) {
clearInvalidRoomList(invalidList, secondKeyPrefix);
}
if (hasCache) {
const dayRoomCache = syncGetStorage(
secondKeyPrefix + poiId
);
if (dayRoomCache && dayRoomCache.data) {
//命中缓存
const dayRoomData = JSON.parse(dayRoomCache.data);
toastCacheStatus('命中缓存');
return dayRoomData;
} else {
toastCacheStatus('第二部分缓存数据丢失');
}
}
//debug调试用
setCachePoiIds(dayRoomList);
}
} catch (err) {}
} else {
toastCacheStatus('没有缓存');
}
//没有缓存
return null;
};
/**
* 遍历清除过期的第二部分缓存(新老货架共用)
*/
const clearInvalidRoomList = (invalidList, secondKeyPrefix) => {
return new Promise(resolve => {
try {
for (const item of invalidList) {
KNB.clearStorage({
key: secondKeyPrefix + item.uniqueKey, // 数据键,String类型
success: () => {}
});
}
resolve(null);
} catch (err) {
resolve(null);
}
});
};
在前端设置缓存时,需要考虑多个方面,以确保缓存的有效性、安全性和性能优化。以下是设置缓存时需要明确的几个关键内容:
1. 缓存策略(Caching Strategy)
缓存策略决定了如何在客户端和服务器之间管理缓存。常见的缓存策略包括:
- Cache-First:优先从缓存获取数据,如果缓存中没有数据,再从服务器获取。
- Network-First:优先从服务器获取数据,如果服务器不可用,再从缓存获取。
- Cache-Only:只从缓存获取数据,不进行网络请求。
- Network-Only:只从服务器获取数据,不使用缓存。
- Stale-While-Revalidate:先从缓存获取数据,同时在后台请求服务器更新缓存。
2. 缓存位置(Cache Location)
缓存可以存储在不同的位置,每个位置都有其优缺点:
- 浏览器缓存(Browser Cache) :使用浏览器的内置缓存机制,如
localStorage、sessionStorage和IndexedDB。 - Service Worker 缓存:使用 Service Worker 拦截网络请求,并将其缓存。
- 内存缓存(In-Memory Cache) :将数据存储在内存中,适用于短期缓存。
3. 缓存时长(Cache Duration)
缓存时长决定了数据在缓存中存储的时间。可以使用 HTTP 头部字段来控制缓存时长:
- Cache-Control:设置缓存策略和时长,例如
max-age、no-cache、no-store等。 - Expires:设置资源的过期时间。
- ETag:使用实体标签进行缓存验证,确保缓存数据的有效性。
4. 缓存的内容(What to Cache)
需要明确哪些内容需要缓存,以及缓存的粒度:
- 静态资源:如 HTML、CSS、JavaScript 文件、图片等,通常适合长期缓存。
- API 响应:如 JSON 数据,可以根据具体需求设置缓存时长。
- 动态内容:如用户数据,可能需要更频繁地更新缓存。
5. 缓存的更新机制(Cache Invalidation)
缓存失效和更新机制是缓存管理的重要部分,确保缓存数据的准确性:
- 时间失效:设置缓存的过期时间,到期后重新请求数据。
- 版本控制:通过版本号或哈希值管理缓存,资源更新时自动失效旧缓存。
- 手动失效:在特定情况下手动清除缓存,如用户登出时清除用户数据缓存。
6. 安全性(Security)
缓存数据的安全性需要特别注意,防止敏感数据泄漏:
- 敏感数据不缓存:避免缓存用户敏感信息,如密码和个人身份信息。
- HTTPS:确保缓存的数据在传输过程中使用 HTTPS 加密。
7. 性能优化(Performance Optimization)
缓存不仅可以提高性能,还可以减少服务器负载:
- 减少重复请求:通过缓存减少对同一资源的重复请求。
- 预加载和预取:在用户需要之前预加载资源,提高加载速度。
- 压缩数据:使用 gzip 或 brotli 压缩缓存数据,减少传输大小