面试题答案
一键面试缓存一致性策略
- 读写顺序控制:
- 写操作:
- 先更新数据库,再删除缓存。这样做是因为如果先删除缓存,在更新数据库前其他读请求过来,会重新从数据库加载旧数据到缓存,导致缓存不一致。更新数据库后删除缓存,下次读操作会重新加载最新数据到缓存。
- 但这种策略存在并发问题,比如A线程更新数据库,B线程在A线程删除缓存前读取数据库并写入缓存,就会导致缓存数据为旧数据。可以通过加分布式锁来解决,只有获取到锁的线程才能进行更新数据库和删除缓存操作。
- 读操作:
- 先从缓存读取数据,如果缓存命中则直接返回;如果缓存未命中,则从数据库读取数据,然后将数据写入缓存并返回。
- 写操作:
- 缓存失效时间设置:
- 为缓存数据设置合理的失效时间。当缓存数据过期后,下一次读请求会从数据库重新加载数据到缓存,从而保证数据的一致性。较短的失效时间可以更快地使缓存数据更新,但会增加数据库的读压力;较长的失效时间则相反。需要根据业务场景和数据更新频率来权衡设置。
- 异步更新缓存:
- 使用消息队列(如Kafka等)。当数据库发生更新时,发送一条消息到消息队列,专门有一个消费者负责接收消息并删除或更新缓存。这种方式可以将数据库更新和缓存更新解耦,提高系统的整体性能和可用性。同时,通过消息队列的重试机制可以保证缓存更新操作的可靠性。
高并发场景下避免数据不一致
- 分布式锁:在写操作时,使用分布式锁(如Redis分布式锁),只有获取到锁的节点才能执行更新数据库和删除缓存的操作。这样可以避免多个节点同时更新缓存导致的数据不一致。
- 读写锁:在缓存层面使用读写锁。读操作可以并发进行,因为读操作不会改变数据,而写操作需要获取写锁,只有获取到写锁才能进行写操作,写操作时会阻塞读操作,保证在写操作期间数据的一致性。
- 版本控制:在数据库表中增加一个版本号字段。每次更新数据时,版本号递增。读取数据时,将版本号一同读入缓存。当写操作时,先读取当前版本号,更新数据后递增版本号,并将新的版本号写入数据库和缓存。读操作时,对比缓存中的版本号和数据库中的版本号,如果不一致则重新从数据库加载数据,保证缓存数据的一致性。