1.session共享问题
1. session复制
将session复制每一台服务器上,缺点:每台机器需要网络通信,需要网络开销,有延迟;同时当服务器太多时出现瓶颈,每台都需要备份session,出现内存不够用的情况。早期的项目有些会这样使用
2. session绑定
利用hash算法,将统一ip的用户,分配到同一服务器上,如ngnix的ip_hash负载均衡算法,缺点,当用户ip发生变化,或者服务器宕机时,用户需要重新登陆
3. session服务器
将session信息记录在一台服务器上。缺点需要保证服务器的稳定性
实现:1. 修改sessionManager,如:shiro里
org.apache.shiro.spring.web.ShiroFilterFactoryBean -> securityManager -> sessionManager -> sessionDAO
2. 通过spring-redis-session包实现
2.分布式系统中的缓存
a. CDN:缓存一些静态资源,距离用户最近的网络提供商提供。
b. 反向代理:缓存静态资源,访问网站数据中心前访问。如ngnix
c. 本地缓存:缓存在本地的访问内容,常用的本地缓存开源框架有EhCache。
d. 分布式缓存:缓存在分布式缓存集群中,常用的分布式缓存开源框架有redis,memcache。
3. 缓存更新/删除
1. 再修改数据库时,是更新还是删除缓存,主要看需要更新缓存的代价大小,如果代价小,此时我们应该更倾向于更新缓存,以保证更高的缓存命中率。否则,删除缓存
2. 删除缓存 -> 更新数据库,还是 更新数据库 -> 删除缓存 ???
删除缓存 -> 更新数据库,可能带来的问题是在并发情况下,1线程删除缓存,2线程执行读取操作,缓存未命中重新查询,再将缓存保存;然后1线程再执行更新数据库。此时缓存中的便出现了脏数据。
更新数据库 -> 删除缓存,可能带来的问题是 a. 更新数据库成功后,更新缓存失败;b. 1线程更新数据库,2线程执行读取操作,缓存未命中重新查询完成,1线程更新数据库成功,清除缓存,2线程此时再保存缓存(此概率极低)
3. 更新缓存的策略选取需要根据实际情况,个人理解,当查询的并发量比较高时,优先选取 更新数据库 -> 删除缓存。当没有什么高并发时,删除缓存失败的可能性会更大,此时选择 删除缓存 -> 更新数据库。
4. 为优化 删除缓存 -> 更新数据库方案,有人给出了其他解决方法:https://blog.csdn.net/qq_27384769/article/details/79499373
5. 从上述可知,上面的俩种方案不能确保缓存的准确性,因此我们需要一些辅助促使
a. 每天定时更新缓存(在半夜)
b. 设置缓存失效时间(注意缓存雪崩)
4. 分布式事务
太复杂,待完善
5. 分布式锁