怎么实现redis的读锁?

梦蝶飘雪 发布于 2016/09/04 21:18
阅读 1K+
收藏 4

解读下一代网络:算力网络正从理想照进现实!>>>

现在有个业务有个需求,用户注册和登录都用的同一个接口,目前我的做法是,当用户的email传递过来后,先去用户表去查询,看该email是否已经存在,如果存在则说明是登录,将用户的id返回即可;如果email不存在,这说明是用户在进行注册,我先讲用户的email入库,然后返回该用户的id。但是目前存在一个问题,如果用户注册时,非常快速的点击两次注册按钮,则后端会插入两条数据。目前我的想法是,在redis中存放用户email相关的一个key值,并且是只读锁,当第二个请求来时,只要该email如果存在于读锁中,则抛弃该请求,直接返回错误提示,可是目前没有找到redis相关的只读锁,求大神支招啊
加载中
2
xinson
xinson
<?php

$ok = $redis->set($key, $random, array('nx', 'ex' => $ttl));

if ($ok) {
    $cache->update();

    if ($redis->get($key) == $random) {
        $redis->del($key);
    }
}

?>
1
0
eechen
eechen
Redis实现锁互斥访问资源及注意事项

避免掉入 SETNX(SET if Not eXists) 陷阱的最好方法就是永远不要使用它:
setnx lock "lock"
expire lock 100
del lock

场景:某个查询数据库的接口,因为调用量比较大,所以加了缓存,并设定缓存过期后刷新.
问题是当并发量比较大的时候,如果没有锁机制,那么缓存过期的瞬间,大量并发请求会穿透缓存直接查询数据库,造成雪崩效应. 如果有锁机制,那么就可以控制只有一个请求去更新缓存,其它的请求视情况要么等待,要么使用过期的缓存.
$key = 'cache_update_lock'; //锁
$random = md5( uniqid(getmypid().'_'.mt_rand().'_', true) ); //随机值
$ttl = 10; //nx表示not exists,ex表示expire,ttl表示time to live,单位是秒.
if( $redis->set($key, $random, ['nx', 'ex' => $ttl]) ) {
    $cache->update(); //加锁后执行业务逻辑,这里是更新缓存
    //加入随机值判断是为了避免删除到其他操作的锁
    if($redis->get($key) == $random) {
        $redis->del($key);
    }
}
0
hphper
hphper
前端也可以稍微控制下吧
梦蝶飘雪
梦蝶飘雪
前端目前设计的没有做控制
0
首席撸出血
首席撸出血

引用来自“xinson”的评论

<?php

$ok = $redis->set($key, $random, array('nx', 'ex' => $ttl));

if ($ok) {
    $cache->update();

    if ($redis->get($key) == $random) {
        $redis->del($key);
    }
}

?>

英雄所见略同


但是如果你用的是java的话,你可以看一下redisson,一个开源项目,支持redis分布式锁比较好的一个项目

0
投资一生
用数据库的事务处理来解决同时插入两条记录的问题。
返回顶部
顶部