redis session 超时时间_程序员必懂的Redis技术实战

3682d12e2d943d1673eb04838d45955a.gif

阅读本文约需要10分钟,您可以先关注我们,避免下次无法找到。

Redis是现在最受欢迎的NoSQL数据库之一,目前广泛用于缓存系统、分布式锁、计数器、消息队列系统、排行榜、社交网络等场景中,本篇文章成哥为大家带来redis日常使用实践,及通过代码实现redis的分布式锁。

01 Redis简介

Redis是一个开源使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可以持久化的日志类型、key-value数据库,并提供多种语言的API。Redis的出现,很大程度上弥补了Memcache这类key/value存储的不足,在部分场合可以对关系型数据库(MySql、DB2等,关系型数据库通过外键关联来建立表与表之间的关系。非关系型数据库通常指数据以对象的形式存储在数据库中,而对象之间的关系通过每个对象自身的属性来决定)起到很好的补充作用。(如可降低数据库访问压力,弊端冷数据的处理)。

02 Redis实现特点

(1)单线程

Redis是通过单线程实现的,单线程避免了多线程的切换性能损耗问题,同时它所有的数据都在内存中,所有的运算都是内存级别的运算,所以即使是单线程redis还能这么快。但也正是因为使用的是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如keys),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。

(2)IO多路复用

Redis通过IO多路复用解决单线程下并发客户端的访问,redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。具体架构如下:

a475de22733bb29968814ed8c1a921d0.png

03 Redis集群方案比较

(1)哨兵模式

2c63ba93840427ae685f4e6998534550.png

在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可用性等各方面表现一般,特别是在主从切换的瞬间存在访问瞬断的情况,而且哨兵模式只有一个主节点对外提供服务,没法支持很高的并发,且单个主节点内存也不宜设置得过大,否则会导致持久化文件过大,影响数据恢复或主从同步的效率 。

(2)高可用集群模式

9fdaab1e6d98800264d5c553d1521213.png

redis高可用集群是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis集群不需要sentinel哨兵也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点)。redis集群的性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。

04 Redis集群部署常见问题

在了解Redis集群部署常见问题之前我们先来了解一下Redis集群的实现原理。Redis Cluster 将所有数据划分为 16384 的 slots(槽位),每个节点负责其中一部分槽位。槽位的信息存储于每个节点中,当 Redis Cluster 的客户端来连接集群时,它也会得到一份集群的槽位配置信息并将其缓存在客户端本地。这样当客户端要查找某个 key 时,可以直接定位到目标节点。同时因为槽位的信息可能会存在客户端与服务器不一致的情况,还需要纠正机制来实现槽位信息的校验调整。

(1)跳转重定位问题

当客户端向一个错误的节点发出了指令,该节点会发现指令的 key 所在的槽位并不归自己管理,这时它会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去连这个节点去获取数据。客户端收到指令后除了跳转到正确的节点上去操作,还会同步更新纠正本地的槽位映射表缓存,后续所有 key 将使用新的槽位映射表。

(2)网络抖动问题

在生产环境中网络抖动问题不可避免,为解决这种问题,Redis Cluster 提供了一种选项cluster­node­timeout,表示当某个节点持续 timeout 的时间失联时,才可以认定该节点出现故障,需要进行主从切换。如果没有这个选项,网络抖动会导致主从频繁切换 (数据的重新复制)。

05 代码实现基于Redis的分布式锁

在多个进程/线程对同一个共享资源读写场景下,会因为资源的争夺而出现混乱,导致数据不一致。为了避免该问题我们可以在进程/线程在操作共享资源前获取一个令牌(也就锁),只有获取了该令牌的进程/线程才可以操作资源,在操作完资源后释放该令牌。这就实现了分布式锁。

Redis的分布式锁是基于Redis SETNX命令来实现的,在Redis中通过SETNX命令设置Key Value时有如下两种结果:

1)返回1,表示为指定的key设置值成功,也即表示当前进程已经获取了锁资源

2)返回0,表示为指定的key设置值失败,因为当前已存在该key,也即表示其它进程获取了锁资源

下面我们就来看看怎么通过python实现分布式锁吧

(1)首先我们创建一个不使用分布式锁的示列,通过多线程对全局变量进行加1操作看看结果如何,具体代码如下:

7008a10968833c39752b59078eaa73e8.png

代码运行结果如下,发现不是我们预期的值(预期值应为3+3=6)

2339a8504c9e77cc787b3790b5a3131a.png

(2)接着我们创建带分布式锁的示列,我们先来看看分布式锁创建的方法,具体如下

1. import time  2. import uuid  3. from redis import StrictRedis, ConnectionPool  4. import threading  5.   6. class CollectRedis:  7.     # 创建redis操作类   8.     def __init__(self):  9.         self.host = "1.1.1.1"  10.         self.port = 6379  11.         self.db = 5  12.  13.     @property  14.     def redis_session(self):  15.         _session = getattr(self, "__redis_session", None)  16.         if _session:  17.             return _session  18.         redis_pool = ConnectionPool(host=self.host, port=self.port, db=self.db)  19.         _session = StrictRedis(connection_pool=redis_pool)  20.         setattr(self, "__redis_session", _session)  21.         return _session  22.       23.     # 获取锁  24.     def get_lock(self, lock_key):  25.         return self.redis_session.get(lock_key)  26.       27.     # 设置锁   28.     def set_lock(self, lock_key, value, timeout=300):  29.         session = self.redis_session  30.         tag = session.setnx(lock_key, value)  31.         # 如果key能创建成功则为该key设置一个超时时间,这个相当于锁的有效时间  32.         # 如果没有超时时间则会导致程序死锁  33.         if tag:  34.             session.expire(lock_key, timeout)  35.         return tag  36.       37.     # 删除锁也就是释放锁  38.     def delete_lock(self, lock_key):  39.         return self.redis_session.delete(lock_key)  40.   41. # 获取锁资源方法  42. def acquire_lock(lock_name, time_out=300):  43.     identifier = str(uuid.uuid4())  44.     end = time.time() + time_out + 30  45.     redis_connect = CollectRedis()  46.     # 如果不能获取锁资源则线程一直挂起直到获取锁资源或者超时  47.     while time.time() 

(3)最后我们在计算函数中增加分布式锁装饰器,然后查看程序运行结果是否符合预期,具体如下

31f8bed3f81f1237898a5d1761fc9952.png
6e8500ad49996080bff85e82f080a0df.png

06 总结

本篇文章主要带大家了解了Redis的一些特点、部署方案、集群中容器遇到的问题及如何基于redis实现分布式锁等内容,如果喜欢本篇文章不要忘了点赞、关注与转发哦!

--END--

@IT管理局专注计算机领域技术、大学生活、学习方法、求职招聘、职业规划、职场感悟等类型的原创内容。期待与你相遇,和你一同成长。

推荐文章:

  • 程序员也需了解的主流云计算网络架构
  • IT工程师都需要掌握的容器技术之扫盲篇
e786245972870b11c6d29924244ede97.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet.Applet 简单实现!~ 网页表格组件 GWT Advanced Table GWT Advanced Table 是一个基于 GWT 框架的网页表格组件,可实现分页数据显示、数据排序和过滤等功能! Google Tag Library 该标记库和 Google 有关。使用该标记库,利用 Google 为你的网站提供网站查询,并且可以直接在你的网页里面显示搜查的结果。 github-java-api github-java-api 是 Github 网站 API 的 Java 语言版本。 java缓存工具 SimpleCache SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的定义 4. 使用redis作缓存时,支持list类型的高级数据结构,更适合论坛帖子列表这种类型的数据 5. 支持混合使用redis缓存和memcached缓存。可以将列表数据缓存到redis中,其他kv结构数据继续缓存到memcached 6. 支持redis的主从集群,可以做读写分离。缓存读取自redis的slave节点,写入到redis的master节点。 Java对象的SQL接口 JoSQL JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于【自动提示】的需要(如:Google搜索), 而开发的架构无关的公共控件, 以满足该类需求可以通过快速配置来开发。AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是一个用来操作Windows注册表的 Java 类库,你可以用来对注册表信息进行读写。 GIF动画制作工具 GiftedMotion GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的PList类库 Blister Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端 JOpenID JOpenID是一个轻量级的OpenID 2.0 Java客户端,仅50KB+(含源代码),允许任何Web网站通过OpenID支持用户直接登录而无需注册,例如Google Account或Yahoo Account。 JActor的文件持久化组件 JFile JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还能够与JSTL相结合生成数据库驱动的动态Maps。 OAuth 实现框架 Agorava Agorava 是一个实现了 OAuth 1.0a 和 OAuth 2.0 的框架,提供了简单的方式通过社交媒体进行身份认证的功能。 Eclipse的JavaScript插件 JSEditor JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接池的性能,根据某些测试数据发现,BoneCP是最快的连接池。BoneCP很小,只有四十几K

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值