redis的数据安全与性能保障

快照持久化方式:可以将存在于某一时刻的所有数据都写入硬盘里面。
只追加文件:(append-only file,AOF),它会在执行写命令时,将被执行的写命令复制到硬盘里面。


redis.conf参数配置:
save 900 1, 900秒内有一次写入,存入快照
save 300 10
,300秒内有10次写入,存入快照
save 60 10000,60秒内有10000此写入,存入快照
同步机制(快照持久化):
appendfsync always:每个Redis写命令都要同步写入硬盘
,比较影响性能
appendfsync everysec:每秒执行一次同步,显式地将多个写命令同步到硬盘
(推荐)
appendfsync no:让操作系统来决定应该何时进行同步,有不确定性
AOF持久化:
auto-aof-rewrite-percentage 100


auto-aof-rewrite-min-size 64mb
就是当AOF文件的体积大雨64MB,并且AOF文件的体积比上一次重写之后的体积大了一倍(100%)的时候,Redis会对AOF文件执行重写操作,整理AOF文件。


主从服务器:
如果用户在启动Redis服务器的时候,指定了一个包含slaveof host port选项的配置文件,那么Redis服务器将根据该选项给定的IP地址和端口来连接主服务器。
jedis.info()可以查询到大量与服务器相关的讯息。


关于redis的文章,网络上大多介绍的不是特别全面,简明易懂,下面是一个游戏平台商品交易市场,用redis实现的例子,里面充分用到了redis的事务特性,并对每行代码做出了详细解释:
/**
     * 用户将商品放入市场的过程
     * @param jedis
     * @param itemid
     * @param sellerid
     * @param price
     * @return
     */
    private boolean listItem(Jedis jedis, String itemid, String sellerid, double price) {
        String inventory = "inventory:" + sellerid;
        String item = itemid + "." + sellerid;
        long end = System.currentTimeMillis() + 5000;

        while (System.currentTimeMillis() < end) {
            //监护用户包裹发生的变化,此处用了watch的乐观锁,watch之后其他线程都不可修改包裹信息
            jedis.watch(inventory);
            //如果指定的商品不在用户包裹里面,那么停止监控并返回false
            if (!jedis.sismember(inventory, itemid)) {
                jedis.unwatch();
                return false;
            }
            //从jedis.multi()到trans.exec(),这是一个redis事务,redis事务可以一次性提交其中的所有命令,避免了分步提交
            //数据的不一致性,同时减少了与redis连接的次数,缩短时间。
            Transaction trans = jedis.multi();
            //把商品添加到商品市场,并移除包裹中商品。
            trans.zadd("market:", price, item);
            trans.srem(inventory, itemid);
            //若因为watch的乐观锁返回失败,则继续重试。
            List<Object> results = trans.exec();
            if (results == null){
                continue;
            }
            return true;
        }
        return false;
    }

    /**
     * 用户从市场购买商品
     * @param jedis
     * @param buyerid
     * @param itemid
     * @param sellerid
     * @param lprice
     * @return
     */
    private boolean purchaseItem(Jedis jedis, String buyerid, String itemid, String sellerid, double lprice) {

        String buyer = "users:" + buyerid;
        String seller = "users:" + sellerid;
        String item = itemid + "." + sellerid;
        String inventory = "inventory:" + buyerid;
        long end = System.currentTimeMillis() + 10000;
        while (System.currentTimeMillis() < end) {
            //此处从市场拿走了商品,从买家拿走了钱,所以两者状态要同时watch
            try {
                jedis.watch("market:", buyer);
                Set<Tuple> tuples = jedis.zrangeWithScores("market:", 0, -1);
                System.out.println("The market PurchaseItem liuzhe contains:");
                for (Tuple tuple : tuples) {
                    System.out.println("  " + tuple.getElement() + ", " + tuple.getScore());
                }

                System.out.println("jedis.name():" + jedis);

                double price = jedis.zscore("market:", item);
                int funds = Integer.parseInt(jedis.hget(buyer, "funds"));
                //检查商品价格是否变化,以及买家是否有钱购买
                if (price != lprice || price > funds) {
                    jedis.unwatch();
                    return false;
                }
                Transaction trans = jedis.multi();
                //先将买家钱给卖家,在将市场商品给买家
                trans.hincrBy(seller, "funds", (long) price);
                trans.hincrBy(buyer, "funds", (long) (-price));
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                trans.sadd(inventory, itemid);
                trans.zrem("market:", item);
                List<Object> results = trans.exec();
                //如果有人正在修改,watch的乐观锁会返回空数据,重试。
                if (results == null) {
                    System.out.println("purchaseItem results null continue!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                    continue;
                }
                return true;
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
        return false;
    }
    /**
     * redis中提供了pipelline参数,可以让用户在不用封装mutil()与exec()的时候,将命令一次请求,即非事务型
     * 一次性连接redis进行处理。
     * @param jedis
     * @param token
     * @param user
     * @param item
     */
    private void updateTokenPipeline(Jedis jedis, String token, String user, String item) {
        long timestamp = System.currentTimeMillis();
        Pipeline pipe = jedis.pipelined();
        pipe.hset("login:", token, user);
        pipe.zadd("recent:", timestamp, token);
        if (item != null) {
            pipe.zadd("viewed:", timestamp, token);
            pipe.zremrangeByRank("viewed:" + token, 0, -26);
            pipe.zincrby("viewed:", -1, item);
        }
        pipe.exec();
    }
关于redis的安全以及事务性,在这里就基本介绍完毕,redis其性能非常高,但也不该乱用,应该用在合适的地方。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值