LRU (最も最近使用されていない、最も最近使用されていない) アルゴリズムは、履歴アクセスに基づいています。データの記録 データを排除するための中心的な考え方は、「データに最近アクセスされた場合、将来アクセスされる可能性も高い」ということです。
最も一般的な実装は、リンクされたリストを使用してキャッシュされたデータを保存することです。詳細なアルゴリズムは次のように実装されます:
Java では、LinkHashMap を使用して、ハッシュ リンク リストの実装を使用して LRU を実装できます。
Title Redis キャッシュの削除戦略最大キャッシュの設定Redis では、ユーザーは最大メモリ サイズ maxmemory を設定できます。デフォルトは 0 です。最大キャッシュは指定されていません。新しいデータが追加されると、最大メモリを超えると Redis がクラッシュするため、設定する必要があります。redis メモリ データ セットのサイズが特定のサイズに増加すると、データ削除戦略が実装されます。 排除戦略
redis 排除戦略の構成: maxmemory-policy voltile-lru、ホット構成をサポート
redis は 6 種類のデータを提供します削除戦略:
volatile-lru: 有効期限が設定されている、最も最近使用されていないデータ セット (server.db[i].expires) を選択します。データ削除
volatile-ttl:有効期限を設定したデータセット(server.db[i].expires)から期限切れとなるデータを選択します.
volatile-random: 有効期限が設定されているデータセット (server.db[i].expires) から削除するデータをランダムに選択します
allkeys-lru: データ セット (server.db[i].dict) から最も最近使用されていないデータを選択して、
allkeys-random: データ セット (server.db[i].dict) からデータをランダムに選択して、
no-enviction を排除します。 (エビクション): データのエビクションを禁止します
構文:
multi
構文:
exec
構文:
discard
構文:
watch key [key…]
注: このコマンドを使用して、Redis の楽観的ロックを実装します。
UNWATCHトランザクションに対して以前に監視されていたすべてのキーをクリアします構文:
unwatch
コマンドの図:
トランザクションのデモ:
127.0.0.1:6379> multi OK 127.0.0.1:6379> set s1 111 QUEUED 127.0.0.1:6379> hset set1 name zhangsan QUEUED 127.0.0.1:6379> exec 1) OK 2) (integer) 1 127.0.0.1:6379> multi OK 127.0.0.1:6379> set s2 222 QUEUED 127.0.0.1:6379> hset set2 age 20 QUEUED 127.0.0.1:6379> discard OK 127.0.0.1:6379> exec (error) ERR EXEC without MULTI 127.0.0.1:6379> watch s1 OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> set s1 555 QUEUED 127.0.0.1:6379> exec # 此时在没有exec之前,通过另一个命令窗口对监控的s1字段进行修改 (nil) 127.0.0.1:6379> get s1 111
オプティミスティック ロックを実装できます。具体的なアイデアは次のとおりです。
にします
然后去执行这个事务,如果key的值被修改过则回滚,key不加1
public void watch() { try { String watchKeys = "watchKeys"; //初始值 value=1 jedis.set(watchKeys, 1); //监听key为watchKeys的值 jedis.watch(watchkeys); //开启事务 Transaction tx = jedis.multi(); //watchKeys自增加一 tx.incr(watchKeys); //执行事务,如果其他线程对watchKeys中的value进行修改,则该事务将不会执行 //通过redis事务以及watch命令实现乐观锁 List<Object> exec = tx.exec(); if (exec == null) { System.out.println("事务未执行"); } else { System.out.println("事务成功执行,watchKeys的value成功修改"); } } catch (Exception e) { e.printStackTrace(); } finally { jedis.close(); } }
public class RedisLock { public static void main(String[] arg) { //库存key String redisKey = "stock"; ExecutorService executorService = Executors.newFixedThreadPool(20); try { Jedis jedis = new RedisProperties.Jedis("127.0.0.1", 6378); // 可以被秒杀的库存的初始值,库存总共20个 jedis.set(redisKey, "0"); jedis.close(); } catch (Exception e) { e.printStackTrace(); } for (int i = 0; i < 1000; i++) { executorService.execute(() -> { Jedis jedis1 = new Jedis("127.0.0.1", 6378); try { jedis1.watch(redisKey); String redisValue = jedis1.get(redisKey); int valInteger = Integer.valueOf(redisValue); String userInfo = UUID.randomUUID().toString(); // 没有秒完 if (valInteger < 20) { Transaction tx = jedis1.multi(); tx.incr(redisKey); List list = tx.exec(); // 秒成功 失败返回空list而不是空 if (list != null && list.size() > 0) { System.out.println("用户:" + userInfo + ",秒杀成 功!当前成功人数:" + (valInteger + 1)); } // 版本变化,被别人抢了。 else { System.out.println("用户:" + userInfo + ",秒杀失 败"); } } // 秒完了 else { System.out.println("已经有20人秒杀成功,秒杀结束"); } } catch (Exception e) { e.printStackTrace(); } finally { jedis1.close(); } }); } executorService.shutdown(); } }
以上がRedis キャッシュ削除戦略とトランザクションを使用して楽観的ロックを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。