设为首页 收藏本站
查看: 543|回复: 0

[经验分享] Redis事务和脚本功能

[复制链接]

尚未签到

发表于 2016-12-18 10:58:00 | 显示全部楼层 |阅读模式
  Redis事务是指将一些命令打包,一次性按顺序执行多个命令的机制,不会出现并发的情况,将命令都执行完以后才会执行其他命令。在一定程度上满足ACID特性。
    1、Redis事务原理
  事务由命令MULTI开始,使执行命令的客户端切换到事务状态,之后当执行EXEC、DISCARD、WATCH、MULTI以外的命令均会将命令放在一个先进先出的队列中。当向客户端发送EXEC命令时,服务器将会遍历事务队列按顺序执行其中的指令。并将返回结果在执行完毕后一起返回。
  由于事务的命令提交是一个过程,在事务命令提交过程中即在EXEC执行之前,存在事务执行的命令被修改的可能,若对事务中的某些key修改敏感,可以使用WATCH命令监听某些key,如果在事务执行之前监听的key被修改,则该事物拒绝执行。其实现原理是在Redis中保存了一个监听key的字典,key为监听的键而value是监听该键的数据库客户端。当key被修改后Redis会查看该字典该key是否被客户端监听,若正在被监听则会打开value对应的客户端的REDIS_DIRTY_CAS标识,当执行EXEC命令时会检测该标识是否打开,打开则拒绝执行该事务。
  注意,WATCH命令的作用只是当被监控键被修改后阻止之后的一个事务执行,而不能保证其他客户端是否修改,同时监听的有效期是EXEC之后,之后所有的监控被取消。
  ACID特性
  原子性,指的是数据库将食物中的多个操作当做一个整体来执行,服务器要么全部执行,要么全不执行。Redis事务具有原子性,但Redis不具有回滚机制,及时某个命令出现错误也会继续执行后面的命令。
  一致性,指的是数据库在事务执行之前是一致的,那么在执行之后也是一致的,没有非法或无效的错误。Redis事务中有三类错误,一是命令不存在或命令格式不正确的错误,在入队时可发现,事务拒绝执行。对数据库键执行错误类型的操作是第二类错误,跳过错误执行继续执行。宕机是第三类错误,但数据仍能保证一致性。
  隔离性,指数据库中多个事务并发执行也互不影响,与顺序执行结果相同。Redis是单线程顺序执行事务,因此满足隔离性。
  持久性,指当执行以后永久保存到存储中。Redis的持久性由Redis的持久化机制来决定,无持久化则没有持久性,RDB机制需要条件触发也不满足,AOF机制当appendfsync为always是满足持久性,而为everysec时会出现数据丢失也不满足,为no时也不具有持久性。
   2、Lua脚本
  与Redis事务类似,Lua脚本功能是将Redis的命令打包成一个lua脚本,在服务器端原子的执行。与Redis的事务特性相比减少了网络开销,一次提交打包的命令;原子性执行避免出现Watch的竞态条件;同时可以被复用,存储以便之后继续使用。
    创建Redis的Lua环境
  调用lua_open创建原始lua环境,载入Lua函数库包括base、table、string、math、debug、struct等库,可以修改redis返回的数据。创建全局表格包括Redis.call和Redis.pcall、Redis.log等执行redis命令的函数。
  为保证相同的脚本在不同的机器上产生相同的结果,Redis要求Lua中运行的函数是无副作用的纯函数。主要涉及随机函数和排序函数。math的随机函数有副作用,Redis使用自己的随机函数,只要种子seed相同结果相同。同时像集合这种无序的类型内容相同但是添加顺序不同也会造成结果不同。因此对于顺序敏感的命令Redis会先做一次排序。
  创建错误处理辅助函数,在脚本中的变量应使用local生命避免污染环境,如果没有加local会报错。
  Redis会将创建的Lua环境在redisServer结构体中与Redis进行关联。
    执行Lua脚本
  Redis执行命令必须有客户端状态,这里为了执行Lua脚本通过伪客户端执行。执行步骤如下图
DSC0000.png


  Redis创建lua字典用来保存lua脚本,键是检验和值是Lua脚本。RVAL和SCRIPT LOAD载入的脚本都会被保存。EVAL会将脚本定义名为一个f_+校验和的函数,之后将脚本添加到字典中,最后将EVAL传入的键名和参数作为keys数组和ARGV数组作为全局变量传入lua环境,并设置钩子函数,执行脚本会进行垃圾回收。
  EVAL script numkeys key [key ...] arg [arg ...]
  另一个执行lua脚本的命令是EVALSHA,用于之前已经在LUA环境中定义过的脚本,通过SHA1校验和调用。SCRIPT FLUSH用于清除服务器中所有lua脚本的信息,释放字典内容,重新创新新lua环境。SCRIPT EXISTS命令根据输入的检验和检查对应的脚本是否存在。SCRIPT LOAD与EVAL相同。SCRIPT KILL进行超时处理。
  EVALSHA sha1 numkeys key [key ...] arg [arg ...]
    Lua脚本的复制。
  EVAL、SCRIPT FLUSH、SCRIPT LOAD命令直接同步,在主从服务器都会被执行。EVALSHA命令根据校验和执行,但主从服务器可能保存的脚本情况不一,可能出现脚本找不到的情况。因此Redis在复制EVALSHA时会先通过reol_scriptcache_dict字典记录的所有lua脚本中查看是否有该校验和, 如果没有则转换我EVAL命令进行传播。当添加新的从服务器是,会清空reol_scriptcache_dict字典,来确保新的从服务器不会出现脚本找不到的错误。
    其他
  为了防止某个脚本执行时间过长导致Redis无法提供服务(比如陷入死循环),Redis提供了lua-time-limit参数限制脚本的最长运行时间,默认为5秒钟。当脚本运行时间超过这一限制后,Redis将开始接受其他命令但不会执行(以确保脚本的原子性,因为此时脚本并没有被终止),而是会返回“BUSY”错误。通过SHUTDOWN NOSAVE不进行持久化来操作

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-315947-1-1.html 上篇帖子: Redis 集群(上)(转载) 下篇帖子: keepalived实现redis主从高可用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表