1"use strict";(self.webpackChunkengula_website=self.webpackChunkengula_website||[]).push([["9213"],{9746:function(e,n,i){i.r(n),i.d(n,{default:()=>l});var r=i(2676),s=i(453);function t(e){let n=Object.assign({h1:"h1",a:"a",p:"p",strong:"strong",hr:"hr",h2:"h2",ul:"ul",li:"li",code:"code",pre:"pre",ol:"ol",blockquote:"blockquote",table:"table",thead:"thead",tr:"tr",th:"th",tbody:"tbody",td:"td"},(0,s.ah)(),e.components);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.h1,{id:"redis-72--engula-migration",children:["Redis 7.2 â Engula migration",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#redis-72--engula-migration",children:"#"})]}),"\n",(0,r.jsxs)(n.p,{children:["Step 2 of the migration â the engine migration. Engula is a drop-in for Redis 7.2 and the two ",(0,r.jsx)(n.strong,{children:"can replicate to each other"}),", so it reuses the same rolling-failover mechanism as Step 1; client code needs no changes and rollback is cleaner."]}),"\n",(0,r.jsxs)(n.p,{children:["The main flow uses ",(0,r.jsx)(n.strong,{children:"standalone master/replica"}),"; ",(0,r.jsx)(n.strong,{children:"Redis Cluster"})," differences are in the supplement at the end."]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.h2,{id:"applicability--prerequisites",children:["Applicability & prerequisites",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#applicability--prerequisites",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Prerequisite: the source is already Redis 7.2 (if still on 6.x, do ",(0,r.jsx)(n.a,{href:"/en/docs/migration/upgrade-6-to-7",children:"Step 1"})," first)."]}),"\n",(0,r.jsxs)(n.li,{children:["Engula matches Redis 7.2 in protocol / commands / replication / RDB and ",(0,r.jsx)(n.strong,{children:"can act as master or replica in both directions"})," â the basis for both this step and its rollback."]}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.h2,{id:"before-the-migration",children:["Before the migration",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#before-the-migration",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Config alignment"}),": keep Engula and the source Redis consistent on ",(0,r.jsx)(n.code,{children:"maxmemory"})," and eviction policy, persistence, auth, connections / timeouts, TLS, etc."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Compatibility spot-check"}),": though it is a drop-in, still extract high-frequency / critical usage from real command logs and spot-check behavior on the Engula replica (return values, TTL semantics, pipeline / transaction boundaries)."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Backup & baseline"}),": run one ",(0,r.jsx)(n.code,{children:"BGSAVE"})," on the source; record latency / memory baselines to compare gains after migration."]}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.h2,{id:"migration-flow-main-standalone-masterreplica",children:["Migration flow (main: standalone master/replica)",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#migration-flow-main-standalone-masterreplica",children:"#"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"â Add Engula replica Engula replicates from the Redis 7.2 master; catch up\nâ¡ Verify Catch-up + sample consistency + key command behavior\n⢠(optional) load test / compare latency / memory on real workload\n⣠Failover to Engula Pause writes â wait Engula to catch up offset â promote Engula â repoint clients\n⤠Soak Keep the Redis node as an Engula replica (duration up to you); monitor + observe gains\n⥠Wrap up Retire the Redis node\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Key actions (example commands, adjust per environment)"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Add replica: on Engula, ",(0,r.jsx)(n.code,{children:"REPLICAOF <redis-master-ip> <port>"})," (set ",(0,r.jsx)(n.code,{children:"masterauth"})," if needed); wait for initial sync."]}),"\n",(0,r.jsxs)(n.li,{children:["Catch-up check: ",(0,r.jsx)(n.code,{children:"INFO replication"})," shows ",(0,r.jsx)(n.code,{children:"master_link_status:up"}),", offset aligned; sample-compare Key + Value + TTL."]}),"\n",(0,r.jsxs)(n.li,{children:["Failover (establish a consistency point, then promote):","\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["On the old master (Redis 7.2), ",(0,r.jsx)(n.code,{children:"CLIENT PAUSE WRITE <ms>"})," to briefly pause writes."]}),"\n",(0,r.jsxs)(n.li,{children:["Record the old master's ",(0,r.jsx)(n.code,{children:"master_repl_offset"})," from ",(0,r.jsx)(n.code,{children:"INFO replication"}),"."]}),"\n",(0,r.jsx)(n.li,{children:"Wait for the Engula replica's offset to reach that value."}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"REPLICAOF NO ONE"})," on Engula to promote it."]}),"\n",(0,r.jsx)(n.li,{children:"Repoint clients to Engula."}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Blue-green retention"}),": after failover, point the original Redis node at Engula with ",(0,r.jsx)(n.code,{children:"REPLICAOF <engula-master>"})," so it follows Engula as a warm standby â since replication is bidirectional, Redis follows Engula normally and rollback can be lossless."]}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.h2,{id:"redis-cluster-supplement",children:["Redis Cluster supplement",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#redis-cluster-supplement",children:"#"})]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:['Cluster can reuse the "per-shard add replica, c
1atch up, manual failover" idea, but ',(0,r.jsx)(n.strong,{children:"a separate dry run before production is recommended"})," â do not extrapolate single-instance results to Cluster."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Same core flow; the differences are commands and cutover:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Add replica"}),": Engula node ",(0,r.jsx)(n.code,{children:"CLUSTER MEET"})," to join, then ",(0,r.jsx)(n.code,{children:"CLUSTER REPLICATE <master-node-id>"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Failover"}),": on the target Engula replica, ",(0,r.jsx)(n.code,{children:"CLUSTER FAILOVER"}),", ",(0,r.jsx)(n.strong,{children:"one shard at a time"})," (verify ",(0,r.jsx)(n.code,{children:"cluster_state:ok"}),", ",(0,r.jsx)(n.code,{children:"role:master"})," before the next). ",(0,r.jsx)(n.code,{children:"CLUSTER FAILOVER"})," already pauses the primary, ships the offset, and waits for the replica to catch up before completing, so you ",(0,r.jsx)(n.strong,{children:"don't"})," add a bare ",(0,r.jsx)(n.code,{children:"CLIENT PAUSE"}),"; by default ",(0,r.jsx)(n.strong,{children:"do not use"})," ",(0,r.jsx)(n.code,{children:"FORCE"})," / ",(0,r.jsx)(n.code,{children:"TAKEOVER"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Cutover"}),": Cluster clients follow the topology automatically â no manual repointing."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Blue-green retention"}),": keep the Redis node as a replica of the Engula master for that shard, for rollback."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Retirement order"}),": remove Redis replicas first, the Redis master last."]}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.h2,{id:"verification-checkpoints",children:["Verification checkpoints",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#verification-checkpoints",children:"#"})]}),"\n",(0,r.jsxs)(n.table,{children:["\n",(0,r.jsxs)(n.thead,{children:["\n",(0,r.jsxs)(n.tr,{children:["\n",(0,r.jsx)(n.th,{children:"Stage"}),"\n",(0,r.jsx)(n.th,{children:"Check"}),"\n",(0,r.jsx)(n.th,{children:"Pass criteria"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.tbody,{children:["\n",(0,r.jsxs)(n.tr,{children:["\n",(0,r.jsx)(n.td,{children:"After add replica"}),"\n",(0,r.jsx)(n.td,{children:"catch-up"}),"\n",(0,r.jsxs)(n.td,{children:[(0,r.jsx)(n.code,{children:"master_link_status:up"}),", offset aligned"]}),"\n"]}),"\n",(0,r.jsxs)(n.tr,{children:["\n",(0,r.jsx)(n.td,{children:"Before failover"}),"\n",(0,r.jsx)(n.td,{children:"sample consistency, key commands"}),"\n",(0,r.jsx)(n.td,{children:"sampled data matches, key usage behaves as expected"}),"\n"]}),"\n",(0,r.jsxs)(n.tr,{children:["\n",(0,r.jsx)(n.td,{children:"After failover"}),"\n",(0,r.jsx)(n.td,{children:"new master role"}),"\n",(0,r.jsxs)(n.td,{children:["Engula ",(0,r.jsx)(n.code,{children:"role:master"})," (Cluster: ",(0,r.jsx)(n.code,{children:"cluster_state:ok"}),")"]}),"\n"]}),"\n",(0,r.jsxs)(n.tr,{children:["\n",(0,r.jsx)(n.td,{children:"Soak"}),"\n",(0,r.jsx)(n.td,{children:"latency / errors / connections / memory"}),"\n",(0,r.jsx)(n.td,{children:"no regression; memory lower than Redis as expected"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.h2,{id:"rollback",children:["Rollback",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#rollback",children:"#"})]}),"\n",(0,r.jsx)(n.p,{children:"Engula and Redis are bidirectional master/replica, so rollback is cleaner than Step 1:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["During the soak the kept Redis replica follows the Engula master and stays in sync. To roll back, re-promote that Redis node and repoint clients (Cluster: ",(0,r.jsx)(n.code,{children:"CLUSTER FAILOVER"})," back)."]}),"\n",(0,r.jsxs)(n.li,{children:["Because data follows in real time, ",(0,r.jsx)(n.strong,{children:"rollback can be essentially lossless"}),"; for consistency-sensitive workloads still briefly freeze writes at cutover / rollback to get a definite consistency point."]}),"\n",(0,r.jsx)(n.li,{children:"Keep the Redis nodes during the soak â do not rebuild them â so rollback stays available."}),"\n"]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.h2,{id:"after-migration-validate-the-gains",children:["After migration: validate the gains",(0,r.jsx)(n.a,{className:"header-anchor","aria-hidden":"true",href:"#after-migration-validate-the-gains",children:"#"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.a,{href:"/en/proof-live",children:"Live Proof"})})," â compatibility / performance / RDB / memory-efficiency results."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Back to ",(0,r.jsx)(n.a,{href:"/en/docs/migration/overview",children:"Migration overview"})," \xb7 Previous: ",(0,r.jsx)(n.a,{href:"/en/docs/migration/upgrade-6-to-7",children:"Redis 6.x â 7.2"}),"."]})]})}function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}=Object.assign({},(0,s.ah)(),e.components);return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(t,{...e})}):t(e)}let l=a;a.__RSPRESS_PAGE_META={},a.__RSPRESS_PAGE_META["en%2Fdocs%2Fmigration%2Fmigrate-7-to-engula.md"]={toc:[{text:"Applicability & prerequisites",id:"applicability--prerequisites",depth:2},{text:"Before the migration",id:"before-the-migration",depth:2},{text:"Migration flow (main: standalone master/replica)",id:"migration-flow-main-standalone-masterreplica",depth:2},{text:"Redis Cluster supplement",id:"redis-cluster-supplement",depth:2},{text:"Verification checkpoints",id:"verification-checkpoints",depth:2},{text:"Rollback",id:"rollback",depth:2},{text:"After migration: validate the gains",id:"after-migration-validate-the-gains",depth:2}],title:"Redis 7.2 â Engula migration",headingTitle:"Redis 7.2 â Engula migration",frontmatter:{}}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.