Redis incr解决并发订单问题

场景:

1、新增订单,订单编码字段的规则为 “DD+yyyyMMdd+0000001。

2、每天订单量10万

思路:

1、假设redis服务器绝对安全

2、将订单编码存到缓存中(redis),其值只存“DD”+yyyyMMdd后面的数字部分;

对应的key为:key标识+yyyyMMdd,即每天一个key

3、每次生成订单编码时,先调用redis的incr方法,使其在原来编码的基础上加1,并返回结果

4、判断返回的结果,如果返回的是1,说明当前key之前不存在,为生成的新的一天的key,

6、如果redis宕机,或者key被删除,调用指定的接口,接口会去数据库查询今天最大的订单编码,

解析后,将其存在redis中,后面的订单编码再在此基础上自增

PHP实现:

$key = 'DD'.date('Ymd', time());
$id = $redis->incr($key);
$final_id = '';
        $l = strlen($id);
        if ($l>6) {
            $final_id =  $id;
        } else {
            $final_id = str_repeat(0, 6-$l).$id;//用0填充到6位数字
        }
echo $key.$final_id;

针对上面第6条
数据库查询当天最新订单号,处理提取出数值 $v,重新赋值给$key
$redis->set($key,$v);

分布式环境session共享解决方案

背景:

假设第一次访问服务A生成一个sessionid并且存入cookie中,第二次却访问服务B客户端会在cookie中读取sessionid加入到请求头中,如果在服务B通过sessionid没有找到对应的数据那么它创建一个新的并且将sessionid返回给客户端,这样并不能共享我们的Session无法达到我们想要的目的。

解决方案:

  • 使用cookie(安全性问题)
  • 使用Nginx中的ip绑定策略,同一个ip只能在指定的同一个机器访问(不支持负载均衡)
  • 利用数据库同步session(效率问题)
  • 使用token代替session
  • 存放在redis中

nginx解决方案

提供了ip_hash策略,可以保持用户ip进行hash值计算固定分配到某台服务器上,然后只要是该ip则会保持分配到该服务器上,保证用户访问的是同一台服务器,那么session问题就不存在了。这也是解决session共享的一种方式,也称为黏性session。但是假设一台tomcat服务器挂了的话,那么session也会丢失。所以比较好的方案是抽取session

Redis解决方案

1.  session数据如何在Redis中存储?

2.  session属性变更何时触发存储?

考虑到session中数据类似map的结构,采用redis中hash存储session数据比较合适,如果使用单个value存储session数据,不加锁的情况下,就会存在session覆盖的问题,因此使用hash存储session,每次只保存本次变更session属性的数据,避免了锁处理,性能更好

如果每改一个session的属性就触发存储,在变更较多session属性时会触发多次redis写操作,对性能也会有影响,我们是在每次请求处理完后,做一次session的写入,并且之写入变更过的属性

如果本次没有做session的更改, 是不会做redis写入的,仅当没有变更的session超过一个时间阀值(不变更session刷新过期时间的阀值),就会触发session保存,以便session能够延长有效期