网站设计公司服务平台,wordpress选择哪种固定连接,wordpress优化攻略,代账公司网站模板1.使用工厂模式和策略模式实现布隆过滤器解决缓存穿透问题
Bitmap
Bitmap是一种数据结构#xff0c;它使用位图来表示数据。在处理大量数据时#xff0c;Bitmap可以通过将每个数据元素映射到一个位#xff0c;然后使用位运算来对数据进行操作。 通过使用Bitmap#xff0c…1.使用工厂模式和策略模式实现布隆过滤器解决缓存穿透问题
Bitmap
Bitmap是一种数据结构它使用位图来表示数据。在处理大量数据时Bitmap可以通过将每个数据元素映射到一个位然后使用位运算来对数据进行操作。 通过使用Bitmap我们可以快速地完成排序、查找和去重等操作。优点极大的节省储存空间。但是Bitmap也存在一些局限性例如它只能表示有限的数值类型并且对于数据稀疏的情况可能不太适用。
布隆过滤器
布隆过滤器是一种用于快速检索一个元素是否可能存在于一个集合中的数据结构。 它的基本原理是利用多个哈希函数将一个元素映射成多个位然后将这些位设置为1。当查询一个元素时如果这些位都被设置为1则认为元素可能存在于集合中。布隆过滤器的优点在于它的内存占用极少并且不局限于数值类型。但是由于哈希冲突的存在布隆过滤器也存在误判的可能。
缓存穿透
访问的资源不存在而导致这个不存在的数据每次请求都要到数据库中去查询导致数据库挂掉
用布隆过滤器解决缓存穿透问题
不直接访问数据库而是先通过布隆过滤器判断访问的资源是否存在存在则放行不存在则拦截。 使用BitMap作为布隆过滤器通过多个哈希函数来将被访问的元素映射到位数组中的多个位置上将对应的位置设置为1。 当需要判断一个元素是否在布隆过滤器中时只需将该元素进行多次哈希并检查对应的位数组位置是否都为1如果其中有任意一位为0则说明该元素不在集合中如果所有位都为1则说明该元素可能在集合中因为有可能存在哈希冲突需要进一步检查。
使用工厂模式和策略模式解决缓存穿透问题
定义布隆过滤器接口首先定义一个布隆过滤器接口包括添加元素和判断元素是否存在两个基本操作。实现具体的布隆过滤器类创建类实现布隆过滤器接口中的方法。在这个类中需要定义布隆过滗器的数据结构比如位数组、大小等属性。定义哈希策略接口定义一个哈希策略接口包含计算哈希值的方法。实现具体的哈希策略类创建多个具体的哈希策略类每个类对应一种哈希函数的计算方法。创建布隆过滤器工厂类定义一个布隆过滤器工厂类其中包含一个用于创建布隆过滤器对象的工厂方法。工厂方法接受布隆过滤器的大小和哈希策略对象作为参数并返回一个具体的布隆过滤器对象。使用布隆过滤器工厂在需要创建布隆过滤器对象的地方调用布隆过滤器工厂的工厂方法来创建布隆过滤器对象并传入相应的哈希策略对象。 总结使用策略模式是创建多个具体的哈希策略类每个类对应一种哈希函数。并且创建布隆过滤器的工厂类。 当需要创建布隆过滤器对象时直接调用工厂类并传入相应的哈希策略对象。 这样可以将对象的创建和哈希函数的选择解耦更灵活的创建对象和选择哈希函数。
好处
使用工厂模式和策略模式来实现布隆过滤器带来以下好处
1解耦性工厂模式和策略模式的结合可以将对象的创建和哈希函数的选择分离使得各部分之间的耦合度降低。这样在需要修改布隆过滤器的具体实现或者切换哈希函数时只需要修改相应的工厂类或策略类而不影响其他部分。 2可扩展性通过工厂模式和策略模式我们可以方便地添加新的布隆过滤器实现类和哈希函数策略类而不需要修改现有代码。这样在需要增加新的布隆过滤器类型或者新的哈希函数时只需添加相应的类即可。
2.使用Redis采用一主两从哨兵的集群方案
使用Redis
当用户数量较多时用户频繁的访问数据库数据库压力增大系统的性能下降。因此使用Redis对数据进行缓存减小数据库的压力提高系统的性能和访问速度。
为什么采用一主两从哨兵的集群方案解决高并发高可用问题
进一步提高Redis的并发能力可以搭建主从集群实现读写分离。 我们项目的redis采用一主二从的集群方案主节点负责写数据从节点负责读数据主节点写入数据之后需要把数据同步到从节点中实现了读写分离解决了高并发问题。 哨兵是一个独立的进程作为进程它会独立运行。其原理是哨兵通过发送ping命令等待Redis服务器响应从而监控运行的多个Redis实例。 哨兵可以实现自动故障修复哨兵可以监测到主节点宕机自动将从节点切换为主节点并发布通知其他从服务器修改配置文件当旧主服务器恢复后会成为一个新的从节点。
怎样解决高并发高可用问题
主从集群保证高并发哨兵保证高可用。
怎样解决数据一致性问题
数据一致性当修改了数据库的数据也要同时更新缓存的数据缓存和数据库的数据要保持一致。 使用旁路缓存模式在缓存与数据库双写时保持一致性。 先更新数据库后删除缓存。理论上会出现不一致的情况但概率较小因为缓存的写入速度是比数据库的写入速度快很多。
**更新缓存替换为删除缓存**那么**下一次执行的查询操作都会从数据库中加载数据**此时数据一致性就有了保证。比较方法时注意缓存被清空后线程只能到数据库中查询在数据库中查完就会直接更新缓存。
先查缓存再查数据库。
**重点在与看结束后数据库与缓存是否一致用多久一致的。**1先删缓存再更新数据库
多线程调度不确定可能会导致A删缓存B去查缓存“空”--然后去查数据库--拿着数据库中数据更新缓存--A更新数据库
结束后数据库中是A更新后的信息缓存中是原始信息。2先更数据库再删缓存
A更数据库B查缓存--B拿到原始数据--A删除缓存
结束后数据库中新数据缓存被删即还会获得新数据。【从B在数据库拿到原始数据到写到缓存中但持续时间相比其他方法短】3延迟双删
A删缓存B去查缓存“空”--然后去查数据库--拿着数据库中数据更新缓存--A更新数据库--延迟删除缓存
结束后相比1最后缓存与数据库时一致的但性能上不如2总结采取旁路缓存使缓存和数据库保持数据的一致性 读的时候先读缓存缓存没有的话就读数据库然后取出数据后放入缓存同时返回响应。 更新的时候先更新数据库再删除缓存中对应着数据库更新的数据。
3.使用Spring Task实现订单超时取消使用WebSocket实现用户催单。
WebSocket
基于TCP的一种新的网络协议。实现了浏览器与服务器全双工通信——浏览器和服务器只需完成一次握手两者就可以建立连接双向数据传输。 WebSocket两边都可以主动通信。 应用场景网页聊天、视频弹幕股票信息实时更新服务器主动推送到网页上的
订单超时取消流程
客户下单后未支付订单一直处于“待支付”状态。 使用Spring Task工具的cron表达式设置定时任务触发时间每分钟检查一次是否存在支付超时的订单如果存在超时则将订单状态修改为“已取消”。
用户催单流程
用户在小程序中点击催单按钮后根据用户id查询是否有支付成功的订单有则调用WebSocke实现服务端向客户端推送消息展示用户订单和支付成功信息。
4.使用自定义拦截器和JWT令牌实现用户登录认证用ThreadLocal存储用户ID
用户登录认证流程
1用户登录时发送用户名和密码给服务器服务器验证通过则生成一个包含用户信息的JWT令牌并将其发送给客户端。 2客户端受到JWT令牌后保存在本地中 3每当用户发起请求时将JWT令牌添加到请求头中 4服务器端的自定义拦截器会拦截所有请求从请求头中提取JWT令牌。 5拦截器解析JWT令牌获取用户信息并将其存储在ThreadLocal中,以避免在每次请求时都去解析JWT令牌。 6拦截器可以检查用户是否已经通过认证通过则处理请求未通过则返回错误信息。 7请求完成后拦截器remove清楚ThreadLocal里的用户信息
为什么用JWT不用Session
传统的Session用户认证方案:
(1)用户向服务器发送用户名和密码。 (2)服务器验证通过后在当前**对话session**里面保存相关数据比如用户角色、登录时间等等。 (3)服务器向用户返回一个 session_id写入用户的 Cookie。 (4)用户随后的每一次请求都会通过 Cookie将 session_id 传回服务器。 (5)服务器收到 session_id找到对应的session并获取前期保存的数据由此得知用户的身份。
这种传统的通过session的方式适用于前后端不分离的情况因为session是保存在服务器端因此对于跨域或服务器集群的情况很不友好。 而JWT解决了跨域问题而且1jwt基于json数据处理方便。2使用非对称加密和签名技术安全性高。3资源服务使用JWT可不依赖认证服务即可完成授权。
为什么用ThreadLocal
ThreadLocal为每个线程提供单独一份存储空间具有线程隔离的效果只有在线程内才能获取到对应的值线程外则不能访问。 这样可以保证线程之间的数据隔离避免了线程安全问题。
ThreadLocal使用流程
每次执行请求时拦截器将用户信息用set保存在ThreadLocal中ThreadLocal每次调用set时是一个独立的线程当另一个用户调用ThreadLocal的set时方法 时就会新建另一个线程线程之间互不影响当对应线程在调用get时候就会请求到set时候的信息。在拦截器执行过后的方法中添加ThreadLocal线程remove()方法这样每次请求结束后会将ThreadLocal线程中的数据删除这样可以防止线程过多内存泄露。
为什么用拦截器不用过滤器、切面
粒度更细 拦截器可以针对特定的控制器或控制器方法进行拦截实现精确的拦截逻辑 而过滤器是基于URL路径进行拦截无法做到针对具体的控制器或方法切面也是基于切点进行拦截粒度相对较粗。
5.使用AOP统一记录登录者操作日志
使用AOP切片将登陆者增删改用户信息的操作信息记录到数据库中。
流程
1建表日志信息表 2自定义注解在增删改等方法运行时调用切面 3定义切面类操作者记录先通过当前请求的请求头拿到JWT令牌并解析出操作者的用户ID然后记录操作命令和操作时间等信息插入到日志信息表中。
6.使用Redis分布式锁实现高并发商品秒杀解决超卖问题
为什么不用单体锁
单体应用难以满足实际高并发访问需求会将单体应用部署到多个tomcat实例上由负载均衡将请求分发到不同实例上。 单体锁synchronized、ReentrantLock是JVM层面的锁只能控制单个实例上的并发访问安全多实例下依然存在数据一致性问题。
分布式锁
分布式锁指的是所有服务中的所有线程都去获取同一把锁但只有一个线程可以成功的获得锁其他没有获得锁的线程必须全部等待直到持有锁的线程释放锁。
RedLock解决Redis集群主从不同步数据丢失问题
Redisson使用主从集群模式主节点挂掉从节点没有同步到锁的情况 使用RedLock针对Redis中所有节点来进行同步能够保证超过半数的Redis加锁了才算加锁成功从而保证并发安全。
解决流程
多用户并发操作的情况下多个用户尝试购买同一件商品导致商品库存不足或者超卖。 采用Redis提供的Redisson组件实现Redis分布式锁来控制并发访问。 当一个线程去获取锁锁的VALUE中存入UUID来保证锁和当前线程绑定 当前线程获取锁成功开始处理业务时内部会有watch dog看门狗每隔10s看当前线程是否还持有锁如果持有则给锁延长生存时间。
当Redis集群部署时为了解决主节点挂掉从节点没有同步到锁的情况使用RedLock针对Redis中所有节点来进行同步能够保证超过半数的Redis加锁了才算加锁成功从而保证并发安全。
另外用户限流防止同一用户多次秒杀
使用布隆过滤器记录用户和商品ID来解决。 当用户参与秒杀时判断是否ID是否记录存在布隆过滤器中不存在证明该用户是第一次参与秒杀改商品放行继续后续业务 过滤器中存在则禁止继续秒杀。
7.基于Redis使用防重Token和lua脚本防止重复提交订单
lua脚本作用
使用lua脚本实现原子性的查询并删除操作。为了确保即使多个请求同时到达也只有一个请求能够成功删除Token。
流程
用户发起请求时服务端生成唯一的token作为信息凭证。 将Token存入Redis并设定过期时间防止Redis内存溢出。 在后续请求中要携带这个Token服务器收到后在Redis中通过lua脚本进行原子性的查询并删除操作 如果Token存在并被成功删除说明是第一次请求则继续处理业务生成订单如果不存在说明是重复请求则返回错误提示。