Redis 在支付标记化系统中的应用 | 最佳实践
原题:《Redis最佳实践--以支付标记化》
1.项目介绍
为落实《网络支付报文结构及要素技术规范》(银办发〔2016〕222号)、《中国人民银行关于加强支付结算管理防范电信网络新型违法犯罪有关事项的通知》(银发〔2016〕261号)、《非银行支付机构网络支付业务管理办法》(中国人民银行公告〔2015〕第43号)等监管文件要求,与第三方支付机构进行的交易中的账号信息均需要进行标记化处理。目前清算机构和第三方支付机构、银行已有或规划了标记化服务,其中银联,部分银行,部分支付机构(如支付宝)已经建立了支付标记化系统(以下简称TSP),网联也将其进行了规划。
2.项目目标
2.1 项目总体要求:
支付标记化技术平台应在充分考虑互操作性、兼容性的基础上,解决卡号信息泄露、支付场景认证等方面的问题。
支付标记化服务应具备通用性和互操作性,方案设计在系统交互、数据报文、交易路由以及授权处理上均应遵循互联互通的原则。
支付标记在确保与现有的支付流程进行融合的同时,有效加强身份 认证与风险监控。支付标记申请时,该标记被限定在某一特定应用范围,且身份认证手段作为支付标记申请过程中的重要步骤被执行,其担保级别表明了该支付标记与卡号绑定关系的可信程度;交易发生时,TSP将验证支付标记的应用场景,同时借助担保级别的相关要素进行风险监控。
2.2 项目具体目标:
2.2.1 接入要求
TSP服务系统支持多渠道多机构接入。
2.2.2 性能需求
根据对应用机构相关业务量的分析调研得出,TSP服务系统需达到如下性能要求:
(一)并发数达到30000TPS;
(二)响应速度小于0.1S;
(三)系统支持7*24小时服务;
(四)系统采用集群部署,防止单点运行的风险出现。
2.2.3 可扩展性需求
为了满足系统的安全性和高可用性要求,WEB服务器部署在互联网区域内、应用层服务器、缓存服务器、数据库部署在互联网区域后;WEB服务器支持多节点负载均衡、集群部署,应用层服务器支持无状态横向扩展,可进行多节点负载均衡、集群部署,要求如下:
(一)应用服务器采用集群部署;
(二)采用分布式数据库;
(三)缓存服务器支持负载均衡、集群部署、主从复制的方式同步数据;
2.2.4 可靠性需求
主要指在软件失效的频率、严重程度、易恢复性,以及故障可预测性等方面的要求。
TSP系统性能可靠性要求如下:
(一)TSP系统应满足未来三年业务运行的性能需求。
(二)系统应支持业务的多用户并发操作;在规定的硬件环境条件和给定的业务压力下,系统应满足性能需求和压力解除后系统自恢复能力;系统性能极限应满足业务需求。
(三)应结合典型交易、复杂业务流程、频繁的用户操作、大数据量处理等原则,选取测试业务点进行检测。
3.项目内容
TSP系统中提供两种服务,分别如下:
3.1 标记生成服务
输入要素:需要上送给应用方的1.机构号;2.账号信息(包含账号,户名,手机号,身份 证号等);3.标记种类。
输出结果:返回标记信息。
使用加密算法进行标记,生成后插入标记库并返回给请求方。
备注:由于标记化信息存储到分布式数据库,为了提供统一规则方便分库分表配置,需要将账号后3位追加到标记信息后面。
3.2 标记查找服务
请求方需要将标记信息转为账户信息进行后续处理时会发送标记查找请求给TSP,TSP根据标记信息和机构号来确定唯一一条标记信息记录返回给请求方账户信息。
输入要素:需要上送应用方的标记信息。
输出结果:返回账户信息(包含账号,户名,手机号,身份 证号等)。
4.项目架构
4.1 总体设计
TSP服务系统采用分布式服务架构保证高可用和业务连续性;使用Docker技术支持弹性扩容来满足高并发处理需求,并且在进行服务节点扩充时可以不间断服务;通过缓存等技术手段保证数据快速读写,提升响应速度。
目前响应时间要求为收到标记化和去标记化请求后,50毫秒内返回。并发需求分为两方面,一方面是标记生成并发数,另外一方面是标记查找并发数。根据每日签约和支付的交易评估比例约为1:50。
(1) 标记生成TPS=600
(2) 标记查找TPS=30000
4.2 逻辑设计
TSP服务系统采用微服务架构,由注册中心(ZooKeeper)统一进行管理,服务消费方从网关平台中接收应用或者机构的请求,然后转发给服务提供方。TSP服务需要连接数据库以及Redis,TSP服务将Token和卡号信息存到MySQL数据库中;Redis会自动从数据库中加载被频繁访问的数据,以便加快数据库相关操作的检索速度。
在这里需要注意的是TSP服务的调用方式有两种,一种是由系统内部其他服务调用TSP服务,也可以理解为是服务编排内的操作。还有一种是由外部直接调用的方式,使用HTTP协议进行通讯,使用与TSP系统内部兼容的Json报文格式,以直接访问服务的方式,进行TSP操作。这两种方式中前者应该为TSP服务调用的主要手段,后者则为分布式服务增加了易用性。
4.3 分布式应用架构
TSP服务系统使用分布式服务框架Dubbo,该框架在运行的时候提供包括:服务注册、服务发布、服务发现、服务路由等诸多功能。
注册中心负责服务地址的注册与查找,相当于目录服务。服务消费者通过注册中心可以查询到服务提供者相关的地址信息。TSP功能的实现人员,将外部所需功能接口包装成若干个dubbo服务并作为服务的提供方注册到ZooKeeper(注册中心)。整个TSP服务可支持多租户,为不同服务消费者分配机构号,供服务消费者调用。
Redis主要存储MySQL数据库中访问频率较高的数据,通过算法我们可以实现将高频存储数据从数据库中缓存至缓存中心,在接收到去标记服务时先选择从缓存中心进行查询,若查询不到相关结果再到数据库中查找,同时运行独立的服务,将数据库与缓存中心的数据保持同步。
5.Redis使用
5.1 缓存机制
生成缓存:通过对标记业务的分析,有相当多的场景绑定支付,也就是在标记生成(用户签约)后立刻使用标记查找(支付),所以在TSP接收到标记生成请求后将标记信息同时存储到数据库和缓存中心,优先写入缓存中心,之后异步记录到数据库中。
查询缓存:TSP接收到查询请求时先查找缓存中心,如果没有查到数据则查询数据库,并将查询到的数据同步到缓存中心。
5.2 超期时间
目前,标记信息缓存至缓存中心后设置超期时间为15天。在每次查找标记信息后调用Redis续期将超期时间重置。在业务发展、标记信息不断增加的过程中,可适当缩短超期时间。
5.3 安装部署
5.3.1 安装软件准备
redis-3.2.9
ruby-2.4.0
redis-3.2.1.gem
5.3.2 环境检查
安装之前运行yum源命令安装redis依赖包,如果不能正常安装依赖包,需要使用源码安装,这样会非常麻烦.
Redis依赖包安装命令:
yum -y install cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make gcc-c++ libstdc++-devel tcl zlib-devel
5.3.3 Redis单机安装
注意:安装时使用root用户安装,实际生产环境中请新建用户(redis或者cache等)进行管理。
安装redis依赖包,最好使用yum命令安装
yum -y install cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make gcc-c++ libstdc++-devel tcl zlib-devel
上传redis安装包到一个文件目录,解压安装包
tar –xzvf redis-3.2.9.tar.gz
进入解压的redis-3.2.9目录执行安装命令make和make install
编译
make
安装
make install
安装完成之后进入src目录,复制redis-trip.rb文件到/usr/local/bin
cp redis-trib.rb /usr/local/bin
新建redis用户,之后使用redis用户管理redis服务, 新建用户: useradd -d /home/redis -m redis 修改密码: passwd redis 切换redis用户 su redis
5.3.4 Redis配置
以下操作使用redis 用户操作
新建配置文件目录
mkdir -p /home/redis/standalone
复制配置文件到新建目录中,并配置。
拷贝配置文件
cp /opt/redis/redis-3.2.9/redis.conf /home/redis/standalone
修改配置文件
vi /home/redis/standalone/redis.conf
修改内容如下:
端口号:
port 6379(默认)
IP绑定,修改为服务器的ip:
bind 172.31.87.1
备份文件目录:
dir /home/redis/standalone/
配置后台启动
daemonize yes
修改进程号文件
pidfile /home/redis/standalone/redis.pid
修改日志文件路径
logfile "/home/redis/standalone/redis.log"
保存并退出
单机安装校验
使用redis用户校验,启动redis服务,并查看redis进程
cd /home/redis/standalone
指定redis配置文件
redis-server redis.conf
查看redis进程
ps -ef|grep redis-server
连接客户端测试,连接redis
redis-cli -h 192.168.88.135 -p 6379(实际地址以生产为准)
存值
set key1 value1
取值
get key1
测试ok后关闭redis进程,redis集群不需要单独的节点。
pkill -9 redis-server
5.3.5 集群安装
前提条件
• 集群安装需要redis3.0+的版本支持
• 每台服务器上完成单机安装
• redis3.x集群需要ruby环境支持,需要安装ruby环境
物理环境
安装redis集群共使用了三台物理机,具体资源情况如下
操作系统版本
CPU | 内存 | 存储 | |
Redhat7.4 | 8C | 64G | 华为 |
集群规划图如下:
集群配置文件修改
切换redis用户,创建两个节点目录。
mkdir -p /home/redis/cluster/6379
mkdir -p /home/redis/cluster/6479
复制/home/redis/standalone目录下的redis.conf到6379节点目录下
编辑刚复制的redis.conf 文件
编辑以下配置文件内容,修改进程号文件,以端口号区分
pidfile /home/redis/cluster/6379/redis.pid
修改日志文件存放目录
logfile “/home/redis/cluster/6379/redis.log”
开启集群
cluster-enabled yes
指定集群的配置文件
cluster-config-file "/home/redis/cluster/6379/nodes.conf"
集群中节点挂了,不影响整个集群,可以正常访问其他节点的数据
cluster-require-full-coverage no
此配置表示后台启动
daemonize yes
端口号:
port 6379(默认)
IP绑定,修改为自己服务器的ip:
bind 172.31.87.1
备份文件目录:
dir /home/redis/cluster/6379/
配置文件修改完成之后把刚修改的redis.conf文件复制到各个节点目录下,然后修改各节点目录下配置文件的中的ip bind属性和端口号port属性
安装Ruby
• 选取一台服务器安装ruby用来创建redis集群
• 使用root权限安装
• 上传ruby-2.4.0.tar.gz到服务器,并解压
• 解压ruby安装包
• tar xf ruby-2.4.0-tar.gz
• 运行./configure执行安装配置和检测安装环境
• ./configure
编译和安装
编译
make
安装
make install
安装redis-3.2.1.gem
gem install –-local redis-3.2.1.gem
各节点启动
分别启动三台服务器上的六个节点
redis-server 6379/redis.conf
redis-server 6479/redis.conf
三台服务器6个节点都开启后检查个节点开启状态,每个服务器会显示两个节点
ps –ef|grep redis-server
创建集群
在安装ruby的服务器上执行创建命令,参数是对应的节点信息:
redis-trib.rb create --replicas 1 172.31.87.1:6379 172.31.87.1:6479 172.31.87.2:6379 172.31.87.2:6479 172.31.87.3:6379 172.31.87.3:6479
开始创建集群,期间会让你输入yes或no 输入yes
创建集群成功
5.3.6 Redis集群优化
maxmemory选项
不要让Redis所在机器物理内存使用超过实际内存总量的3/5。
配置redis.conf中的maxmemory选项 配置标准为物理内存的40%。
如果一台服务器上分主从两个节点就分别配置20%。如下选项:
(以生产环境分配为200G内存为准)
maxmemory 5100000000
设置内存淘汰机制
allkeys-lru: 优先删除掉最近最不经常使用的key,用以保存新数据
maxmemory-policy allkeys-lru
备份
因tsp系统Redis中数据无需持久化,为保证系统效率并未开启备份策略。
开启TCP连接快速回收
开启TCP连接中TIME-WAIT sockets的快速回收,有助于快速释放TCP连接
修改/etc/sysctl.conf文件修改下面的参数,如果没有请新增此参数
net.ipv4.tcp_tw_recycle=1
修改open files参数
#临时生效,重启后,参数又会被还原
ulimit -n 65536
#永久生效
#修改/etc/security/limits.conf文件
* soft nofile 65536
* hard nofile 65536
注意:**重启服务器此参数才能生效**。
其他优化内容
#修改vi /etc/rc.local
#添加如下内容:
echo 1 > /proc/sys/vm/overcommit_memory
echo 8192 > /proc/sys/net/core/somaxconn
echo never > /sys/kernel/mm/transparent_hugepage/enabled
5.3.7 Redis集群验证
数据存储验证
连接redis,使用set和get来存储和获取数据,注意存储节点信息
连接redis:
redis-cli –c –h 172.31.87.1(实际地址为生产为准)
存值
set key value
取值
get key
三个主节点都有相应说明创建集群成功
集群信息查询
通过命令查询redis集群节点信息:
redis-cli –c –h 172.31.87.1 cluster nodes
字段含义:
myself:您正在联系的节点。
master:节点是主节点。
slave:节点是从节点。
fail?:节点从属关系无法调整,无法连接,此时需要重启节点
fail:节点处于FAIL状态。无法连接的节点
我们只需要关心集群节点从属关系,和集群运行状态,首先看下主节点和从节点的快速识别:
节点信息为IP:127.0.0.1 端口30004 ,slave为从节点,后面跟的一个长的字段时它所对应的主节点的id号,我们找下
可以看到从节点30001对应的主节点时30004。当主节点宕机超过一个节点时,集群就无法正常提供服务。
特别注意:因为三个主节点不能同时宕机两个或两个以上,所以一台服务器上不能同时拥有两个主节点。
因为当这台服务器宕机时,集群服务将无法正常提供。
6. 附录一(Redis备份方式详解)
快照备份方式:RDB 是一个非常紧凑(compact)的文件,它保存了Redis在某个时间点上的数据集。 这种文件非常
适合用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份一次RDB文件,并且在每个月的每一天,也备份一个RDB文件。这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。RDB非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心。RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。RDB 在恢复大数据集时的速度比较快。
追加文件备份方式:使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的 fsync 策略,比如无 fsync,每秒钟一次 fsync,或者每次执行写入命令时 fsync。AOF的默认策略为每秒钟 fsync一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,所以主线程可以继续努力地处理命令请求)。AOF 文件是一个只进行追加操作的日志文件(append only log),因此对AOF文件的写入不需要进行seek,即使日志因为某些原因而包含了未写入完整的命令(比如写入时磁盘已满,写入中途停机,等等),redis-check-aof工具也可以轻易地修复这种问题。
Redis 可以在AO文件体积变得过大时,自动地在后台对 AOF 进行重写:重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合。整个重写操作是绝对安全的,因为 Redis 在创建新AOF文件的过程中,会继续将命令追加到现有的AOF文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。而一旦新 AOF文件创建完毕,Redis 就会从旧 AOF 文件切换到新AOF文件,并开始对新 AOF 文件进行追加操作。AOF 文件有序地保存了对数据库执行的所有写入操作,这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂,对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子,如果你不小心执行了FLUSHALL 命令,但只要 AOF 文件未被重写,那么只要停止服务器,移除 AOF 文件末尾的 FLUSHALL命令,并重启Redis,就可以将数据集恢复到FLUSHALL执行之前的状态。
1.Redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中。
2.RDB 持久化适合大规模的数据恢复但它的数据一致性和完整性较差。
3.Redis 需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中。
4.AOF 的数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率。
5.Redis 针对 AOF文件大的问题,提供重写的瘦身机制。
6.若只打算用Redis 做缓存,可以关闭持久化。
7.若打算使用Redis 的持久化。建议RDB和AOF都开启。其实RDB更适合做数据的备份,留一后手。AOF出问题了,还有RDB。
8. 默认情况下Redis没有开启AOF(append only file)方式的持久化,可以在redis.conf中通过appendonly参数开启:
appendonly yes
9. 配置redis自动重写AOF文件的条件:
当目前的AOF文件大小超过上一次重写时的AOF文件大小的百分之多少时会再次进行重写,如果之前没有重写过,则以启动时的AOF文件大小为依据
auto-aof-rewrite-percentage 100
允许重写的最小AOF文件大小
auto-aof-rewrite-min-size 64mb
7. 附录二(Redis配置文件详解)
本文作者:姜文浩,从事银行业务系统开发运维多年,前期偏向于传统的业务中间件、消息中间件以及SOA、ESB架构,近期逐渐转向于分布式架构以及开源中间件、NoSQL 数据库等,在系统优化、系统架构方面有着一定经验。
社区“Redis”主题下,有精品文章、资料和大量问答,您可以点击阅读原文,或前往如下地址浏览:
http://www.talkwithtrend.com/Topic/91/blog
高分资料,欢迎阅读下载:
新浪Redis运维实践
http://www.talkwithtrend.com/Document/detail/tid/231941
长按二维码关注公众号