- 到redis官网下载redis压缩包
- tar -zxvf redis-5.0.8.tar.gz
- mv redis-5.0.8 /usr/local/redis
- cd /usr/local/redis
- make -j 4
- make install
- vi redis.conf 把# requirepass foobared 改为 requirepass 123456(设置密码);127.0.0.1 改为 0.0.0.0(允许全部主机访问);daemonize no 改为 yes(允许后台执行)
- redis-server ./redis.conf (启动)
- redis-cli (客户端连接)
- ./utils/install_server.sh
- 配置项:回车、/usr/local/redis/redis.conf、/usr/local/redis/redis.log、/usr/local/redis/data、回车、回车
- 查看安装的服务:chkconfig --list | grep redis
- 查看这个服务的配置:vi /etc/rc.d/init.d/redis_6379
- 关闭/重启:systemctl stop/start redis_6379
用户端:PASS = MD5(明文 + 固定salt)
- 服务端:PASS = MD5(用户输入,即前段传回来的PASS + 随机alt)
- 之后再保存到后台数据库
- 通过用户输入的账号密码查询到用户信息
- 生成token作为key,将用户信息持久化到redis
- 将token保存到cookie中,并将cookie共享到同一个应用服务器中
- 为用户类添加一个参数解析器
- 参数解析器中获取token,从而获取用户信息,并将用户信息放回出去
- 将该参数解析器添加到WebMvc配置中
- 在controller上把用户类作为参数传入,webMvc会自动通过参数解析器来填充用户信息
- 如果用户信息不为null,则允许用户继续访问页面;否则返回登录页面
### 页面缓存+URL缓存+对象缓存
- 注入thymeleaf视图解析器和上下文对象(ThymeleafViewResolver+ApplicationContext)
- 从redis中取页面缓存,没有的话新建一个IWebContext对象,从ThymeleafViewResolver中取
- 其实与页面缓存差不多,几乎一样
- 其实与页面缓存和页面缓存差不多
- 对象缓存不会设置失效时间
- 但是对象更新时,要更新缓存
- 详情查看:点击前往
咱们这里模拟,请求static下的静态页面,在该页面通过ajax发送请求来渲染页面数据
如:AngularJS、Vue.js,利用浏览器缓存
- CDN就近访问,点击前往
查看系统版本信息:lsb_release -a
- 分别安装Erlang、Socat、RabbitMQ(一定按照顺序!)
wget https://www.rabbitmq.com/releases/erlang/erlang-19.0.4-1.el7.centos.x86_64.rpm
wget https://www.rabbitmq.com/releases/rabbitmq-server/v3.6.15/rabbitmq-server-3.6.15-1.el6.noarch.rpm
wget http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm
rpm -ivh erlang-19.0.4-1.el7.centos.x86_64.rpm
rpm -ivh socat-1.7.3.2-5.el7.lux.x86_64.rpm
rpm -ivh rabbitmq-server-3.6.15-1.el6.noarch.rpm
- 配置rabbitmq
vi /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.15/ebin/rabbit.app
将 {loopback_users, [<<"guest">>]} 改为 {loopback_users, []}
- 安装管理插件:rabbitmq-plugins enable rabbitmq_management
- 启动RabbitMQ,然后访问IP:5672/,默认用户名密码:guest即可查看
cd /usr/lib/rabbitmq/bin
./rabbitmq-server start
思路:减少数据库访问
- 系统初始化时,把商品库存数量加载到redis
- 收到请求时,redis预减库存,库存不足,直接返回,否则进入第三步
- 请求入队(消息队列),立即返回信息:“排队中”
- 请求出队,生产订单,减少库存
- 客户端轮询,是否秒杀成功
总结:
其实简单来说,就是用户点击秒杀时,将消息发送到消息中间件中的某个队列里
然后直接返回一个标识,表示排队中
消息消费者使用RabbitListener监听这个队列,当消息到达时消费这个消息,调用接口进行业务操作
当客户端收到服务端返回的标识后,再发送一个请求到服务端判断订单状态
注意轮询的时间,不能太快也不能太慢
- 接口改造,带上PathVariable参数
- 添加生成的地址的接口
- 秒杀收到请求,先验证PathVariable
总结:
其实简单来说,就是在执行主业务代码前先请求一次后台,随机生成一个字符串,保存到redis中并返回客户端
当客户端请求成功后,才真正请求主业务代码接口,并将这个path串带上
主业务代码接口读取redis校验这个path串,匹配成功才执行主业务代码
否则返回错误信息,有效方式他人恶意调用主业务代码
ScriptEngine的使用
总结:
其实简单来说,就是在controller层调用接口,后台自动随机生成一个数学表达式
然后将表达式写入BufferedImage对象中
通过ScriptEngine计算出这个数学表达式的值,并保存到redis中
再通过ImageIO接口将HttpServletResponse的OutputStream对象和BufferedImage以图片格式写出到img标签的src下
当用户提交的验证码的值与redis中的匹配时,删除redis中的记录,并继续执行业务代码
否则返回错误信息
自定义AccessLimit注解,可以使用拦截器减少对业务的侵入
总结:
AccessLimit参数解释:seconds-多少秒内 maxCount-允许访问多少次接口 needLogin-是否需要登录
其实简单来说,就是为AccessLimit注解添加一个拦截器
将用户id和接口URL作为key 将访问次数作为value,保存到redis中
如果是第一次访问,就往redis中插入一条数据,value为1,过期时间为seconds参数
如果不是第一次访问,且未超过maxCount限制,就将value自增1
如果seconds秒内超过了maxCount限制,就返回false并通过HttpServletResponse的OutputStream对象将错误信息写出去